Android在app内部请求服务器apk更新版本

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
首先需要添加权限,否则下载完成之后是无法跳转到安装页面的

 <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /><!-- 自动更新URI跳转安装时需要 -->

1:请求接口如有新版本则提示更新(第一张图)

  if (data.getMsg().equals("有新版本") && appUpdateBean != null) {
                        AppUpdateDialog dialog = new AppUpdateDialog(MainActivity.this, "发现新版本", appUpdateBean.getLevel(), appUpdateBean.getCreatetime(), appUpdateBean.getContent(), "", "立即更新", new OnButtonClick() {
                            @Override
                            public void button01ClickListener() {

                            }

                            @Override
                            public void button02ClickListener() {
                                //立即更新
                                Log.v(TAG, "url==" + appUpdateBean.getUrl());
                                if (appUpdateBean.getUrl() == null) {
                                    return;
                                }
//                                AppUpdateUtils.dialogUpdateVersion(appUpdateBean.getUrl(), MainActivity.this);
                                AppUpdateUtils.downLoadApk(MainActivity.this, appUpdateBean.getUrl());
                            }
                        });
                        dialog.show();
                        dialog.setCanceledOnTouchOutside(false);
                        dialog.setCancelable(false);
                    }

/**
 * date:2020/8/4
 * author:wsm(Administrator)
 * funcation:版本更新
 */
public class AppUpdateDialog extends Dialog {
    public static final String TAG = "AppUpdateDialog";
    private Activity mActivity;
    private String title;
    private String versionname;
    private String time;
    private String content;
    private String button1Text;
    private String button2Text;
    private OnButtonClick onButtonClicks;
    private RelativeLayout mRl_progress;
    private ProgressBar mProgressBar;
    private TextView mTxt_progess;

    public AppUpdateDialog(Activity context, String title, String version, String cratetime, String content, String button1Text,
                           String button2Text, final OnButtonClick onButtonClick) {
        super(context, R.style.MyDialog);
        mActivity = context;
        this.title = title;
        this.versionname = version;
        this.time = cratetime;
        this.content = content;
        this.button1Text = button1Text;
        this.button2Text = button2Text;
        this.onButtonClicks = onButtonClick;

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.public_updateapp);
        TextView tv_title = (TextView) findViewById(R.id.tv_title);
        TextView tv_version = (TextView) findViewById(R.id.tv_version);
        TextView tv_time = (TextView) findViewById(R.id.tv_time);
        TextView tv_content = (TextView) findViewById(R.id.tv_content);
        TextView tv_ok = (TextView) findViewById(R.id.tv_ok);
        mRl_progress = (RelativeLayout) findViewById(R.id.rl_progress);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mTxt_progess = (TextView) findViewById(R.id.txt_progess);
        tv_title.setText(title);
        tv_version.setText(versionname);
        tv_time.setText(time);
        tv_content.setText(content);
        tv_ok.setText("立即更新");
        initBroadcastListener();

        tv_ok.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_ok.setText("正在更新,请稍等。。。");
                onButtonClicks.button02ClickListener();
            }
        });
    }

    /**
     * 接收广播监听下载进度
     */
    private void initBroadcastListener() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("STATUS_RUNNING");
        BroadcastReceiver Receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction().equals("STATUS_RUNNING")) {
                    String progress = intent.getStringExtra("progress");
                    if (Integer.parseInt(progress) > 0) {
                    //下载进度大于1则显示进度条
                        mRl_progress.setVisibility(View.VISIBLE);
                        mProgressBar.setProgress(Integer.parseInt(progress));
                        mTxt_progess.setText(progress + "%");
                    }


                }
            }
        };
        mActivity.registerReceiver(Receiver, intentFilter);
    }

}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rlcommon"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:background="@drawable/white10"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:gravity="center"
            android:paddingTop="10dp"
            android:text="提示"
            android:textColor="@color/txt0"
            android:textSize="18sp"
            android:visibility="visible" />


        <TextView
            android:id="@+id/tv_version"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/tv_time"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:textSize="14sp" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="15dp"
            android:background="@color/search" />

        <RelativeLayout
            android:id="@+id/rl_progress"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:visibility="gone">

            <ProgressBar
                android:id="@+id/progressBar"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="3dp"
                android:layout_centerVertical="true"
                android:layout_marginRight="5dp"
                android:layout_toLeftOf="@id/txt_progess"
                android:progressDrawable="@drawable/progressbar_carch" />

            <TextView
                android:id="@+id/txt_progess"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:text="0%"
                android:textColor="@color/txtblack" />
        </RelativeLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:padding="5dp">

            <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:visibility="gone">

                <TextView
                    android:id="@+id/tv_cancel"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:gravity="center"
                    android:padding="10dp"
                    android:text="否"
                    android:textSize="14sp" />
            </RelativeLayout>

            <TextView
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:background="@color/search" />

            <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1">

                <TextView
                    android:id="@+id/tv_ok"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:gravity="center"
                    android:padding="10dp"
                    android:text="立即更新"
                    android:textColor="@color/txt0"
                    android:textSize="16sp" />

            </RelativeLayout>

        </LinearLayout>
    </LinearLayout>
</RelativeLayout>

2:点击立即更新(第二张图)

public class AppUpdateUtils {
    public static final String TAG = "AppUpdateUtils";

    private static long mId;
    private static DownloadManager mDownloadManager;
    private static Activity mActivity;

    public static void downLoadApk(Activity activity, String url) {
        mActivity = activity;
        //以下两行代码可以让下载的apk文件被直接安装而不用使用Fileprovider,系统7.0或者以上才启动。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            StrictMode.VmPolicy.Builder localBuilder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(localBuilder.build());
        }
        //创建request对象
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        //设置什么网络情况下可以下载
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
        //设置通知栏的标题
        request.setTitle("下载");
        //设置通知栏的message
        request.setDescription("应用正在下载.....");

        //7.0以上的系统适配
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            request.setRequiresDeviceIdle(false);
            request.setRequiresCharging(false);
        }

        //制定下载的文件类型为APK
        request.setMimeType("application/vnd.android.package-archive");
        //设置漫游状态下是否可以下载
        request.setAllowedOverRoaming(false);

        // 下载过程和下载完成后通知栏有通知消息。
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE | DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

        //大于11版本手机允许扫描
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            //表示允许MediaScanner扫描到这个文件,默认不允许。
            request.allowScanningByMediaScanner();
        }

        //设置文件存放目录
        request.setDestinationInExternalFilesDir(activity, Environment.DIRECTORY_DOWNLOADS, "update.apk");
        //获取系统服务
        mDownloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
        //进行下载
        //注册广播接收者,监听下载状态
        mId = mDownloadManager.enqueue(request);
        activity.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
         //用于监听显示下载进度
        mDownloadObserver = new DownloadChangeObserver(null);
        mActivity.getContentResolver().registerContentObserver(CONTENT_URI, true, mDownloadObserver);
    }


    //广播监听下载的各个状态
    private static BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            checkStatus();
        }
    };

    //检查下载状态
    private static void checkStatus() {
        DownloadManager.Query query = new DownloadManager.Query();
        //通过下载的id查找
        query.setFilterById(mId);
        Cursor cursor = mDownloadManager.query(query);
        if (cursor.moveToFirst()) {
            int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
            switch (status) {
                //下载暂停
                case DownloadManager.STATUS_PAUSED:
                    Log.v(TAG, "checkStatus 下载暂停");

                    break;
                //下载延迟
                case DownloadManager.STATUS_PENDING:

                    Log.v(TAG, "checkStatus 下载延迟");
                    break;
                //正在下载
                case DownloadManager.STATUS_RUNNING:

                    Log.v(TAG, "checkStatus 正在下载");
                    break;
                //下载完成
                case DownloadManager.STATUS_SUCCESSFUL:
                    ToastUtil.show("下载完成");
                    Log.v(TAG, "checkStatus 下载完成");
                    //下载完成安装APK
                    installAPK();
//                    cursor.close();
                    break;
                //下载失败
                case DownloadManager.STATUS_FAILED:
                    Log.v(TAG, "checkStatus 下载失败");
                    ToastUtil.show("下载失败");
//                    cursor.close();
                    mActivity.unregisterReceiver(receiver);
                    break;
            }
        }
    }
   //用于显示下载进度
    static class DownloadChangeObserver extends ContentObserver {

        public DownloadChangeObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(mId);
            DownloadManager dManager = (DownloadManager) mActivity.getSystemService(Context.DOWNLOAD_SERVICE);
            final Cursor cursor = dManager.query(query);
            if (cursor != null && cursor.moveToFirst()) {
                final int totalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
                final int currentColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
                int totalSize = cursor.getInt(totalColumn);
                int currentSize = cursor.getInt(currentColumn);
                float percent = (float) currentSize / (float) totalSize;
                int progress = Math.round(percent * 100);
                Log.v(TAG, "下载进度==" + progress);
                //发送广播进行界面显示
                Intent intent = new Intent("STATUS_RUNNING");
                intent.putExtra("progress", progress + "");
                mActivity.sendBroadcast(intent);
            }
        }
        
    }
    private static void installAPK() {
        Log.v(TAG, "installAPK 正在安装");
        // 由于没有在Activity环境下启动Activity,设置下面的标签
        //Android 7.0以上要使用FileProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Log.v(TAG, "Build.VERSION.SDK_INT>=24");
            //下载的路径
            File file = new File(mActivity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "update.apk");
            Log.v(TAG, "file==" + file);
            //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
            Uri apkUri = FileProvider.getUriForFile(mActivity, "这里是你的清单文件中配置包名.fileprovider", file);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
            mActivity.startActivity(intent);
        } else {
            Log.v(TAG, "老方法");
            //以前的启动方法
            File file = new File(mActivity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "update.apk");
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            mActivity.startActivity(install);
        }
    }


}

3:配置清单文件相关

  <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="app包名.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>

4:res文件下新建xml文件夹,新建filepaths
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path
            name="download"
            path="" />
    </paths>
</resources>

5:注意加入需要的权限,例如存储权限网络权限等。。
到这里效果就实现了,当下载完成后打开系统自带更新页面安装app即可

另外一种方式逻辑为跳转应用市场更新
app版本跳转应用市场更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值