5

我需要实现这样的程序:

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

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

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

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

谢谢。

4

2 回答 2

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;
    }       
};
}
于 2013-07-07T16:15:43.723 回答
2

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

我做了什么:

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

  2. 使用 setter 和 getter 在 Service 和 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();
}

广播接收器:

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);
    }
}
于 2013-07-08T08:32:29.220 回答