안 드 로 이 드 시스템 에서 응용 프로그램 앞 배경 전환 의 실현 요점 을 깊이 분석 하 다.

프로그램 이 실현 되 기 전에 안 드 로 이 드 에서 Activities 와 Task 의 기초 지식 을 살 펴 보 자.
하나의 Activity 가 다른 Activity 를 시작 할 수 있다 는 것 을 잘 알 고 있 습 니 다.이 Activity 가 다른 프로그램 에 정의 되 어 있 더 라 도 예 를 들 어 사용자 에 게 지도 정 보 를 보 여 주 려 면 현재 Activity 가 이 일 을 할 수 있 습 니 다.그러면 현재 당신 의 Activity 가 해 야 할 일 은 요청 정 보 를 Intent 대상 에 넣 는 것 입 니 다.또한 이 Intent 대상 을 startActivity()에 전달 하면 지도 가 표 시 됩 니 다.그러나 사용자 가 Back 키 를 누 르 면 Activity 가 다시 화면 에 나타 납 니 다.
사용자 에 게 지 도 를 표시 하 는 Activity 와 당신 의 Activity 는 한 프로그램 에 있 는 것 같 습 니 다.다른 프로그램 에 정의 되 어 있 고 프로 세 스 에서 실행 되 고 있 지만.Android 는 사용자 의 체험 을 유지 하기 위해 Activity 와 빌 린 Activity 를 Task 에 넣 습 니 다.그러면 Task 는 스 택 형식 으로 서로 연 결 된 Activity 를 구성 합 니 다.스 택 의 아래쪽 에 있 는 Activity 는 바로 이 Task 를 개척 하 는 것 입 니 다.보통 사용자 가 응용 프로그램 실행 기 에서 선택 한 Activity 입 니 다.스 택 상단 의 Activity 는 현재 실행 중인 Activity-사용자 가 상호작용 하고 있 는 Activity 입 니 다.
하나의 Activity 가 다른 Activity 를 시작 할 때 새로 시작 한 Activity 가 스 택 에 눌 려 실행 중인 Activity 가 됩 니 다.오래된 Activity 는 여전히 스 택 에 있 습 니 다.사용자 가 BACK 키 를 눌 렀 을 때 실행 중인 Activity 팝 업 창 고 는 오래된 Activity 가 실행 중인 Activity 로 복 구 됩 니 다.스 택 에 대상 이 포함 되 어 있 기 때문에 하나의 작업 에서 같은 Activity 하위 클래스 의 여러 대상 을 열 었 다 면,예 를 들 어 여러 개의 지도 브 라 우 저―스 택 은 모든 인 스 턴 스 에 하나의 단독 입 구 를 가지 고 있 습 니 다.스 택 에 있 는 Activity 는 정렬 되 지 않 고 팝 업 만 됩 니 다.Task 는 Activity 인 스 턴 스 로 구 성 된 스 택 입 니 다.manifest 파일 의 특정한 종류 나 요소 가 아니 기 때문에 하나의 Task 속성 을 설정 할 수 없습니다.Activity 를 상관 하지 않 고 하나의 Task 의 모든 속성 값 은 아래쪽 Activity 에 설정 되 어 있 습 니 다.이것 은 Affinity 에 사용 해 야 합 니 다.Affinity 에 대해 서 는 더 이상 자세히 설명 하지 않 습 니 다.문 서 를 조회 할 수 있 습 니 다.
하나의 Task 에 있 는 모든 Activity 가 하나의 전체 로 작 동 합 니 다.전체 Task(전체 Activity 스 택)는 프론트 데스크 로 밀 리 거나 백 스테이지 로 밀 릴 수 있 습 니 다.실행 중인 Task 에 네 개의 Activity 가 있다 고 가정 합 니 다.실행 중인 Activity 아래 에 세 개의 Activity 가 있 습 니 다.이때 사용 자 는 HOME 키 를 누 르 고 프로그램 실행 기 를 누 른 다음 에 새로운 프로그램 을 실행 합 니 다.(실제로 새로운 Task 가 실행 되 었 습 니 다)현재 Task 는 배경 으로 물 러 갑 니 다.새로 시작 한 프로그램의 root Activity 가 이때 표 시 됩 니 다.한 동안 사용 자 는 다시 응용 프로그램 으로 돌아 가 이전의 응용 프로그램(이전의 그 Task)을 다시 선택 했다.그러면 이전의 그 Task 는 이때 다시 프론트 데스크 로 돌 아 왔 다.사용자 가 BACK 키 를 눌 렀 을 때 화면 은 방금 떠 난 그 응용 프로그램의 Activity 를 표시 하 는 것 이 아니 라 프론트 데스크 로 돌아 간 Task 의 스 택 꼭대기 Activity 를 제외 했다.이 Task 의 다음 Activity 를 표시 합 니 다.상술 한 것 이 바로 Activity 와 Task 의 일반적인 행위 이지 만 이 행 위 는 거의 모든 면 에서 수정 할 수 있다.Activity 와 Task 의 관계,그리고 Task 에서 Activity 의 행 위 는 이 Activity 를 시작 하 는 Intent 대상 의 표지 와 manifest 파일 에 있 는 Activity 의요소 의 속성 이 공동으로 영향 을 받는다.
이상 은 Activity 와 Task 에 대한 설명 입 니 다.
안 드 로 이 드 프로젝트 를 개발 할 때 사용 자 는 프로그램 전환 을 피 할 수 없 으 며,전환 과정 에서 프로그램 은 백 엔 드 로 들 어가 실행 되 며,필요 할 때 작업 관리자 나 프로그램 을 다시 클릭 하거나 정보 알림 표시 줄 에 있 는 아이콘 을 클릭 하여 원래 의 인터페이스 로 돌아 갑 니 다.이러한 효 과 는 텐 센트 QQ 와 유사 합 니 다.QQ 를 열 면 메 인 화면 을 표시 하고,다른 프로그램 을 사용 할 때 QQ 는 아이콘 으로 정보 알림 표시 줄 에 표시 하 며,QQ 를 사용 할 때 정보 알림 표시 줄 에 있 는 아이콘 을 클릭 하면 QQ 메 인 화면 을 표시 합 니 다.
먼저 본 예시 의 실현 효과 도 를 보십시오.
2016428144551137.jpg (416×686)
2016428144627452.jpg (419×693)
위의 그림 두 번 째 그림 에서 우리 가 클릭 하면 원래 의 Activity 로 돌아 갑 니 다.
우리 의 프로그램 이 배경 에 들 어가 서 작 동 할 때 우리 의 시 뮬 레이 터 상단 에 아이콘 형식 으로 나타 날 것 입 니 다.다음 그림:
2016428144647679.jpg (416×164)
이러한 효과 에 대해 일반적인 방법 은 Activity 의 onStop()방법 에서 해당 하 는 코드 를 작성 하 는 것 입 니 다.Activity 가 배경 에 들 어 갈 때 onStop()방법 을 호출 하기 때문에 저 희 는 onStop()방법 에서 Notification 형식 으로 프로그램 아이콘 과 정 보 를 표시 할 수 있 습 니 다.그 중에서 대 호 는 다음 과 같 습 니 다.

@Override 
  protected void onStop() { 
  // TODO Auto-generated method stub 
    super.onStop(); 
    Log.v("BACKGROUND", "      "); 
    showNotification(); 
  } 
이상 의 쇼 Notification()방법 은 Notification 입 니 다.
그리고 정보 알림 표시 줄 의 Notification 을 클릭 한 후 원래 의 Activity 로 돌아 갑 니 다.
물론 HOME 키 를 포착 할 수 있 습 니 다.사용자 가 HOME 키 를 눌 렀 을 때 Notification 을 표시 합 니 다.다음은 코드 예제 입 니 다.

//   HOME           
 
  @Override 
 
  public boolean onKeyDown(int keyCode, KeyEvent event) { 
 
    // TODO Auto-generated method stub 
 
    //   HOME  
 
    if(keyCode == KeyEvent.KEYCODE_HOME){ 
 
      //   Notification 
 
      notification = new NotificationExtend(this); 
 
      notification.showNotification(); 
 
      moveTaskToBack(true);         

      return true; 
 
    } 
 
    return super.onKeyDown(keyCode, event); 
 
  } 
여기 NotificationExtend 는 Notification 을 표시 하 는 패키지 입 니 다.클래스 의 코드 는 다음 과 같 습 니 다.

package com.test.background; 

import android.app.Activity; 
 
import android.app.Notification; 
 
import android.app.NotificationManager; 
 
import android.app.PendingIntent; 
 
import android.content.Intent; 
 
import android.graphics.Color; 

/** 
 * Notification    
 * @Description: Notification    
 * @File: NotificationExtend.java 
 * @Package com.test.background 
 */ 
 
public class NotificationExtend { 
 
  private Activity context; 

  public NotificationExtend(Activity context) { 
 
    // TODO Auto-generated constructor stub 
 
    this.context = context; 
 
  } 
 
  //   Notification 
 
  public void showNotification() { 
 
    //     NotificationManager    
 
    NotificationManager notificationManager = ( 
 
        NotificationManager)context.getSystemService( 
 
            android.content.Context.NOTIFICATION_SERVICE); 
 
    //   Notification      
 
    Notification notification = new Notification( 
 
        R.drawable.icon,"   ",  
 
        System.currentTimeMillis()); 
 
    //           "Ongoing" "    "   
 
    notification.flags |= Notification.FLAG_ONGOING_EVENT; 
 
    //            "    " ,       。 
 
    notification.flags |= Notification.FLAG_AUTO_CANCEL 
 
    notification.flags |= Notification.FLAG_SHOW_LIGHTS; 
 
    notification.defaults = Notification.DEFAULT_LIGHTS; 
 
    notification.ledARGB = Color.BLUE; 
 
    notification.ledOnMS = 5000; 

    //           
 
    CharSequence contentTitle = "       "; //       
 
    CharSequence contentText = "      ,   ……"; //       

    Intent notificationIntent = new Intent(context,context.getClass()); 
 
    notificationIntent.setAction(Intent.ACTION_MAIN); 
    notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER); 
    PendingIntent contentIntent = PendingIntent.getActivity( 
    context, 0, notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT); 
    notification.setLatestEventInfo( 
    context, contentTitle, contentText, contentIntent); 
    //  Notification   NotificationManager 
    notificationManager.notify(0, notification); 
 
  } 

  //      
 
  public void cancelNotification(){ 
 
    NotificationManager notificationManager = ( 
 
        NotificationManager) context.getSystemService( 
 
            android.content.Context.NOTIFICATION_SERVICE); 
 
    notificationManager.cancel(0); 
 
  } 
 
} 

설정 파일 에 모든 Activity 를 단일 작업 으로 실행 하도록 설정 해 야 합 니 다.그렇지 않 으 면 원래 Activity 로 돌아 갈 때마다 Activity 가 새로 추 가 됩 니 다.원래 Activity 로 돌아 가지 않 습 니 다.
FLAG 사용 중ACTIVITY_NEW_TASK 가 표 지 를 제어 할 때 도 기 존 액 티 비 티 로 되 돌아 가지 않 는 현상 이 나타난다.이 표지 가 Activity 로 하여 금 새로운 Task 를 시작 하 게 한 다음 에 사용자 가 HOME 키 를 눌 러 이 Activity 를 떠 나 면 사용자 가 BACK 키 를 눌 렀 을 때 원래 Activity 로 돌아 갈 수 없습니다.일부 응용 프로그램(예 를 들 어 Notification)은 항상 새로운 Task 에서 Activity 를 열 고 자신의 Task 에서 열지 않 기 때문에 항상 FLAG 를 포함 합 니 다.ACTIVITY_NEW_TASK 의 인 텐트 는 startActivity()에 전달 된다.따라서 이 제어 표지 로 다른 것 에 의 해 호출 될 수 있 는 Activity 가 있다 면 프로그램 이 독립 적 으로 원래 Activity 로 돌아 가 는 방법 을 주의 하 십시오.코드 는 다음 과 같 습 니 다:

<activity android:name="ShowMessageActivity" 
       android:launchMode="singleTask"></activity>  
Android 응용 전 배경 전환 판단
안 드 로 이 드 에 서 는 응용 프로그램 앞 배경 에서 전환 하 는 리 셋 이나 방송 을 제공 하지 않 았 습 니 다.이 기능 은 우리 만 처리 할 수 있 습 니 다.이전에 이 문제 에 부 딪 힌 처리 방식 은 BaseActivity 를 실현 한 다음 에 다른 모든 Activity 를 계승 한 다음 에 생명주기 함수 에서 해당 하 는 검 측 을 하 는 것 이다.구체 적 인 검 측 방법 은 다음 과 같다.
       Activity 의 onStart 와 onStop 방법 에서 계산 합 니 다.계수 변 수 는 count 이 고 onStart 에서 변 수 를 1,onStop 에서 1 을 빼 고 두 개의 Activity 가 있다 고 가정 합 니 다.각각 A 와 B 입 니 다.
       상황 1.먼저 A 를 시작 하고 A 를 다시 시작 합 니 다.B:시작 A,count=1,A 가 B 를 시작 합 니 다.생명주기 의 순 서 는 B.onStart->A.onStop 이 고 count 의 수 는 1 입 니 다.
       상황 2.먼저 A 를 시작 한 다음 홈 키 를 누 르 면 데스크 톱 으로 돌아 갑 니 다.A,count=1 을 시작 하고 홈 키 를 누 르 면 데스크 톱 으로 돌아 갑 니 다.A.onStop,count 의 계수 변 위 0 을 실행 합 니 다.
       위의 두 가지 상황 을 통 해 알 수 있 듯 이 count 수 를 0 으로 계산 함으로써 응용 이 프론트 에서 백 스테이지 로 잘 렸 다 는 것 을 판단 할 수 있다.백 스테이지 에서 프런트 로 자 르 는 것 도 비슷 한 이치 다.구체 적 으로 뒤에 있 는 코드 를 보 세 요.
       그러나 프로젝트 에서 모든 Activity 가 같은 BaseActivity 에서 계승 되 는 것 이 아니라면 이 기능 을 실현 할 수 없다.다행히도 안 드 로 이 드 는 API 14 이후 애플 리 케 이 션 류 에서 라 이 프 사이클 리 셋 을 사용 하 는 등록 방법 을 제공 하여 응용 수명 주 기 를 집중 적 으로 관리 합 니 다.이 인 터 페 이 스 는 registerActivity LifecycleCallbacks 라 고 하 는데 이 를 통 해 자신의 Activity Life CycleCallback 을 등록 할 수 있 습 니 다.모든 Activity 의 생명주기 가 이곳 으로 되 돌아 오 는 대응 방법.사실 이 등록 방법의 본질은 우리 가 BaseActivity 를 실현 하 는 것 과 같 고 생명주기 관 리 를 Activity 자체 의 실현 으로 옮 겼 을 뿐이다.
 구체 적 인 사용 방법 은 다음 과 같다.

public class MyApplication extends Application{ 
  public int count = 0; 
  @Override 
  public void onCreate() { 
    super.onCreate(); 
 
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { 
 
      @Override 
      public void onActivityStopped(Activity activity) { 
        Log.v("viclee", activity + "onActivityStopped"); 
        count--; 
        if (count == 0) { 
          Log.v("viclee", ">>>>>>>>>>>>>>>>>>>     lifecycle"); 
        } 
      } 
 
      @Override 
      public void onActivityStarted(Activity activity) { 
        Log.v("viclee", activity + "onActivityStarted"); 
        if (count == 0) { 
          Log.v("viclee", ">>>>>>>>>>>>>>>>>>>     lifecycle"); 
        } 
        count++; 
      } 
 
      @Override 
      public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 
        Log.v("viclee", activity + "onActivitySaveInstanceState"); 
      } 
 
      @Override 
      public void onActivityResumed(Activity activity) { 
        Log.v("viclee", activity + "onActivityResumed"); 
      } 
 
      @Override 
      public void onActivityPaused(Activity activity) { 
        Log.v("viclee", activity + "onActivityPaused"); 
      } 
 
      @Override 
      public void onActivityDestroyed(Activity activity) { 
        Log.v("viclee", activity + "onActivityDestroyed"); 
      } 
 
      @Override 
      public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 
        Log.v("viclee", activity + "onActivityCreated"); 
      } 
    }); 
  } 
} 

그 밖 에 이 기능 을 실현 할 수 있 는 다른 방법 이 있 습 니까?
응용 프로그램 이 배경 으로 자 를 때 프론트 데스크 톱 에서 실행 되 는 프로 세 스 는 우리 의 app 에서 데스크 톱 app 으로 바 뀌 었 습 니 다.이 점 에 따라 우 리 는 응용 프로그램 전 배경 전환 을 감지 하 는 기능 을 실현 할 수 있 습 니 다.Activity 의 onStop 라 이 프 사이클 에서 검색 코드 를 실행 합 니 다.현재 프론트 데스크 에서 실행 중인 프로 세 스 가 우리 자신의 프로 세 스 가 아 닌 것 을 발견 하면 응용 프로그램 이 배경 으로 잘 렸 다 는 것 을 설명 합 니 다.
onPause 가 아 닌 왜 onStop 에서 검 측 했 는 지 생각해 보 세 요.이것 은 A 가 B 를 시작 할 때 생명주기 의 실행 순 서 는 다음 과 같 기 때문이다.A.onPause->B.onCreate->B.onStart->B.onResume->A.onStop.즉,A 의 onPause 방법 에서 B 의 생명주기 가 아직 실행 되 지 않 았 고 프로 세 스 가 프론트 에 들 어가 지 않 았 기 때문에 당연히 검출 되 지 않 았 다.우 리 는 코드 를 onPause 생명주기 로 옮 겼 는데,확실히 효과 가 없다 는 것 을 발견 했다.
구체 적 인 실현 코드 는 다음 과 같다.

//               
 private boolean isCurrentRunningForeground = true; 
 @Override 
 protected void onStart() { 
   super.onStart(); 
   if (!isCurrentRunningForeground) { 
     Log.d(TAG, ">>>>>>>>>>>>>>>>>>>     activity process"); 
   } 
 } 
 
 @Override 
 protected void onStop() { 
   super.onStop(); 
   isCurrentRunningForeground = isRunningForeground(); 
   if (!isCurrentRunningForeground) { 
     Log.d(TAG,">>>>>>>>>>>>>>>>>>>     activity process"); 
   } 
 } 
 
 public boolean isRunningForeground() { 
   ActivityManager activityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE); 
   List<ActivityManager.RunningAppProcessInfo> appProcessInfos = activityManager.getRunningAppProcesses(); 
   //      
   for (ActivityManager.RunningAppProcessInfo appProcessInfo : appProcessInfos) { 
     if (appProcessInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { 
       if (appProcessInfo.processName.equals(this.getApplicationInfo().processName)) { 
         Log.d(TAG,"EntryActivity isRunningForeGround"); 
         return true; 
       } 
     } 
   } 
   Log.d(TAG, "EntryActivity isRunningBackGround"); 
   return false; 
 } 

좋은 웹페이지 즐겨찾기