首页 > 代码库 > Android 更新升级下载 自定义Updates 兼容版

Android 更新升级下载 自定义Updates 兼容版

Android 更新模块 自定义Update



写这个总结是因为在项目中碰到了Android系统兼容的BUG  

Android项目原本使用的是API提供的下载方法  
如下:
			DownloadManager downloadManager = (DownloadManager) getSystemService(Activity.DOWNLOAD_SERVICE);
			DownloadManager.Request request = new Request(Uri.parse(dl));
			request.setTitle(getString(R.string.app_name));
			request.setDestinationUri(getDownloadName(getIntent().getStringExtra("version_name")));
			long reference = downloadManager.enqueue(request);
			UserSettingHelper.getInstance().setUpgradeKey(reference);


但如三星  华为 等手机它自带的系统中 删除掉了google服务从而导致崩溃 


在网上找了资料 然后改吧改吧总算快速修复了bug:

1) 主activity 
package com.example.updataapk;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

/**
 * 
 * @author baozi
 * 
 */
public class MainActivity extends Activity {

	// 地址
	private String dl = "http://17shihui.cn/download/shihui.apk";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Function_Utility.setAppContext(getApplicationContext());

		findViewById(R.id.button1).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Uri uri = Uri.parse(dl);
				Intent intent = new Intent(Intent.ACTION_VIEW, uri);
				startActivity(intent);
			}
		});
		findViewById(R.id.button2).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				try {
					download(dl);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	private void download(String dl) throws Exception {
		if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
			Intent service = new Intent(this, DownloadService.class);
			service.putExtra(DownloadService.INTENT_URL, dl);
			startService(service);

		} else {
			Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(dl));
			startActivity(intent);
		}
	}
}


2) 下载模块
package com.example.updataapk;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;

public class DownloadService extends Service {
	// notification 名字
	private String notify_name = "apk正在下载...";
	public static final String INTENT_URL = "url";
	private Context mContext = this;
	Notification mNotification;
	private static final int NOTIFY_ID = 0;
	private NotificationManager mNotificationManager;
	/* 下载包安装路径 */
	private static final String savePath = Function_Utility.getUpgradePath();
	private static final String saveFileName = savePath + "demo.apk";
	private String apkUrl;
	private int progress;
	boolean canceled;
	private Thread downLoadThread;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);
	}

	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i("DownloadService", "intent=" + intent.toString() + " ;           flags= " + flags + " ;    startId" + startId);
		if (intent.hasExtra(DownloadService.INTENT_URL)) {
			apkUrl = (String) intent.getExtras().get(DownloadService.INTENT_URL);
		}
		progress = 0;
		setUpNotification();
		new Thread() {
			public void run() {
				// 开始下载
				startDownload();
			};
		}.start();

		return startId;

	};

	private void startDownload() {
		canceled = false;
		downloadApk();
	}

	private Handler mHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case 0:
				// 下载完毕
				// 取消通知
				mNotificationManager.cancel(NOTIFY_ID);
				installApk();
				break;
			case 2:
				// 这里是用户界面手动取消,所以会经过activity的onDestroy();方法
				// 取消通知
				mNotificationManager.cancel(NOTIFY_ID);
				break;
			case 1:
				int rate = msg.arg1;
				if (rate < 100) {
					RemoteViews contentview = mNotification.contentView;
					contentview.setTextViewText(R.id.tv_progress, rate + "%");
					contentview.setProgressBar(R.id.progressbar, 100, rate, false);
				} else {
					// 下载完毕后变换通知形式
					mNotification.flags = Notification.FLAG_AUTO_CANCEL;
					mNotification.contentView = null;
					mNotification.setLatestEventInfo(mContext, "下载完成", "文件已下载完毕", null);
					stopSelf();// 停掉服务自身
				}
				PendingIntent contentIntent2 = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);
				mNotification.contentIntent = contentIntent2;
				mNotificationManager.notify(NOTIFY_ID, mNotification);
				break;
			case 3:
				mNotification.flags = Notification.FLAG_AUTO_CANCEL;
				RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.update_download_notification_layout);
				contentView.setTextViewText(R.id.name, "下载失败");
				// 指定个性化视图
				mNotification.contentView = contentView;
				Intent intent = new Intent(getApplicationContext(), MainActivity.class);
				PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

				// 指定内容意图
				mNotification.contentIntent = contentIntent;
				mNotificationManager.notify(NOTIFY_ID, mNotification);

				stopSelf();// 停掉服务自身
				break;

			}
		}
	};

	/**
	 * 安装apk
	 * 
	 * @param url
	 */
	private void installApk() {
		File apkfile = new File(saveFileName);
		if (!apkfile.exists()) {
			return;
		}
		Intent i = new Intent(Intent.ACTION_VIEW);
		i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
		mContext.startActivity(i);
	}

	private int lastRate = 0;
	private InputStream is = null;
	private FileOutputStream fos = null;

	/**
	 * 下载apk
	 * 
	 * @param url
	 */
	private void downloadApk() {
		downLoadThread = new Thread(mdownApkRunnable);
		downLoadThread.start();
	}

	private Runnable mdownApkRunnable = new Runnable() {

		@Override
		public void run() {
			try {
				URL url = new URL(apkUrl);
				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
				conn.connect();
				int length = conn.getContentLength();
				is = conn.getInputStream();

				File file = new File(savePath);
				if (!file.exists()) {
					file.mkdirs();
				}
				String apkFile = saveFileName;
				File ApkFile = new File(apkFile);
				fos = new FileOutputStream(ApkFile);

				int count = 0;
				byte buf[] = new byte[1024];

				do {
					int numread = is.read(buf);
					count += numread;
					progress = (int) (((float) count / length) * 100);
					// 更新进度
					Message msg = mHandler.obtainMessage();
					msg.what = 1;
					msg.arg1 = progress;
					if (progress >= lastRate + 1) {
						mHandler.sendMessage(msg);
						lastRate = progress;
					}
					if (numread <= 0) {
						mHandler.sendEmptyMessage(0);// 下载完成通知安装
						// 下载完了,cancelled也要设置
						canceled = true;
						break;
					}
					fos.write(buf, 0, numread);
				} while (!canceled);// 点击取消就停止下载.
				Log.i("DownloadService----------canceled", canceled + "");
				fos.close();
				is.close();
			} catch (Exception e) {

				Message msg = mHandler.obtainMessage();
				msg.what = 3;
				mHandler.sendMessage(msg);
				e.printStackTrace();
			} finally {
				try {
					if (fos != null) {
						fos.close();
					}
					is.close();
					if (is != null) {
						is.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		}
	};

	/**
	 * 创建通知
	 */
	private void setUpNotification() {
		int icon = R.drawable.ic_launcher;
		CharSequence tickerText = "开始下载";
		long when = System.currentTimeMillis();
		mNotification = new Notification(icon, tickerText, when);
		;
		// 放置在"正在运行"栏目中
		mNotification.flags = Notification.FLAG_ONGOING_EVENT;

		RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.update_download_notification_layout);
		contentView.setTextViewText(R.id.name, notify_name);
		// 指定个性化视图
		mNotification.contentView = contentView;

		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);

		// 指定内容意图
		mNotification.contentIntent = contentIntent;
		mNotificationManager.notify(NOTIFY_ID, mNotification);
	}

}

3) 下载到手机的地址 
package com.example.updataapk;

import java.io.File;
import java.io.IOException;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Environment;

@SuppressWarnings("deprecation")
@SuppressLint({ "DefaultLocale", "SimpleDateFormat" })
public class Function_Utility {

	private static Context mAppContext;

	public static void setAppContext(Context context) {
		mAppContext = context;
	}

	public static Context getAppContext() {
		return mAppContext;
	}

	/**
	 * 下载到SD卡地址
	 */
	public static String getUpgradePath() {
		String filePath = getAppRootPath() + "/upgrade/";
		File file = new File(filePath);
		if (!file.isDirectory()) {
			file.mkdirs();
		}
		file = null;
		return filePath;
	}

	public static String getAppRootPath() {
		String filePath = "/weimicommunity";
		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
			filePath = Environment.getExternalStorageDirectory() + filePath;
		} else {
			filePath = getAppContext().getCacheDir() + filePath;
		}
		File file = new File(filePath);
		if (!file.exists()) {
			file.mkdirs();
		}
		file = null;
		File nomedia = new File(filePath + "/.nomedia");
		if (!nomedia.exists())
			try {
				nomedia.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		return filePath;
	}
}

4) Androidmanifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.updataapk"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.updataapk.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name="com.example.updataapk.DownloadService" >
        </service>
    </application>

</manifest>

效果图:


下载完成后 自动安装

Android 更新升级下载 自定义Updates 兼容版