亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android 雙進(jìn)程守護(hù)的實(shí)現(xiàn)代碼

 更新時(shí)間:2018年08月18日 08:43:01   作者:reggie1996  
這篇文章主要介紹了Android 雙進(jìn)程守護(hù)的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

前言

最近有在項(xiàng)目中用到高德的定位SDK,功能是每隔一定的時(shí)間獲取一次用戶的地理位置,采取的方案是在后臺(tái)開啟一個(gè) Service,監(jiān)聽高德地圖的位置變化。

該功能在用戶手機(jī)屏幕亮?xí)r完美實(shí)現(xiàn),但是當(dāng)屏幕被關(guān)閉的時(shí)候,位置信息卻無法被獲取了,經(jīng)過原因的排查,發(fā)現(xiàn)是由于在用戶手機(jī)息屏后,后臺(tái)的 Service 被系統(tǒng)清除,所以功能無法起作用,也就是所謂的進(jìn)程被殺了。

殺進(jìn)程,一方面是因?yàn)槭謾C(jī)內(nèi)存不足,另一方面其實(shí)是 Google 從用戶的方面考慮,把一些常駐后臺(tái)的程序通過一定的算法進(jìn)行管理,將那些過度消耗系統(tǒng)資源的流氓軟件殺除,保證手機(jī)的性能和續(xù)航。但是有的軟件,像定位這類的必須要保持后臺(tái)的運(yùn)行,如何才能避免被系統(tǒng)殺掉呢。其實(shí)避免被殺進(jìn)程很難做到,除非是像微信、QQ、支付寶這類系統(tǒng)廠商認(rèn)可的軟件被官方加入白名單可以避免被殺進(jìn)程。那其他的小軟件怎么辦,我們可以另辟蹊徑,無法避免被殺進(jìn)程,那就讓我們的軟件在被殺進(jìn)程后,能自動(dòng)重啟。

我這里介紹一下雙進(jìn)程守護(hù)的方法,來實(shí)現(xiàn)進(jìn)程被殺后的拉起。

雙進(jìn)程守護(hù)

雙進(jìn)程守護(hù)的思想就是,兩個(gè)進(jìn)程共同運(yùn)行,如果有其中一個(gè)進(jìn)程被殺,那么另一個(gè)進(jìn)程就會(huì)將被殺的進(jìn)程重新拉起,相互保護(hù),在一定的意義上,維持進(jìn)程的不斷運(yùn)行。

雙進(jìn)程守護(hù)的兩個(gè)進(jìn)程,一個(gè)進(jìn)程用于我們所需的后臺(tái)操作,且叫它本地進(jìn)程,另一個(gè)進(jìn)程只負(fù)責(zé)監(jiān)聽著本地進(jìn)程的狀態(tài),在本地進(jìn)程被殺的時(shí)候拉起,于此同時(shí)本地進(jìn)程也在監(jiān)聽著這個(gè)進(jìn)程,準(zhǔn)備在它被殺時(shí)拉起,我們將這個(gè)進(jìn)程稱為遠(yuǎn)端進(jìn)程。

由于在 Android 中,兩個(gè)進(jìn)程之間無法直接交互,所以我們這里還要用到 AIDL (Android interface definition Language ),進(jìn)行兩個(gè)進(jìn)程間的交互。

代碼實(shí)現(xiàn)

先來看一下demo代碼結(jié)構(gòu),結(jié)構(gòu)很簡(jiǎn)單,我這里創(chuàng)建了一個(gè) Activity 作為界面,以及兩個(gè) Service ,一個(gè)是后臺(tái)操作的 本地Service,另一個(gè)是守護(hù)進(jìn)程的 遠(yuǎn)端Service,還有一個(gè) AIDL文件用作進(jìn)程間交互用。

項(xiàng)目結(jié)構(gòu)

Activity 的定義很簡(jiǎn)單,就幾個(gè)按鈕,控制 Service 的狀態(tài),我這邊定義了三個(gè)按鈕,一個(gè)是開啟后臺(tái)服務(wù),另外兩個(gè)分別是關(guān)閉本地Service和遠(yuǎn)端的Service。

/**
 * @author chaochaowu
 */
public class GuardActivity extends AppCompatActivity {

  @BindView(R.id.button)
  Button button;
  @BindView(R.id.button2)
  Button button2;
  @BindView(R.id.button3)
  Button button3;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getSupportActionBar().hide();
    setContentView(R.layout.activity_guard);
    ButterKnife.bind(this);
  }


  @OnClick({R.id.button, R.id.button2, R.id.button3})
  public void onViewClicked(View view) {
    switch (view.getId()) {
      case R.id.button:
        startService(new Intent(this, LocalService.class));
        break;
      case R.id.button2:
        stopService(new Intent(this, LocalService.class));
        break;
      case R.id.button3:
        stopService(new Intent(this, RemoteService.class));
        break;
      default:
        break;
    }
  }
}

可以看一下界面。

主界面

AIDL文件可以根據(jù)業(yè)務(wù)需要添加接口。

/**
 * @author chaochaowu
 */
interface IMyAidlInterface {
  String getServiceName();
}

重點(diǎn)是在兩個(gè) Service 上。

在定義Service時(shí),需要在 AndroidManifest 中聲明一下 遠(yuǎn)端Service 的 process 屬性,保證 本地Service 和 遠(yuǎn)端Service 兩者跑在不同的進(jìn)程上,如果跑在同一個(gè)進(jìn)程上,該進(jìn)程被殺,那就什么都沒了,就沒有了雙進(jìn)程守護(hù)的說法了。

<service
  android:name=".guard.LocalService"
  android:enabled="true"
  android:exported="true" />
<service
  android:name=".guard.RemoteService"
  android:enabled="true"
  android:exported="true"
  android:process=":RemoteProcess"/>

先來看 LocalService 的代碼,重點(diǎn)關(guān)注 onStartCommand 方法 和 ServiceConnection 中重寫的方法。onStartCommand 方法是在 Service 啟動(dòng)后被調(diào)用,在 LocalService 被啟動(dòng)后,我們將 RemoteService 進(jìn)行了啟動(dòng),并將 LocalService 和 RemoteService 兩者綁定了起來(因?yàn)檫h(yuǎn)端Service 對(duì)于用戶來說是不可見的,相對(duì)于我們實(shí)際工作的進(jìn)程也是獨(dú)立的,它的作用僅僅是守護(hù)線程,所以說 RemoteService 僅與 LocalService 有關(guān)系,應(yīng)該只能由 LocalService 將它啟動(dòng))。

啟動(dòng)并綁定之后,我們需要重寫 ServiceConnection 中的方法,監(jiān)聽兩者之間的綁定關(guān)系,關(guān)鍵的是對(duì)兩者綁定關(guān)系斷開時(shí)的監(jiān)聽。

當(dāng)其中一個(gè)進(jìn)程被殺掉時(shí),兩者的綁定關(guān)系就會(huì)被斷開,觸發(fā)方法 onServiceDisconnected ,所以,我們要在斷開時(shí),進(jìn)行進(jìn)程拉起的操作,重寫 onServiceDisconnected 方法,在方法中將另外一個(gè) Service 重新啟動(dòng),并將兩者重新綁定。

/**
 * @author chaochaowu
 */
public class LocalService extends Service {

  private MyBinder mBinder;

  private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
      try {
        Log.i("LocalService", "connected with " + iMyAidlInterface.getServiceName());
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
      Toast.makeText(LocalService.this,"鏈接斷開,重新啟動(dòng) RemoteService",Toast.LENGTH_LONG).show();
      startService(new Intent(LocalService.this,RemoteService.class));
      bindService(new Intent(LocalService.this,RemoteService.class),connection, Context.BIND_IMPORTANT);
    }
  };

  public LocalService() {
  }

  @Override
  public void onCreate() {
    super.onCreate();
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this,"LocalService 啟動(dòng)",Toast.LENGTH_LONG).show();
    startService(new Intent(LocalService.this,RemoteService.class));
    bindService(new Intent(this,RemoteService.class),connection, Context.BIND_IMPORTANT);
    return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
    mBinder = new MyBinder();
    return mBinder;
  }

  private class MyBinder extends IMyAidlInterface.Stub{

    @Override
    public String getServiceName() throws RemoteException {
      return LocalService.class.getName();
    }

  }

}

在另外一個(gè) RemoteService 中也一樣,在與 LocalService 斷開鏈接的時(shí)候,由于監(jiān)聽到綁定的斷開,說明 RemoteService 還存活著,LocalService 被殺進(jìn)程,所以要將 LocalService 進(jìn)行拉起,并重新綁定。方法寫在 onServiceDisconnected 中。

/**
 * @author chaochaowu
 */
public class RemoteService extends Service {

  private MyBinder mBinder;

  private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
      try {
        Log.i("RemoteService", "connected with " + iMyAidlInterface.getServiceName());
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
      Toast.makeText(RemoteService.this,"鏈接斷開,重新啟動(dòng) LocalService",Toast.LENGTH_LONG).show();
      startService(new Intent(RemoteService.this,LocalService.class));
      bindService(new Intent(RemoteService.this,LocalService.class),connection, Context.BIND_IMPORTANT);
    }
  };

  public RemoteService() {
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this,"RemoteService 啟動(dòng)",Toast.LENGTH_LONG).show();
    bindService(new Intent(this,LocalService.class),connection,Context.BIND_IMPORTANT);
    return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
    mBinder = new MyBinder();
    return mBinder;
  }

  private class MyBinder extends IMyAidlInterface.Stub{

    @Override
    public String getServiceName() throws RemoteException {
      return RemoteService.class.getName();
    }

  }
}

運(yùn)行效果

啟動(dòng) Activity 點(diǎn)擊開啟 LocalService 啟動(dòng)本地服務(wù),提示中可以看到, LocalService 啟動(dòng)后 RemotService 守護(hù)線程也被啟動(dòng)。此時(shí),兩者已經(jīng)綁定在了一起。

開啟服務(wù)

點(diǎn)擊關(guān)閉 LocalService 模擬本地進(jìn)程被殺,Toast 提示鏈接斷開,并嘗試重新啟動(dòng) LocalService,第二個(gè)Toast 提示 LocalService 被重新拉起。

關(guān)閉本地服務(wù)

點(diǎn)擊關(guān)閉 RemoteService 模擬遠(yuǎn)端進(jìn)程被殺,Toast 提示鏈接斷開,并嘗試重新啟動(dòng) RemoteService ,第二個(gè)Toast 提示 RemoteService 被重新拉起。

關(guān)閉遠(yuǎn)端服務(wù)

可以發(fā)現(xiàn),無論我們?cè)趺礆⑦M(jìn)程,進(jìn)程都會(huì)被重新拉起,這就達(dá)到了 Service 保活,雙進(jìn)程相互守護(hù)的目的。

總結(jié)

在開發(fā)的過程中總是有些無法避免的麻煩,但是方法總比困難多,耐心研究研究就行了。關(guān)于進(jìn)程的保活,其實(shí)是沒有辦法的辦法,我們應(yīng)該盡量避免將進(jìn)程常駐后臺(tái),如果真的需要,在完成后臺(tái)工作后,也要及時(shí)將他們銷毀。否則后臺(tái)進(jìn)程無端地消耗系統(tǒng)資源,用戶又不知道,咱們的軟件就也就成了流氓軟件。開發(fā)人員應(yīng)該有自己的良心,嗯。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論