app的自动更新(调用DownloadManager)

时间:2023-03-08 22:45:44

具体思路为:调用接口与服务器版本对比,当服务器版本号大于本地的,调用DownloadManager进行下载,之前也试过很多方法,但是兼容性都不是很好,还有一点要注意的是,在这里我并没有设置固定的下载路径,最初设置之后华为某手机上直接闪退,原因是找不到路径:

与服务器上版本号对比就不写了,最简单的是app上写个常量,与获取的版本号比较就行,每次更新修改工程里的这个常量。

附上下载方法:

/**
* 版本更新Dialog
* */
private void showUpdateDialog(final String downPath) {
new AlertDialog.Builder(this).setTitle("提示").setMessage("发现新版本,是否更新?")
.setPositiveButton("马上更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
//使用系统下载类
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Uri uri = Uri.parse(downPath);
DownloadManager.Request request = new DownloadManager.Request(uri);
// 设置自定义下载路径和文件名,该方法可能在某些机型不兼容
// String apkName = "yourName" + DateUtils.getCurrentMillis() + ".apk";
// request.setDestinationInExternalPublicDir(yourPath, apkName);
// MyApplication.getInstance().setApkName(apkName);
//设置允许使用的网络类型,这里是移动网络和wifi都可以
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE|DownloadManager.Request.NETWORK_WIFI);

//禁止发出通知,既后台下载,如果要使用这一句必须声明一个权限:android.permission.DOWNLOAD_WITHOUT_NOTIFICATION
//request.setShowRunningNotification(false);

//不显示下载界面
request.setVisibleInDownloadsUi(false);
// 设置为可被媒体扫描器找到
request.allowScanningByMediaScanner();
// 设置为可见和可管理
request.setVisibleInDownloadsUi(true);
request.setMimeType("application/cn.trinea.download.file");
/*设置下载后文件存放的位置,如果sdcard不可用,那么设置这个将报错,因此最好不设置如果sdcard可用,下载后的文件
在/mnt/sdcard/Android/data/packageName/files目录下面,如果sdcard不可用,设置了下面这个将报错,不设置,下载后的文件在/cache这个 目录下面*/
//request.setDestinationInExternalFilesDir(this, null, "tar.apk");
long id = downloadManager.enqueue(request);//TODO 把id保存好,在接收者里面要用,最好保存在Preferences里面
MyApplication.getInstance().setApkId(Long.toString(id));//TODO 把id存储在Preferences里面
dialog.dismiss();
}
})
.setNegativeButton("下次再说", new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int arg1) {
// TODO Auto-generated method stub
dialog.dismiss();
}

}).show();
}

》》MyApplication 类:

public class MyApplication extends Application {

public static Context applicationContext;
private static MyApplication instance;

private static final String APK_ID = "apk_id";
private String apk_id = null;

@Override
public void onCreate() {
super.onCreate();
applicationContext = this;
instance = this;
}

public static MyApplication getInstance() {

return instance;
}

/**
* 设置下载APK ID
* @param id
* @return
*/
public void setApkId(String id){

SharedPreferences preferences= PreferenceManager.getDefaultSharedPreferences(applicationContext);
SharedPreferences.Editor editor=preferences.edit();
if(editor.putString(APK_ID, id).commit()){
apk_id=id;
}
}
/**
* 获取下载APK ID
* @return
*/
public String getApkId(){
apk_id = null;
if(apk_id==null){
SharedPreferences preferences=PreferenceManager.getDefaultSharedPreferences(applicationContext);
apk_id=preferences.getString(APK_ID, null);
}
return apk_id;
}
}

》》广播CompleteReceiver 类:

public class CompleteReceiver extends BroadcastReceiver {
private DownloadManager downloadManager;

@Override
public void onReceive(Context context, Intent intent) {

String action = intent.getAction();
if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
Toast.makeText(context, "下载完成!", Toast.LENGTH_LONG).show();

long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);//TODO 判断这个id与之前的id是否相等,如果相等说明是之前的那个要下载的文件

DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor cursor = downloadManager.query(query);
int columnCount = cursor.getColumnCount();
String path = null;//TODO 这里把所有的列都打印一下,有什么需求,就怎么处理,文件的本地路径就是path
while (cursor.moveToNext()) {
for (int j = 0; j < columnCount; j++) {
String columnName = cursor.getColumnName(j);
String string = cursor.getString(j);
if (columnName.equals("local_uri")) {
path = string;
}
if (string != null) {
System.out.println(columnName + ": " + string);
} else {
System.out.println(columnName + ": null");
}
}
}
cursor.close();

//如果sdcard不可用时下载下来的文件,那么这里将是一个内容提供者的路径,这里打印出来,有什么需求就怎么样处理 if(path.startsWith("content:")) {
if(path.startsWith("content:")) {
System.out.println("-----------------------CompleteReceiver 下载完了----路径path = " + path.toString());
}

if(id == Long.parseLong(MyApplication.getInstance().getApkId())){//TODO 判断这个id与之前的id是否相等,如果相等说明是之前的那个要下载的文件
Intent install = new Intent(Intent.ACTION_VIEW);
// Uri downloadFileUri = downloadManager.getUriForDownloadedFile(id);
String uriString = getFilePathFromUri(context, Uri.parse(path));//TODO 转换path路径 否则报解析包错误
System.out.println("-----------------------CompleteReceiver 转换后----路径uriString = " + uriString);
install.setDataAndType(Uri.fromFile(new File(uriString)), "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
} else if (action.equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
Toast.makeText(context, "点击通知了....", Toast.LENGTH_LONG).show();
}
}

/**
* 转换 path路径
* */
public static String getFilePathFromUri(Context c, Uri uri) {
String filePath = null;
if ("content".equals(uri.getScheme())) {
String[] filePathColumn = { MediaStore.MediaColumns.DATA };
ContentResolver contentResolver = c.getContentResolver();

Cursor cursor = contentResolver.query(uri, filePathColumn, null,
null, null);

cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
} else if ("file".equals(uri.getScheme())) {
filePath = new File(uri.getPath()).getAbsolutePath();
}
return filePath;
}

}

<manifest 配置:

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

<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".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>
<receiver android:name=".CompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>
</intent-filter>
</receiver>
</application>

</manifest>