如何从Android前台服务向Activity发送数据?

huangapple go评论72阅读模式
英文:

How to Send Data to the Activity from a Foreground Service in Android?

问题

我需要找到一种方法,从前台服务发送数据到主活动。
我正在考虑在前台服务中使用一个接口来实现这个目的,并寻求关于其实现的建议。
向活动发送数据有时可能每隔几秒钟连续发生。
你认为什么是最好和最高效的解决方案?

已尝试的解决方案:

  1. 创建静态变量和方法:可能导致全局状态问题和内存泄漏。
  2. 创建绑定服务(最适合双向通信):对后台服务运行的影响不确定。
  3. 使用意图发送数据到服务:可能不适用于频繁更新。
  4. 使用广播接收器:不适用于频繁和大容量通信。
英文:

I need to find a way to send data from the foreground service to the main activity.
I'm considering using an interface in the foreground service for this purpose and seeking advice on its implementation.
Sending data to the activity can sometimes occur every few seconds and consecutively.
What do you think is the best and most efficient solution?

Solutions tried:

  1. Create Static Variables and Methods: May lead to global state issues and memory leaks.
  2. Create a Bound Service (Best for Two-way Communication): Uncertainty about its impact on background service running.
  3. Use Intent to Send Data to Service: May not be optimal for frequent updates.
  4. Use Broadcast Receiver: Not reliable for frequent and high-volume communication.

答案1

得分: 0

最好的方法是使用一个接口。定义一个名为DataUpdateListener的接口,并在您的服务中创建一个带有自己的setter的私有字段。

在您的主活动中,使用setter方法实现接口,每当您想要发布数据时,请检查监听器是否不为null,然后将数据传递给它。

public interface DataUpdateListener {
    void onDataUpdated(String data);
}

您需要修改您的服务并添加监听器:

public class YourService extends Service {

    private DataUpdateListener dataUpdateListener;

    // 本地绑定的实例
    private final IBinder binder = new LocalBinder();

    public void setDataUpdateListener(DataUpdateListener listener) {
        this.dataUpdateListener = listener;
    }

    private void sendDataToActivity(String data) {
        if (dataUpdateListener != null) {
            dataUpdateListener.onDataUpdated(data);
        }
    }

    public class LocalBinder extends Binder {
        public YourService getService() {
            return YourService.this;
        }
    }

    // 方法返回本地绑定
    @Override
    public IBinder onBind(@NonNull Intent intent) {
        super.onBind(intent);
        return binder;
    }
}

此外,您需要在您的服务中定义LocalBinder

在您的主活动中实现接口:

public class MainActivity extends AppCompatActivity implements DataUpdateListener {

    @Override
    public void onDataUpdated(String data) {
        // 在这里处理接收到的数据
    }
}

要将接口绑定到您的服务,可以像这样做:

public class MainActivity extends AppCompatActivity implements DataUpdateListener {
    private YourService foregroundService;
    private boolean isServiceBound = false;

    @Override
    protected void onStart() {
        super.onStart();
        Intent serviceIntent = new Intent(this, YourService.class);
        startService(serviceIntent);
        bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (isServiceBound) {
            unbindService(serviceConnection);
            isServiceBound = false;
        }
    }

    private final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            YourService.LocalBinder binder = (YourService.LocalBinder) iBinder;
            foregroundService = binder.getService();
            foregroundService.setDataUpdateListener(MainActivity.this);
            isServiceBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            foregroundService = null;
            isServiceBound = false;
        }
    };
}
英文:

The best approach is to use an interface. Define an interface like DataUpdateListener and create a private field with its own setter in your service.

in your main activity implement the interface using setter method, and whenever you want to publish data check if listener is not null, pass data to it.

public interface DataUpdateListener {
    void onDataUpdated(String data);
}

your need to change your service and add listeners:

public class YourService extends Service {

    private DataUpdateListener dataUpdateListener;

    // Instance of the local binder
    private final IBinder binder = new LocalBinder();

    public void setDataUpdateListener(DataUpdateListener listener) {
        this.dataUpdateListener = listener;
    }

    private void sendDataToActivity(String data) {
        if (dataUpdateListener != null) {
            dataUpdateListener.onDataUpdated(data);
        }
    }

    public class LocalBinder extends Binder {
        public YourService getService() {
            return YourService.this;
        }
    }


// Method to return the local binder
@Override
public IBinder onBind(@NonNull Intent intent) {
    super.onBind(intent);
    return binder;
}

}

also you need to define localbinder in your service:

in your main activity implement interface :

public class MainActivity extends AppCompatActivity implements DataUpdateListener {


    @Override
    public void onDataUpdated(String data) {
        // handle the received data here
    }
}

and for binding interface to your service, you can do it like this:

public class MainActivity extends AppCompatActivity implements DataUpdateListener {
    private YourService foregroundService;
    private boolean isServiceBound = false;


    @Override
    protected void onStart() {
        super.onStart();
        Intent serviceIntent = new Intent(this, YourService.class);
        startService(serviceIntent);
        bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (isServiceBound) {
            unbindService(serviceConnection);
            isServiceBound = false;
        }
    }

    private final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            YourService.LocalBinder binder = (YourService.LocalBinder) iBinder;
            foregroundService = binder.getService();
            foregroundService.setDataUpdateListener(MainActivity.this);
            isServiceBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            foregroundService = null;
            isServiceBound = false;
        }
    };
}

huangapple
  • 本文由 发表于 2023年7月23日 14:26:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76746890.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定