在后台运行的更新服务

SMD*_*SMD 5 android android-intent android-service android-broadcast

我需要实现这样一个程序:

  1. 启动后台服务
  2. 使用参数更新服务(来自 UI - 用户输入)
  3. 活动结束后,该服务应继续运行并每分钟向 HTTP 服务器发送请求。在这个阶段我仍然需要我在第二阶段更新的参数 - 我将它们发送到服务器。
  4. 该服务应存储服务器最后的响应并与最后一个进行比较。如果有变化,通知用户。
  5. 最后,当活动再次启动时,服务应该使用最新的服务器响应更新 UI。

我尝试过的:BroadcastReciver - 问题是在 onRecive 结束后,所有未声明为 final 的参数都会消失,而且我没有找到一种方法来更新每分钟自动发送的 Intent。

服务 - 使用 startService() - 问题是当活动结束服务时,如停止和启动,刷新它的所有参数。再一次,我不知道如何在服务启动后更新参数。

那么如何处理这样的情况呢?

谢谢。

SMD*_*SMD 2

谢谢javaJoe,虽然你的回答没有解决我的问题,但给了我一些好主意。

我做了什么:

  1. 在 Activity onCreate 中,检查我的服务是否正在运行,如果正在运行,则将其绑定,否则创建新服务并绑定它。

  2. 使用 setter 和 getter 在服务和活动之间传输参数。

  3. 在 Activity onDestroy 中(问题是服务调用 self Destory),Activity 通过 Intent 将最终参数发送到 Broadcastreciver。然后,广播接收器再次启动服务,并使用正确的参数启动它。

我不知道这个架构是否理想,我想得到一些反馈。

这是代码:

活动:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Set Service Intent
    serviceIntent = new Intent(this, UpdateService.class);
    if (isMyServiceRunning()) {
        //Bind to the service
        bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    }else{
        updateService=new UpdateService();
        //Start the service
        startService(serviceIntent);
        //Bind to the service
        bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    }
}

private boolean isMyServiceRunning() {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (UpdateService.class.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        updateService = ((UpdateService.MyBinder) service).getService();
        //Set Initial Args
        updateService.setParams(int arg0);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        updateService = null;
    }
};

@Override
protected void onDestroy() {
    //UnBind from service
    unbindService(serviceConnection);
    //Stop Service
    stopService(serviceIntent);
    //Prepare intent to broadcast reciver
    Intent intent = new Intent(MainActivity.this,ServiceRunnerBCR.class);
    intent.setAction(ServiceRunnerBCR.ACTION_SET_UpdateService);
    intent.putExtra(ServiceRunnerBCR.keyVal_arg0, arg0);
    intent.putExtra(ServiceRunnerBCR.keyVal_arg1, arg1);
    //Send broadcast to start UpdateService after the activity ended
    sendBroadcast(intent);

    super.onStop();
}
Run Code Online (Sandbox Code Playgroud)

广播接收器:

public class ServiceRunnerBCR extends BroadcastReceiver {


    public static final String ACTION_SET_UpdateService = "ACTION_ALARM";

    public static final String keyVal_arg0="ARG0";
    public static final String keyVal_arg1="ARG1";


    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ACTION_SET_UpdateService)){   
             updateIntent(context, intent.getDoubleExtra(keyVal_arg0, 0.02), intent.getStringExtra(keyVal_arg1));
        }
    }

    private void updateIntent(Context context, double arg0, String arg1){
        Intent intent = new Intent(context,UpdateService.class);
        intent.setAction(ACTION_SET_UpdateService);
        intent.putExtra(keyVal_arg0, arg0);
        intent.putExtra(keyVal_arg1, arg1);
        synchronized (this){
            try {
                this.wait(6000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        context.startService(intent);
        Log.d("OREN","ServiceRunner");
    }
}
Run Code Online (Sandbox Code Playgroud)

服务:

public class UpdateService extends Service {

    private final IBinder binder = new MyBinder();
    public static final String keyVal_arg0="ARG0";
        public static final String keyVal_arg1="ARG1";
    private Timer timer;
    private HTTPHandler http = new HTTPHandler();
    private int test=0;
    double arg0=0;
    String arg1= "";

    private TimerTask updateTask = new TimerTask() {
        @Override
        public void run() {
            test++;
            Log.d("OREN", "Timer task doing work " + test + " arg0: " + arg0);
                        //Do some work here
        }
    };


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent!=null){
            arg0=intent.getDoubleExtra(keyVal_arg0, 0.002);
                        arg1=intent.getStringExtra(keyVal_arg1);
            timer = new Timer("UpdateTimer");
            timer.schedule(updateTask, 1000L, 10 * 1000L);
            Log.d("OREN", "ServiceStarted" + test);
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("OREN", "OnBind" + test);
        return binder;
    }

    public void setArg0(double d){
        arg0=d;
    }

    // create an inner Binder class
    public class MyBinder extends Binder {
        public UpdateService getService() {
            return UpdateService.this;
        }
    }

    @Override
    public void onDestroy() {
        Log.d("OREN", "OnDestroy" + test);
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("OREN", "OnUnBind" + test);
        return super.onUnbind(intent);
    }
}
Run Code Online (Sandbox Code Playgroud)