安卓自更新,兼容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
原文地址:https://www.cnblogs.com/Android-FJH/p/8820096.html