2

мне нужно реализовать такую ​​процедуру:служба обновления работает на фоне

  1. Начать фоновую службу
  2. Обновление службы с параметрами (от UI - ввод пользователя)
  3. После деятельность закончилась служба должна каждый раз выполняйте запросы на запуск и преформ на HTTP-сервер. на этом этапе мне все еще нужны параметры, которые я обновил на втором этапе - я отправляю их на сервер.
  4. Служба должна хранить последний ответ сервера и составлять каждый с последним. если есть изменения, уведомите пользователя.
  5. И наконец, когда действие начинается снова, служба должна обновить интерфейс с последним ответом сервера.

Что я пробовал: BroadcastReciver - Проблема после onRecive закончилось все аргументы, которые не объявлены окончательным вытрут, так же как я не нашел способ обновить Intent, посылаемый автоматически каждую минуту.

Служба - Использование startService() - Проблема в том, что активность прекратила службу, например, останавливается и запускается, очищая все ее аргументы. и еще раз я не понял, как обновить аргументы после того, как служба уже запущена.

Как справиться с такой ситуацией?

Спасибо.

+0

это может помочь - http://stackoverflow.com/вопросы/4300291/пример-связи между ними -activity-and-service-using-messaging – coderplus

ответ

1

Благодаря javaJoe, хотя ваш ответ не решить мою проблему, она дала мне некоторые хорошие идеи.

Что я сделал:

  1. в деятельности OnCreate, проверьте, если моя служба работает, если так связать его еще, создать новый и связать его.

  2. Передача аргументов между Сервисом и Деятельностью с использованием сеттеров и геттеров.

  3. в действии 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); 
    } 
} 
+0

Не зная, какая проблема будет решена, я не могу сказать, действительно ли это лучший способ сделать это или нет. Однако я могу сказать пару вещей. 1) Вы вызываете super.onStop() изнутри onDestroy(). Это, несомненно, создаст проблемы. 2), вы вызываете сон (6000) в поток пользовательского интерфейса. Вы также синхронизируете его, что не нужно. Лучше использовать обработчик там, если вам нужна какая-то задержка. Однако эта жесткая задержка может свидетельствовать о необходимости изменения вашей архитектуры. Я бы предложил попытаться избежать этого. :) –

+0

спасибо, я изменил ожидание (6000) до (isMyServiceRunning()). Если я остановлю службу в событии onStop вместо события onDestroy, это не вызовет проблемы? – SMD

+1

Я думаю, оставив его в onDestroy в порядке. Проблема в том, что вы переопределяете onDestroy, но затем вызываете onStop(). Например, это должно быть «public void onDestroy() {super.onDestroy();}». У вас есть "public void onDestroy() {super.onStop();}". Кроме того, похоже, что вы по-прежнему блокируете свой основной поток пользовательского интерфейса «while {(isMyServiceRunning())}». –

2

Звучит так, как будто вам нужно «привязать» к вашему сервису. То, что я опубликовал ниже, является простым шаблоном, как это сделать. Для ваших целей вам нужно будет хранить переменные в вашем классе обслуживания и создавать геттеры, чтобы при повторном запуске вашей деятельности вы могли получить самые последние переменные. Также - обратите внимание, что я запускаю и останавливаю пример сервиса ниже в 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; 
    }  
}; 
} 
+0

Спасибо, но, к сожалению, задача таймера обслуживания по-прежнему останавливается после unBinding. Кстати, может быть, проблема с заданием таймера: 'code' \t частный TimerTask updateTask = новый TimerTask() { \t \t @Override \t \t общественности недействительным запуска() { \t \t \t тест ++; \t \t \t Log.d («OREN», «Задача таймера, выполняющая работу» + тест); \t \t} \t}; \t \t \t общественного недействительный runOnTimer (двойной рад) { \t \t радиус = радиан; \t таймер = новый таймер («UpdateTimer»); \t timer.schedule (updateTask, 1000L, 10 * 1000L); \t \t} 'code' – SMD

+0

Вместо этого попробуйте использовать AlarmManager. Он будет регистрироваться в ОС через ожидающие намерения, поэтому вы будете уверены, что он не остановится, если вы специально не сообщите об этом. –

Смежные вопросы