package com.dazhongcun.merchants.service; import java.io.File; import java.net.URLEncoder; import com.dazhongcun.application.BaseApplication; import com.dazhongcun.meifa.merchants.R; import com.dazhongcun.merchants.database.BaseAppDbHelper; import com.dazhongcun.merchants.entity.Downloads; import com.dazhongcun.merchants.utils.FileUtils; import android.annotation.SuppressLint; import android.app.DownloadManager; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.text.TextUtils; import android.webkit.MimeTypeMap; import android.widget.Toast; @SuppressLint("NewApi") public class UpgradeService extends Service implements Runnable { public static final String DOWNLOAD_URL = "download_url"; private DownloadManager downloadManager; private Downloads downloads = new Downloads(); private BaseAppDbHelper<Downloads> mDbHelper; private String mDownloadUrl; private long downloadId = -1; private File destDir = null; private File destFile = null; private String destFileName; private static final int DOWNLOAD_FAIL = -1; private static final int DOWNLOAD_SUCCESS = 0; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case DOWNLOAD_SUCCESS: Toast.makeText(getApplicationContext(), R.string.app_upgrade_download_sucess, Toast.LENGTH_LONG) .show(); install(destFile); break; case DOWNLOAD_FAIL: Toast.makeText(getApplicationContext(), R.string.app_upgrade_download_fail, Toast.LENGTH_LONG) .show(); break; default: break; } } }; private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { long reference = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (downloadId == reference) { queryDownloadStatus(); } } }; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); mDbHelper = new BaseAppDbHelper<Downloads>(); IntentFilter filter = new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE); registerReceiver(receiver, filter); } private void queryDownloadStatus() { DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); Cursor c = downloadManager.query(query); if (c.moveToFirst()) { int status = c.getInt(c .getColumnIndex(DownloadManager.COLUMN_STATUS)); switch (status) { case DownloadManager.STATUS_PAUSED: // Log.v("down", "STATUS_PAUSED"); case DownloadManager.STATUS_PENDING: // Log.v("down", "STATUS_PENDING"); case DownloadManager.STATUS_RUNNING: // 正在下载,不做任何事情 // Log.v("down", "STATUS_RUNNING"); break; case DownloadManager.STATUS_SUCCESSFUL: // 完成 // Log.v("down", "下载完成"); Message msg1 = mHandler.obtainMessage(); msg1.what = DOWNLOAD_SUCCESS; mHandler.sendMessage(msg1); break; case DownloadManager.STATUS_FAILED: // 清除已下载的内容,重新下载 // Log.v("down", "STATUS_FAILED"); downloadManager.remove(downloadId); mDbHelper.remove(Downloads.class, Downloads.DOWNLOAD_ID, downloadId); Message msg2 = mHandler.obtainMessage(); msg2.what = DOWNLOAD_FAIL; mHandler.sendMessage(msg2); break; } } stopSelf(); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override @Deprecated public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub super.onStart(intent, startId); if (intent != null) { parseIntent(intent); } } private void parseIntent(Intent intent) { final Bundle arguments = intent.getExtras(); if (arguments != null) { if (arguments.containsKey(DOWNLOAD_URL)) { mDownloadUrl = arguments.getString(DOWNLOAD_URL); if (Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED)) { destDir = new File(Environment .getExternalStorageDirectory().getPath() + BaseApplication.mAppDownloads); if (destDir.exists()) { try { destFileName = mDownloadUrl.substring(mDownloadUrl .lastIndexOf("/") + 1).toString(); if(destFile == null ||"".equals(destFile)){ destFileName = BaseApplication.mAppName + ".apk"; } } catch (Exception e) { // TODO: handle exception destFileName = BaseApplication.mAppName + ".apk"; } File destFile = new File(destDir.getPath() + "/" + destFileName); if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) { install(destFile); stopSelf(); return; } }else{ if(destDir.mkdirs()){ try { destFileName = mDownloadUrl.substring(mDownloadUrl .lastIndexOf("/") + 1).toString(); if(destFile == null ||"".equals(destFile)){ destFileName = BaseApplication.mAppName + ".apk"; } } catch (Exception e) { // TODO: handle exception destFileName = BaseApplication.mAppName + ".apk"; } File destFile = new File(destDir.getPath() + "/" + destFileName); if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) { install(destFile); stopSelf(); return; } } } } else { return; } new Thread(this).start(); } } } @Override public void run() { // TODO Auto-generated method stub download(); } @SuppressLint("NewApi") private void download() { if (Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED)) { if (destDir == null) { destDir = new File(Environment.getExternalStorageDirectory() .getPath() + BaseApplication.mAppDownloads); } if (destDir.exists() || destDir.mkdirs()) { destFile = new File(destDir.getPath() + "/" + destFileName);// URLEncoder.encode(mDownloadUrl) if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) { install(destFile); } else { // downloads.setUrl(mDownloadUrl); DownloadManager.Request request = new DownloadManager.Request( Uri.parse(mDownloadUrl)); /** * 下载存储文件夹和文件名 设置下载后文件存放的位置,如果sdcard不可用,那么设置这个将报错,因此最好不设置 * 如果sdcard可用,下载后的文件 * 在/mnt/sdcard/Android/data/packageName/files目录下面, * 如果sdcard不可用,设置了下面这个将报错,不设置,下载后的文件在/cache这个 目录下面 */ downloads.setDirType(BaseApplication.mAppDownloads); downloads.setSubPath(destFileName); //setDestinationInExternalPublicDir这里设置是已包含了/mnt/sdcard request.setDestinationInExternalPublicDir( BaseApplication.mAppDownloads, destFileName); // 设置下载中通知栏提示的标题 final String title = destFileName;/*getResources().getString( R.string.app_name);*/ downloads.setTitle(title); request.setTitle(title); // 设置下载中通知栏提示的介绍 final String description = getResources().getString( R.string.app_upgrade_download_start); downloads.setDescription(description); request.setDescription(description); downloads .setVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); downloads.setScanning(false); request.setShowRunningNotification(true); request.setVisibleInDownloadsUi(true); // 以下两项设置需android3.0以上 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { /** * 表示下载进行中和下载完成的通知栏是否显示,默认只显示下载中通知。 * VISIBILITY_VISIBLE(0) This download is visible but * only shows in the notifications while it's in * progress. VISIBILITY_VISIBLE_NOTIFY_COMPLETED(1) * 表示下载中和完成后显示通知栏提示。 VISIBILITY_HIDDEN(2)表示不显示任何通知栏提示, * 这个需要在AndroidMainfest中添加权限android * .permission.DOWNLOAD_WITHOUT_NOTIFICATION. * VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION(3)This * download shows in the notifications after completion * ONLY */ request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // 表示允许MediaScanner扫描到这个文件,默认不允许。 if (downloads.getScanning()) { request.allowScanningByMediaScanner(); } } /** * 表示下载允许的网络类型,默认在任何网络下都允许下载。 * 有NETWORK_MOBILE(1)、NETWORK_WIFI * (2)、NETWORK_BLUETOOTH三种及其组合可供选择。 * 如果只允许wifi下载,而当前网络为3g,则下载会等待。 * request.setAllowedOverRoaming(boolean * allow)移动网络情况下是否允许漫游。 */ downloads.setNetworkType(0); if (downloads.getNetworkType() != 0) { request.setAllowedNetworkTypes(downloads .getNetworkType()); } /** * 设置下载文件的mineType。 * 因为下载管理Ui中点击某个已下载完成文件及下载完成点击通知栏提示都会根据mimeType去打开文件, * 所以我们可以利用这个属性 * 。比如上面设置了mimeType为application/com.trinea.download.file, * 我们可以同时设置某个Activity的intent * -filter为application/com.trinea.download.file,用于响应点击的打开文件。 */ // 设置文件类型 MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); String mimeString = mimeTypeMap .getMimeTypeFromExtension(MimeTypeMap .getFileExtensionFromUrl(mDownloadUrl)); request.setMimeType(mimeString); downloads.setMimeType(mimeString); /** * 添加请求下载的网络链接的http头,比如User-Agent,gzip压缩等 */ // if(!TextUtils.isEmpty(downloads.getHeader())){ // request.addRequestHeader(Downloads.HEADER, // downloads.getHeader()); // } // //TODO 把id保存好,在接收者里面要用,最好保存在Preferences里面 downloadId = downloadManager.enqueue(request); downloads.setDownloadId(downloadId); mDbHelper.create(downloads); } } } } public boolean checkApkFile(String apkFilePath) { boolean result = false; try { PackageManager pManager = getPackageManager(); PackageInfo pInfo = pManager.getPackageArchiveInfo(apkFilePath, PackageManager.GET_ACTIVITIES); if (pInfo == null) { result = false; } else { if(pInfo.versionCode>BaseApplication.mVersionCode){ result = true; }else{ boolean del = FileUtils.DeleteFolder(apkFilePath); // Logger.d("upgrade", del+ "-------------"); result = false; } } } catch (Exception e) { result = false; e.printStackTrace(); } return result; } public void install(File apkFile) { Uri uri = Uri.fromFile(apkFile); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(uri, "application/vnd.android.package-archive"); startActivity(intent); } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); } }