Android 더 블 프로 세 스 데 몬 구현 코드

머리말
최근 프로젝트 에 고 덕 을 사용 하 는 포 지 셔 닝 SDK 가 있 는데,일정 시간 마다 사용자 의 지리 적 위 치 를 가 져 오 는 기능 이 있 으 며,배경 에 서 비 스 를 열 어 고 덕 지도의 위치 변 화 를 감청 하 는 방안 을 채택 했다.
이 기능 은 사용자 의 휴대 전화 화면 이 밝 아 졌 을 때 완벽 하 게 실현 되 었 으 나 화면 이 꺼 졌 을 때 위치 정 보 를 얻 을 수 없 었 다.원인 을 조사 한 결과 사용자 의 휴대 전화 화면 이 꺼 진 후에 백 스테이지 의 Service 가 시스템 에 의 해 제거 되 었 기 때문에 기능 이 작 동 하지 않 았 다.즉,프로 세 스 가 죽 었 다 는 것 이다.

프로 세 스 를 죽 이 는 것 은 한편 으로 는 핸드폰 메모리 가 부족 하기 때 문 입 니 다.다른 한편 으로 는 구 글 이 사용자 의 측면 에서 볼 때 백 스테이지 에 상주 하 는 프로그램 을 일정한 알고리즘 을 통 해 관리 하고 시스템 자원 을 과도 하 게 소모 하 는 건달 소프트웨어 를 제거 하여 핸드폰 의 성능 과 지속 을 보장 합 니 다.그러나 어떤 소프트웨어 는 포 지 셔 닝 과 같은 백 스테이지 운행 을 유지 해 야 시스템 에 의 해 죽 는 것 을 피 할 수 있 습 니까?사실 피 살 프로 세 스 를 피 하 는 것 은 어렵 습 니 다.위 챗,QQ,알 리 페 이 같은 시스템 업 체 가 인정 하 는 소프트웨어 가 공식 적 으로 화이트 리스트 에 가입 되 지 않 는 한 피 살 프로 세 스 를 피 할 수 있 습 니 다.그 다른 작은 소프트웨어 는 어떻게 합 니까?우 리 는 다른 길 을 개척 할 수 있 습 니 다.피 살 프로 세 스 를 피 할 수 없습니다.그러면 우리 의 소프트웨어 는 피 살 프로 세 스 후에 자동 으로 재 부팅 할 수 있 습 니 다.
프로 세 스 가 살 해 된 후 끌 어 올 리 는 방법 을 소개 합 니 다.
두 프로 세 스 데 몬

두 프로 세 스 를 지 키 는 사상 은 두 프로 세 스 가 공동으로 실행 되 는 것 입 니 다.만약 에 한 프로 세 스 가 죽 으 면 다른 프로 세 스 는 살 해 된 프로 세 스 를 다시 끌 어 올 리 고 서로 보호 하 며 일정한 의미 에서 프로 세 스 의 끊 임 없 는 운행 을 유지 합 니 다.
두 프로 세 스 가 지 키 는 두 프로 세 스 입 니 다.한 프로 세 스 는 우리 가 필요 로 하 는 배경 작업 에 사용 되 고 로 컬 프로 세 스 라 고 부 릅 니 다.다른 프로 세 스 는 로 컬 프로 세 스 의 상 태 를 감청 하 는 것 만 담당 합 니 다.로 컬 프로 세 스 가 죽 었 을 때 끌 어 올 리 려 고 합 니 다.이 프로 세 스 를 원 격 프로 세 스 라 고 부 릅 니 다.
Android 에 서 는 두 프로 세 스 간 에 직접 상호작용 을 할 수 없 기 때문에 AIDL(Android interface definition Language)을 사용 하여 두 프로 세 스 간 의 상호작용 을 해 야 합 니 다.
코드 구현
먼저 demo 코드 구 조 를 살 펴 보 겠 습 니 다.구조 가 간단 합 니 다.저 는 Activity 를 인터페이스 로 만 들 었 고 두 개의 Service 를 만 들 었 습 니 다.하 나 는 배경 에서 작 동 하 는 로 컬 Service 이 고 다른 하 나 는 데 몬 의 원 격 Service 이 며 또 하 나 는 AIDL 파일 을 프로 세 스 간 의 상호작용 으로 사용 합 니 다.

프로젝트 구조
Activity 의 정 의 는 매우 간단 합 니 다.몇 개의 버튼 으로 Service 의 상 태 를 제어 합 니 다.저 는 세 개의 단 추 를 정 의 했 습 니 다.하 나 는 배경 서 비 스 를 시작 하 는 것 이 고 다른 두 개 는 로 컬 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 파일 은 업무 상 필요 에 따라 인 터 페 이 스 를 추가 할 수 있 습 니 다.

/**
 * @author chaochaowu
 */
interface IMyAidlInterface {
  String getServiceName();
}
중요 한 것 은 두 서비스 에 있다.
Service 를 정의 할 때 AndroidManifest 에서 원 격 Service 의 process 속성 을 설명 하고 로 컬 Service 와 원 격 Service 두 가지 가 서로 다른 프로 세 스에 서 달 릴 수 있 도록 해 야 합 니 다.같은 프로 세 스에 서 달 려 가면 이 프로 세 스 가 죽 으 면 아무것도 없습니다.더 블 데 몬 이라는 말 이 없습니다.

<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 의 코드 를 살 펴 보고 onStartCommand 방법 과 ServiceConnection 에서 다시 쓰 는 방법 에 중점 을 둡 니 다.onStartCommand 방법 은 Service 가 시 작 된 후에 호출 되 었 습 니 다.LocalService 가 시 작 된 후에 저 희 는 RemoteService 를 시 작 했 고 LocalService 와 RemoteService 두 가 지 를 연결 시 켰 습 니 다.(원 격 서 비 스 는 사용자 에 게 보이 지 않 기 때문에 저희 가 실제 작업 하 는 프로 세 스에 비해 독립 적 이 고 그 역할 은 수호 스 레 드 일 뿐 입 니 다.그래서 RemoteService 는 LocalService 와 만 관련 이 있 고 LocalService 에서 만 시작 할 수 있 을 것 입 니 다).
시작 하고 연결 한 후에 저 희 는 ServiceConnection 의 방법 을 다시 써 야 합 니 다.이들 의 연결 관 계 를 감청 해 야 합 니 다.관건 은 이들 의 연결 관계 가 끊 겼 을 때의 감청 입 니 다.
그 중의 한 프로 세 스 가 죽 었 을 때 이들 의 바 인 딩 관 계 는 끊 어 집 니 다.트리거 방법 인 onServiceDisconnected 를 실행 합 니 다.따라서 우 리 는 끊 었 을 때 프로 세 스 가 끌 어 올 리 는 작업 을 하고 onServiceDisconnected 방법 을 다시 쓰 며 다른 서 비 스 를 다시 시작 하고 두 가 지 를 다시 연결 해 야 합 니 다.

/**
 * @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,"    ,     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   ",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();
    }

  }

}
또 다른 RemoteService 에서 도 마찬가지 로 LocalService 와 링크 를 끊 었 을 때 바 인 딩 이 끊 어 지 는 것 을 감청 한 것 은 RemoteService 가 살아 있 고 LocalService 가 살 해 된 프로 세 스 라 는 것 을 의미 하기 때문에 LocalService 를 끌 어 올 리 고 다시 연결 해 야 합 니 다.방법 은 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,"    ,     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   ",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();
    }

  }
}
실행 효과
Activity 를 시작 하려 면 LocalService 를 클릭 하여 로 컬 서 비 스 를 시작 합 니 다.알림 에서 알 수 있 듯 이 LocalService 가 시작 되면 RemotService 데 몬 스 레 드 도 시 작 됩 니 다.이때,둘 은 이미 한데 묶 였 다.

서비스 시작
LocalService 를 닫 으 면 로 컬 프로 세 스 가 죽 임 을 모 의 합 니 다.Toast 알림 링크 가 끊 기 고 LocalService 를 다시 시작 하려 고 합 니 다.두 번 째 Toast 알림 LocalService 가 다시 시작 되 었 습 니 다.

로 컬 서비스 닫 기
RemoteService 닫 기 를 누 르 면 원 격 프로 세 스 가 죽 임 을 모 의 합 니 다.Toast 알림 링크 가 끊 기 고 RemoteService 를 다시 시작 하려 고 합 니 다.두 번 째 Toast 알림 RemoteService 가 다시 시작 되 었 습 니 다.

원 격 서비스 닫 기
우리 가 프로 세 스 를 어떻게 죽 이 든 프로 세 스 가 다시 끌 어 올 리 는 것 을 발견 할 수 있 습 니 다.이것 은 Service 가 활성화 되 고 두 프로 세 스 가 서로 지 키 는 목적 을 달성 할 수 있 습 니 다.
총결산
개발 과정 에서 피 할 수 없 는 번 거 로 움 이 있 지만 방법 은 어려움 보다 많 으 니 인내심 을 가지 고 연구 하면 된다.프로 세 스 의 보존 에 관 해 서 는 사실 방법 이 없다.우 리 는 프로 세 스 를 백 스테이지 에 상주 시 키 는 것 을 최대한 피해 야 한다.만약 정말 필요 하 다 면 백 스테이지 작업 을 마 친 후에 도 제때에 그들 을 소각 해 야 한다.그렇지 않 으 면 백 스테이지 프로 세 스 가 이유 없 이 시스템 자원 을 소모 하고 사용자 가 모 르 면 우리 의 소프트웨어 도 깡패 소프트웨어 가 된다.개발 자 는 양심 이 있어 야 지,응?
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기