安卓自更新,兼容7.0
/** * http://blog.csdn.net/rodulf/article/details/51706788 * * 修改后兼容7.0 */ public class UpdateService extends Service { // 文件保存路径(如果有SD卡就保存SD卡,如果没有SD卡就保存到手机包名下的路径) private String APK_dir = ""; private String apkName; // 文件下载路径 private String APK_url = ""; public UpdateService() { } /** 安卓系统下载类 **/ DownloadManager manager; /** 接收下载完的广播 **/ DownloadCompleteReceiver receiver; /** 初始化下载器 **/ private void initDownManager() { manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); receiver = new DownloadCompleteReceiver(); //设置下载地址 // String urlPath = "http://47.93.61.22/wordpress/app-release.apk"; Uri parse = Uri.parse(APK_url); DownloadManager.Request down = new DownloadManager.Request(parse); // 百度音乐 Uri.parse("http://gdown.baidu.com/data/wisegame/fd84b7f6746f0b18/baiduyinyue_4802.apk")); // 乐视体育 //Uri.parse("http://122.228.237.132/apk.r1.market.hiapk.com/data/upload/apkres/2016/6_12/16/com.lesports.glivesports_040405.apk")); // 设置允许使用的网络类型,这里是移动网络和wifi都可以 down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); // 下载时,通知栏显示途中 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); } // 显示下载界面 down.setVisibleInDownloadsUi(true); apkName = parse.getLastPathSegment(); // 设置下载后文件存放的位置 initAPKDir(); down.setDestinationInExternalFilesDir(this, APK_dir, apkName); // 将下载请求放入队列 manager.enqueue(down); //注册下载广播 registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if(intent!=null){ APK_url = intent.getStringExtra("apk_url"); // 调用下载 initDownManager(); } return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { // 注销下载广播 if (receiver != null) unregisterReceiver(receiver); super.onDestroy(); } // 接受下载完成后的intent class DownloadCompleteReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //判断是否下载完成的广播 if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) { //获取下载的文件id long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); Log.d("kodulf","id="+downId); //自动安装apk if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { Uri uriForDownloadedFile = manager.getUriForDownloadedFile(downId); Log.d("kodulf","uri="+uriForDownloadedFile); installApkNew(uriForDownloadedFile); } //停止服务并关闭广播 UpdateService.this.stopSelf(); } } //安装apk protected void installApkNew(Uri uri) { Intent intent = new Intent(); //执行动作 intent.setAction(Intent.ACTION_VIEW); //执行的数据类型 // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // intent.setDataAndType(uri, "application/vnd.android.package-archive"); //不加下面这句话是可以的,查考的里面说如果不加上这句的话在apk安装完成之后点击单开会崩溃 // android.os.Process.killProcess(android.os.Process.myPid()); String path = getRealFilePath(getApplication(),uri); File apkFile = new File(path); //Android 7.0 系统共享文件需要通过 FileProvider 添加临时权限,否则系统会抛出 FileUriExposedException . if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri contentUri = FileProvider.getUriForFile(getApplication(),"com.vipcarehealthservice.e_lap.provider",apkFile); intent.setDataAndType(contentUri,"application/vnd.android.package-archive"); }else { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType( Uri.fromFile(apkFile),"application/vnd.android.package-archive"); } try { startActivity(intent); }catch (Exception e){ e.printStackTrace(); } } } private void initAPKDir() { /** * 创建路径的时候一定要用[/],不能使用[\],但是创建文件夹加文件的时候可以使用[\]. * [/]符号是Linux系统路径分隔符,而[\]是windows系统路径分隔符 Android内核是Linux. */ String APK_dir_old = ""; if (isHasSdcard())// 判断是否插入SD卡 APK_dir_old = getApplicationContext().getFilesDir().getAbsolutePath() + "/apk/download/";// 保存到app的包名路径下 else APK_dir_old = Environment.getExternalStorageDirectory().getAbsolutePath() + ClapConstant.DOWNLOAD_APK ;//"/apk/download/";// 保存到SD卡路径下 File outputfile = new File(APK_dir_old); Uri apkuri ; if (Build.VERSION.SDK_INT >= 24){ apkuri = FileProvider.getUriForFile(this, "com.vipcarehealthservice.e_lap.provider", //可以是任意字符串 outputfile); }else{ apkuri = Uri.fromFile(outputfile); } APK_dir = getRealFilePath(this,apkuri); File destDir = new File(APK_dir,apkName); if (!destDir.exists()) {// 判断文件夹是否存在 destDir.mkdirs(); } } /** * * @Description:判断是否插入SD卡 */ private boolean isHasSdcard() { String status = Environment.getExternalStorageDirectory().getAbsolutePath(); if (status.equals(Environment.MEDIA_MOUNTED)) { return true; } else { return false; } } /** * Try to return the absolute file path from the given Uri * * @param context * @param uri * @return the file path or null */ public static String getRealFilePath( final Context context, final Uri uri ) { if ( null == uri ) return null; final String scheme = uri.getScheme(); String data = null; if ( scheme == null ) data = uri.getPath(); else if ( ContentResolver.SCHEME_FILE.equals( scheme ) ) { data = uri.getPath(); } else if ( ContentResolver.SCHEME_CONTENT.equals( scheme ) ) { Cursor cursor = context.getContentResolver().query( uri, new String[] { MediaStore.Images.ImageColumns.DATA }, null, null, null ); if ( null != cursor ) { if ( cursor.moveToFirst() ) { int index = cursor.getColumnIndex( MediaStore.Images.ImageColumns.DATA ); if ( index > -1 ) { data = cursor.getString( index ); } } cursor.close(); } } return data; } }
mxl创建文件 file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path path="" name="camera_photos" />
<external-cache-path path="app/" name="apk"/>
</paths>
</resources>
AndroidManifest.xml 里面配置
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<!--提供共享路径-->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
关于7.0路劲问题参考
https://blog.csdn.net/c__chao/article/details/65437099