更新在后台运行的服务

时间:2013-07-07 15:57:41

标签: android android-intent android-service android-broadcast

我需要实施这样的程序:

  1. 启动后台服务
  2. 使用参数更新服务(来自用户界面 - 用户输入)
  3. 活动结束后,服务应该每分钟继续运行并向HTTP服务器发出请求。在这个阶段,我仍然需要在第二阶段更新的参数 - 我将它们发送到服务器。
  4. 服务应该存储服务器的最后一个响应,并且每个响应都与最后一个响应。如果有更改,请通知用户。
  5. 最后,当活动再次启动时,服务应使用最新的服务器响应更新UI。
  6. 我尝试了什么: BroadcastReciver - 问题是在onRecive结束后,所有未声明为final的参数将被清除,以及我没有找到更新每分钟自动发送的Intent的方法。

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

    那么如何处理这种情况?

    感谢。

2 个答案:

答案 0 :(得分:3)

听起来你需要做的就是能够“绑定”到你的服务。我在下面发布的是一个如何做到这一点的简单模板。出于您的目的,您需要在Service类中存储变量并创建getter,以便在重新启动活动时可以获得最新的变量。另外 - 请注意我在onResume和onPause中启动和停止下面的服务示例。你无疑会想要以不同的方式做到这一点。

//Activity

//Bind to Service Example

public class ExampleActivity extends Activity implements OnClickListener {

// UI
private Button binderButton;

// service
private MyService myService;
private Intent serviceIntent;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout);

    // binder button
    binderButton = (Button) findViewById(R.id.button1);
    binderButton.setOnClickListener(this);
    binderButton.setText("start");

    serviceIntent = new Intent(this, MyService.class);
}

private ServiceConnection serviceConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        myService = ((MyService.MyBinder) service).getService();
    }

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

@Override
protected void onResume() {
    super.onResume();
    // start the service
    startService(serviceIntent);
    // bind to the service
    bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.button1:
        // call method within the service
        myService.doServiceStuff();
        break;
    }
}

@Override
protected void onPause() {
    super.onPause();
    stopService(serviceIntent);
    unbindService(serviceConnection);
}
}

//Service

public class MyService extends Service {
private final IBinder binder = new MyBinder();

@Override
public IBinder onBind(Intent arg0) {
    return binder;
}

public void doServiceStuff() {
    task.execute();
}

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

AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {

    @Override
    protected Void doInBackground(Void... params) {
        Log.d("yourTag", "long running service task");
        return null;
    }       
};
}

答案 1 :(得分:1)

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

我做了什么:

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

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

  3. 在Activity onDestroy中(问题在于服务调用self Destory)Activity通过Intent将最终参数发送给Broadcastreciver。 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();
    }
    

    Broadcastreciver:

    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");
        }
    }
    

    服务:

    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);
        }
    }