안 드 로 이 드 에서 DownloadManager 가 버 전 업 데 이 트 를 실현 하고 다운로드 진행 인 스 턴 스 를 감청 합 니 다.

DownloadManager 안내
DownloadManager 는 Android 2.3(API level 9)에서 시스템 서비스(Service)방식 으로 장시간 다운로드 작업 을 처리 하 는 DownloadManager 를 제공 합 니 다.두 개의 정적 내부 클래스 DownloadManager.Query(다운로드 정 보 를 조회 하 는 데 사용)와 DownloadManager.Request(다운로드 요청)를 포함 합 니 다.
DownloadManager 는 주로 다음 과 같은 몇 가지 방법 을 제공 합 니 다.
public long enqueue(Request request)는 다운로드 대기 열 에 작업 을 추가 하고 다운로드 정 보 를 조회 할 수 있 도록 downloadId 로 되 돌려 줍 니 다.만약 에 네트워크 가 조건 을 만족 시 키 지 못 하면 Sdcard 마 운 트 중,최대 병발 수 를 초과 하 는 등 이상 이 다운 로드 를 기다 리 고 정상 적 이면 직접 다운로드 합 니 다.
public int remove(long...ids)는 다운 로드 를 삭제 합 니 다.다운 로드 를 취소 하면 다운로드 파일 과 기록 을 동시에 삭제 합 니 다.
public Cursor query(Query query)는 다운로드 파일 의 총 크기,다운로드 한 크기,다운로드 상태 등 을 포함 하여 다운로드 정 보 를 조회 합 니 다.
ContentObserver 소개
public void ContentObserver(Handler handler)모든 ContentObserver 의 파생 클래스 는 이 구조 방법 을 호출 해 야 합 니 다.매개 변수:handler Handler 대상 은 메 인 스 레 드 에서 UI 를 수정 하 는 데 사 용 됩 니 다.
public void onChange(boolean selfChange)에서 관찰 한 Uri 의 내용 이 변 하면 이 방법 을 되 돌려 줍 니 다.모든 ContentObserver 의 파생 클래스 는 이 방법 을 다시 불 러 와 논 리 를 처리 해 야 합 니 다.
특정 Uri 를 관찰 하 는 절 차 는 다음 과 같다.
1.우리 의 특정한 ContentObserver 파생 류 를 만 들 려 면 부모 류 구조 방법 을 다시 불 러 와 야 합 니 다.onChange()방법 을 다시 불 러 와 서 리 셋 후의 기능 을 처리 해 야 합 니 다.
2.지정 한 Uri 에 ContentObserver 파생 클래스 인 스 턴 스 를 등록 하고 주어진 Uri 가 바 뀌 었 을 때 이 인 스 턴 스 대상 을 되 돌려 처리 하 며 registerContentObserver()방법 으로 내용 관찰 자 를 등록 합 니 다.
3.ContentObserver 의 생명주기 가 Activity 와 Service 와 일치 하지 않 기 때 문 입 니 다.따라서 필요 하지 않 을 때 unregister ContentObserver()로그아웃 내용 관찰 자 를 수 동 으로 호출 해 야 합 니 다.
효과 그림:

다운로드 실행
설정 다운로드

downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadObserver = new DownloadChangeObserver();
//             
registerContentObserver();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
/**            */
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
/**         */
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
/**             */
request.setAllowedOverRoaming(false);
/**                 Downloads        ,
      Request   setVisibleInDownloadsUi  ,    true.*/
request.setVisibleInDownloadsUi(true);
/**        */
request.setDestinationInExternalFilesDir(getApplicationContext(), "phoenix", "phoenix.apk");
/**         , return     ID*/
downloadId = downloadManager.enqueue(request);
//                   
registerBroadcast();
권한 추가

<!--      -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--SD       -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--SD        -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--VISIBILITY_HIDDEN               -->
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
<!--DownloadManager-->
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
        Service
<!--      -->
<service android:name="com.github.phoenix.service.DownloadService"></service>
2.다운로드 진행 감청
ContentObserver 등록
세 개의 매개 변 수 는 각각 감청 할 Uri,false 가 이 Uri 와 정확하게 일치 하 는 것 을 나타 내 고 true 는 파생 된 Uri,ContentObserver 의 파생 클래스 인 스 턴 스 와 일치 할 수 있 음 을 나타 낸다.

/**
*   ContentObserver
*/
private void registerContentObserver() {
 /** observer download change **/
 if (downloadObserver != null) {
   getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true, downloadObserver);
 }
}
다운로드 한 데이터 크기 조회
성능 을 향상 시 키 기 위해 정시 작업 을 시작 하고 2 초 마다 데이터 크기 를 조회 하여 handle 에 보 내 UI 를 업데이트 합 니 다.

/**
*       
*/
private class DownloadChangeObserver extends ContentObserver {

 public DownloadChangeObserver() {
   super(downLoadHandler);
   scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
 }

 /**
  *      Uri     ,       
  *
  * @param selfChange       ,          false
  */
 @Override
 public void onChange(boolean selfChange) {
   scheduledExecutorService.scheduleAtFixedRate(progressRunnable, 0, 2, TimeUnit.SECONDS);
 }
}
/**
*   query      ,         ,   ,    
*
* @param downloadId
* @return
*/
private int[] getBytesAndStatus(long downloadId) {
 int[] bytesAndStatus = new int[]{
     -1, -1, 0
 };
 DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);
 Cursor cursor = null;
 try {
   cursor = downloadManager.query(query);
   if (cursor != null && cursor.moveToFirst()) {
     //        
     bytesAndStatus[0] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
     //        
     bytesAndStatus[1] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
     //    
     bytesAndStatus[2] = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
   }
 } finally {
   if (cursor != null) {
     cursor.close();
   }
 }
 return bytesAndStatus;
}

Activity 와 Service 통신
Activity 에서 다운로드 진 도 를 실시 간 으로 업데이트 하려 면 Activity 바 인 딩 서비스 가 통신 을 해 야 합 니 다.
Service 에서 인터페이스 실시 간 으로 진행 값 을 되 돌려 줍 니 다.isBindService 로 Activity 가 서 비 스 를 연결 한 적 이 있 는 지 여 부 를 표시 합 니 다.bindService(ServiceConnection conn)방법 을 호출 할 때 바 인 딩 에 성공 하면 true 로 돌아 갑 니 다.그렇지 않 으 면 false 로 돌아 갑 니 다.true 로 돌아 갈 때 만 바 인 딩 을 풀 수 있 습 니 다.그렇지 않 으 면 오 류 를 보고 할 수 있 습 니 다.

private ServiceConnection conn = new ServiceConnection() {

 @Override
 public void onServiceConnected(ComponentName name, IBinder service) {
   DownloadService.DownloadBinder binder = (DownloadService.DownloadBinder) service;
   DownloadService downloadService = binder.getService();

   //    ,    
   downloadService.setOnProgressListener(new DownloadService.OnProgressListener() {
     @Override
     public void onProgress(float fraction) {
       LogUtil.i(TAG, "    :" + fraction);
       bnp.setProgress((int)(fraction * 100));

       //               ,           
       if (fraction == DownloadService.UNBIND_SERVICE && isBindService) {
         unbindService(conn);
         isBindService = false;
         MToast.shortToast("    !");
       }
     }
   });
 }

 @Override
 public void onServiceDisconnected(ComponentName name) {

 }
};

3.방송 감청 다운로드 성공
다운로드 완료,자동 설치,APK 저장 경로 기록
다운로드 에 성공 한 후 APK 저장 경 로 를 SP 에 저장 하고 타 이 머 를 닫 고 apk 설치 인터페이스 를 엽 니 다.

/**
*   APK
* @param context
* @param apkPath       
*/
public static void installApk(Context context, Uri apkPath) {
 Intent intent = new Intent();
 intent.setAction(Intent.ACTION_VIEW);
 //        Context,     Flag,     
 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 intent.setDataAndType(apkPath, "application/vnd.android.package-archive");
 context.startActivity(intent);
}
사후 처리
1.타이머,스 레 드 닫 기
다운로드 가 완 료 된 방송 을 받 았 을 때 즉시 타 이 머 를 멈 추고 스 레 드 를 취소 합 니 다.
2.서비스 해제,방송 취소,ContentObserver 로그아웃
서 비 스 를 풀 때 는 다운로드 가 완 료 된 방송 과 다운로드 진행 상황 을 감청 하 는 ContentObserver 를 로그아웃 해 야 한다.
3、APK 삭제
응용 프로그램 이 설치 되 었 을 때 다시 시작 하면 APK 삭제 작업 을 실행 합 니 다.

/**
*             apk
*/
private void removeOldApk() {
 //   APK     
 File fileName = new File(SPUtil.getString(Constant.SP_DOWNLOAD_PATH, ""));
 LogUtil.i(TAG, " APK      =" + SPUtil.getString(Constant.SP_DOWNLOAD_PATH, ""));

 if (fileName != null && fileName.exists() && fileName.isFile()) {
   fileName.delete();
   LogUtil.i(TAG, "       APK,      ");
 }
}

5.구체 적 인 응용
먼저 현재 응용 버 전 번 호 를 서버 에 업로드 하여 서버 가 버 전 업 데 이 트 를 할 수 있 는 지 확인 하도록 합 니 다.버 전 업 데 이 트 를 할 수 있 으 면 Service 를 연결 하고 APK 를 다운로드 하기 시작 합 니 다.다운로드 가 완료 되면 설치 인터페이스 가 바로 팝 업 되 고 APK 저장 경 로 를 기록 합 니 다.다음 시작 시 APK 삭 제 를 확인 합 니 다.
원본 코드:DownloadManager_jb51.rar
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기