//Java UpdateUtil.java package com.cdx.unity3d; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.support.v4.content.FileProvider; import java.io.File; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.os.Handler; import android.os.Message; import com.unity3d.player.UnityPlayer; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class UpdateUtil { private Context mContext; private String apkUrl; private String savePath; private String saveFileName; private String downloadMsg; private int progress; private ProgressDialog downloadDialog; private Thread downLoadThread; private boolean interceptFlag = false; public UpdateUtil(Context context) { this.mContext = context; } /** * 更新下载apk */ public static void downLoadApk(final String url, final String storge, Boolean showNotify) { final Activity activity = UnityPlayer.currentActivity; activity.runOnUiThread(new Runnable() { public void run() { UpdateUtil updater = new UpdateUtil((Context)activity); updater.Download(url, storge); } }); } public void Download(String url, String storge) { this.apkUrl = url; this.savePath = storge; this.saveFileName = storge; this.downloadDialog = new ProgressDialog(this.mContext); this.downloadDialog.setTitle("游戏更新"); this.downloadDialog.setMessage("请稍后。。。"); this.downloadDialog.setProgressStyle(1); this.downloadDialog.setCancelable(false); this.downloadDialog.setCanceledOnTouchOutside(false); this.downloadDialog.setMax(100); this.downloadDialog.show(); downloadApk(); } private void downloadApk() { this.downLoadThread = new Thread(this.mdownApkRunnable); this.downLoadThread.start(); } private Runnable mdownApkRunnable = new Runnable() { public void run() { try { URL url = new URL(UpdateUtil.this.apkUrl); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.connect(); int length = conn.getContentLength(); InputStream is = conn.getInputStream(); File file = new File(UpdateUtil.this.saveFileName); if (file.isFile()) { file = new File(file.getParent()); } if ((file.isDirectory()) && (!file.exists())) { file.mkdir(); } String apkFile = UpdateUtil.this.saveFileName; File ApkFile = new File(apkFile); FileOutputStream fos = new FileOutputStream(ApkFile); String fName = UpdateUtil.this.apkUrl.trim(); fName = fName.substring(fName.lastIndexOf("/") + 1,fName.lastIndexOf("?")); UpdateUtil.this.downloadMsg = ("正在下载文件:" + fName); UpdateUtil.this.mHandler.sendEmptyMessage(0); int count = 0; byte[] buf = new byte[1024]; do { int numread = is.read(buf); count += numread; UpdateUtil.this.progress = ((int)((float)count / (float) length * 100.0F)); UpdateUtil.this.downloadMsg = ("正在下载文件:" + fName + " " + count / 1024 + "kb/" + length / 1024 + "kb"); UpdateUtil.this.mHandler.sendEmptyMessage(1); if (numread <= 0) { break; } fos.write(buf, 0, numread); } while (!UpdateUtil.this.interceptFlag); fos.close(); is.close(); UpdateUtil.this.mHandler.sendEmptyMessage(2); } catch (MalformedURLException e) { e.printStackTrace(); UpdateUtil.this.downloadMsg = ("下载失败,出现异常:" + e.getMessage()); UpdateUtil.this.mHandler.sendEmptyMessage(3); } catch (IOException e) { e.printStackTrace(); UpdateUtil.this.downloadMsg = ("下载失败,出现异常:" + e.getMessage()); UpdateUtil.this.mHandler.sendEmptyMessage(3); } } }; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 0: UpdateUtil.this.downloadDialog.setMessage(UpdateUtil.this.downloadMsg); break; case 1: UpdateUtil.this.downloadDialog.setMessage(UpdateUtil.this.downloadMsg); UpdateUtil.this.downloadDialog.setProgress(UpdateUtil.this.progress); break; case 2: UpdateUtil.this.installApk(); UpdateUtil.this.downloadDialog.dismiss(); break; case 3: UpdateUtil.this.downloadDialog.dismiss(); AlertDialog.Builder builder = new AlertDialog.Builder(UpdateUtil.this.mContext); builder.setTitle("下载失败"); builder.setMessage("是否重试?"); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); UpdateUtil.this.Download(UpdateUtil.this.apkUrl, UpdateUtil.this.savePath); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); Activity act = (Activity)UpdateUtil.this.mContext; act.finish(); } }); builder.create().show(); break; } } }; /** * 安装apk */ private void installApk() { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Uri data = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//判断版本大于等于7.0 // 生成文件的uri,, // 注意 下面参数com.xxx.xxx.fileprovider为apk的包名加上.fileprovider, data = FileProvider.getUriForFile(this.mContext, "com.xxx.xxx.fileprovider", new File(this.saveFileName)); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// 给目标应用一个临时授权 } else { data = Uri.fromFile(new File(this.saveFileName)); } intent.setDataAndType(data, "application/vnd.android.package-archive"); this.mContext.startActivity(intent); } }
修改Plugins/Android/AndroidManifest.xml文件,添加权限和provider
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.zfzx.cyzx.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths"/> </provider>
在Plugins/Android/res/xml下添加filepaths.xml文件,注意替换包名!
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!--<external-path name="external_files" path="."/>--> <external-path path="Android/data/包名!" name="files_root" /> <external-path path="." name="external_storage_root" /> </paths>
这样把下载的apk的文件保存在Application.persistentDataPath目录下,也就是在downloadApk方法中传入的storge参数为Application.persistentDataPath + "/包.apk"就可以了。如果打包不了或报错了,将android-support-v4.jar放到Plugins/Android目录下。