Android APP update download, realize progress notification in Notification bar, click install after download is complete

 Simply make a small tool for APP to detect updates, which is a bit rough. You can’t resume the upload at any time. It’s just for personal feeling that it’s not necessary. You can add more functions according to your ideas. This is just for beginners and simple people like me.

   The effect is as follows:

    

    The basic idea first, take my actual development as an example: First of all, of course, we need a network to request our server, get the apk version information and download path in the warehouse, and compare it with your current version number. If the version number is smaller than the version number in the warehouse, the user is prompted to download, and the download intensity operation is performed according to the update level (whether the download is forced or something). At the next time, monitor the progress of the file download to update the progress bar and progress information in the notification. When the download is completed, the user can click (close the notification) to enter the installation apk interface, so that it is completed.

    This time I used the okhttp (okgo) network framework to download the files. I made sure to download the apk without filtering information, just download and install it directly.

The first thing that comes to mind is to use a singleton for download management, we need to pass in a context.

  Context context;
    private static final AppUpdateService INSTANCE = new AppUpdateService();
 
    private static class LazyHolder {
        public static AppUpdateService getThis(Context context) {
            INSTANCE.context = context;
            return INSTANCE;
        }
    }
 
    public static AppUpdateService getInstance(Context context) {
        return LazyHolder.getThis(context);
    }
初始化Notification 、notificationCompat.Builder和notificationManager 

//Initial notification
    private void initNotification() {         notificationManager = (NotificationManager) MyApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);         builder = new NotificationCompat.Builder(MyApplication.getInstance());         builder.setContentTitle("Update. ..") //Set the notification                 title.setSmallIcon(R.mipmap.ic_launcher_round)                 .setLargeIcon(BitmapFactory.decodeResource(MyApplication.getInstance().getResources(), R.mipmap.ic_launcher_round)) //Set the large icon of the notification                 . setDefaults(Notification.DEFAULT_LIGHTS) //Set the reminder method of the notification: Breathing                 light.setPriority(NotificationCompat.PRIORITY_MAX) //Set the priority of the notification:                 maximum.setAutoCancel(false)//Set whether the notification is automatically canceled when clicked once








                .setContentText("Download progress:" + "0%")
                .setProgress(100, 0, false);
        notification = builder.build();//build notification object
    }
Download and update the core code of notification, you can directly choose whether to update Let the user click to install, or install directly.

public void download(String url, String filePath) {         MyApplication.getInstance().okGo.<File>post(url).execute(new FileCallback() {             @Override             public void onSuccess(Response<File> response) {                 File file = response.body();                 Log.e("update", "onSuccess: download complete" + file.getPath() + file.getName());                 builder.setContentTitle("download complete")                         .setContentText("click to install" )                         .setAutoCancel(true);//Set whether the notification is automatically canceled when clicked once                 //Click to install the code block                 Intent intent = new Intent(Intent.ACTION_VIEW);                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 











                intent.setDataAndType(Uri.parse("file://" + file.toString()), "application/vnd.android.package-archive");
                PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);
                notification = builder.setContentIntent(pi).build();
                notificationManager.notify(1, notification);
 
                //自动安装
//              installApk(file);
            }
 
            //下载进度
            @Override
            public void downloadProgress(Progress progress) {
                super.downloadProgress(progress);
                Log.e("update", "downloadProgress: " + progress.fraction);
                builder.setProgress(100, (int) (progress.fraction * 100), false);
                builder.setContentText("下载进度:" + (int) (progress.fraction * 100) + "%");
                notification = builder.build();
                notificationManager.notify(1, notification);
            }
 
            @Override
            public void onStart(Request<File, ? extends Request> request) {
                super.onStart(request);
                initNotification();
            }
 
            @Override
            public void onError(Response<File> response) {
                super.onError(response);
                Toast.makeText(context, "Download error", Toast.LENGTH_SHORT).show();
            }
 
        });
 
    }
Install apk

    private void installApk(File file) {         //New download apk file storage address         File apkFile = file;         Intent intent = new Intent(Intent.ACTION_VIEW);         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);         intent.setDataAndType(Uri.parse(" file://" + apkFile.toString()), "application/vnd.android.package-archive");         context.startActivity(intent);         notificationManager.cancel(1);//Cancel notification     } Get the local version number







 

  public int getVersionCode() {         PackageManager packageManager = context.getPackageManager();         int versionCode = 0;         try {             PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);             versionCode = packageInfo.versionCode;         } catch (PackageManager.NameNotFoundException e) {             e.printStackTrace();         }         return versionCode;     } Get updated information and modify it according to your own network framework.










 public void getUpdate() {         MyApplication.getInstance().okGo.<String>post("*****").execute(new StringCallback() {             @Override             public void onSuccess(Response<String> response) {                 ApkSer apkSer = new ApkSer();                     apkSer = new Gson().fromJson(response.body(), ApkSer.class);                 CustomDialog("A new version needs to be updated", 3, apkSer.getUpdatePath());             }         });     } The prompt box information prompts the user.
 








 

 public void CustomDialog(final String cominit, int updatelv, final String url) {         CustomDialog.Builder dialog = new CustomDialog.Builder(context);         dialog.setTitle("Version Update")                 .setMessage(cominit);         dialog.setCancelable(false) ;         //Update level 0: Normal 1: Key bug fix update 2: New function update 3: Configuration update 4: Special update, forcing users to update         if (updatelv == 0 || updatelv == 2) {             dialog.setCancelBtn(" Next reminder", new DialogInterface.OnClickListener() {                 @Override                 public void onClick(DialogInterface dialog, int i) {                     dialog.dismiss();                 }             });         } else {













            dialog.setCanceledOnTouchOutside(false);
        }
        dialog.setCancelBtn("Key Update", new DialogInterface.OnClickListener() {             @Override             public void onClick(DialogInterface dialog, int i) {                 Toast.makeText(context,"Added to download task" ,Toast.LENGTH_SHORT).show();                 dialog.dismiss();                 download(url, "path");             }         });         dialog.create().show();     } Version information object field









public class ApkSer {         public String type; //Update content type, apk installation package res resource         public String apkName;         public String packageName; //apk package name         public Long versionCode; //library version number         public String versionName; //library version name         public int important; //Update level 0: Normal 1: Key bug fix update 2: New feature update 3: Configuration update 4: Special update, forcing users to update         public String commit; //Update content         public String updatePath; //Update download Address         public String updateTime; //Update time } The complete code is as follows, welcome to comment.










import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
 
import com.google.gson.Gson;
import com.hx.view.widget.CustomDialog;
import com.lzy.okgo.callback.FileCallback;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Progress;
import com.lzy.okgo.model.Response;
import com.lzy.okgo.request.base.Request;
import com.pay.library.config.AppConfig;
import com.yhx .loan.R;
import com.yhx.loan.base.MyApplication;
 
import java.io.File;
 
public class AppUpdateService {     private NotificationManager notificationManager;     private Notification notification; //Download notification progress prompt     private NotificationCompat.Builder builder;     private boolean flag = false; //Send notification after the progress box disappears     public static boolean isUpdate = false; //Is the     context context being updated ;     private static final AppUpdateService INSTANCE = new AppUpdateService();
 





 


 
    private static class LazyHolder {
        public static AppUpdateService getThis(Context context) {
            INSTANCE.context = context;
            return INSTANCE;
        }
    }
 
    public static AppUpdateService getInstance(Context context) {
        return LazyHolder.getThis(context);
    }
 
    private AppUpdateService() {
 
    }
 
    public void getUpdate() {
 
        MyApplication.getInstance().okGo.<String>post(AppConfig.updateAPP_url)
               .upJson("{'package':'包名'}")
                .execute(new StringCallback() {
            @Override
            public void onSuccess(Response<String> response) {                 ApkSer apkSer = new ApkSer();                     apkSer = new Gson().fromJson(response.body(), ApkSer.class);                 CustomDialog("A new version needs to be updated", 3 , apkSer.getUpdatePath());             }         });     }     public void CustomDialog(final String cominit, int updatelv, final String url) {         CustomDialog.Builder dialog = new CustomDialog.Builder(context);         dialog.setTitle("Version update" )                 .setMessage(cominit);         dialog.setCancelable(false);         //Update level 0: Normal 1: Key bug fix update 2: New feature update 3: Configuration update 4: Special update, mandatory user update         if (updatelv == 0 || updatelv == 2) {





 

 







            dialog.setCancelBtn("下次提醒", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int i) {
                    dialog.dismiss();
                }
            });
        } else {
            dialog.setCanceledOnTouchOutside(false);
        }
        dialog.setCancelBtn("重点更新", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int i) {
                Toast.makeText(context,"已添加到下载任务",Toast.LENGTH_SHORT).show();
                dialog.dismiss();
                download(url, "path");
            }
        });
        dialog.create().show();
    }
 
 
    //Initialize notification
    private void initNotification() {         notificationManager = (NotificationManager) MyApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);         builder = new NotificationCompat.Builder( MyApplication.getInstance());         builder.setContentTitle("Update...") //Set the notification                 title.setSmallIcon(R.mipmap.ic_launcher_round)                 .setLargeIcon(BitmapFactory.decodeResource(MyApplication.getInstance().getResources(), R.mipmap.ic_launcher_round)) //Set the large notification icon.                 setDefaults(Notification.DEFAULT_LIGHTS) //Set the notification method: breathing light






                .setPriority(NotificationCompat.PRIORITY_MAX) //Set the priority of the notification:
                maximum.setAutoCancel(false)//Set whether the notification is automatically canceled when
                clicked once.setContentText("Download progress:" + "0%")
                .setProgress(100, 0, false);
        notification = builder.build();//Build notification object
    }
 
    public void download(String url, String filePath) {         MyApplication.getInstance().okGo.<File>post(url).execute(new FileCallback () {             @Override             public void onSuccess(Response<File> response) {                 File file = response.body();                 Log.e("update", "onSuccess: download complete" + file.getPath() + file.getName( ));                 builder.setContentTitle("Download complete")
 






                        .setContentText("Click to install")
                        .setAutoCancel(true);//Set whether the notification is automatically canceled when clicked once
 
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.setDataAndType(Uri. parse("file://" + file.toString()), "application/vnd.android.package-archive");
                PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);
                notification = builder.setContentIntent (pi).build();
                notificationManager.notify(1, notification);
 
                //Automatic installation
// installApk(file);
            }
 
            //Download progress
            @Override
            public void downloadProgress(Progress progress) {
                super.downloadProgress(progress);
                Log.e("update", "downloadProgress: " + progress.fraction);
                builder.setProgress(100, (int) (progress.fraction * 100), false);
                builder.setContentText("下载进度:" + (int) (progress.fraction * 100) + "%");
                notification = builder.build();
                notificationManager.notify(1, notification);
            }
 
            @Override
            public void onStart(Request<File, ? extends Request> request) {
                super.onStart(request);
                initNotification();
            }
 
            @Override
            public void onError(Response<File> response) {
                super.onError(response);
                Toast.makeText(context, "下载错误", Toast.LENGTH_SHORT).show();
            }
 
        });
 
    }
 
    /**
     * 安装apk
     */
    private void installApk(File file) {
        //新下载apk文件存储地址
        File apkFile = file;
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(Uri.parse("file://" + apkFile.toString()), "application/vnd.android.package-archive");
        context.startActivity(intent);
        notificationManager.cancel(1);//取消通知
 
    }
 
    /**
     * 获取本地版本号
     *
     * @return
     */
    public  int getVersionCode() {
        PackageManager packageManager = context.getPackageManager();
        int versionCode = 0;
        try {
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            versionCode = packageInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return versionCode;
    }
 
}
 
Finally, I found that API>=24 is definitely not working with this method. For file:///storage/emulated/0/xxx, android N file access crash android.os.FileUriExposedException. If you want to go online, you will not repeat the introduction in many ways. Please see the introduction of the following bloggers.

https://blog.csdn.net/honjane/article/details/54411820
https://blog.csdn.net/ruancoder/article/details/67639621
https://blog.csdn.net/xiaoyu940601/article/details/54406725

Finally found for the file:///storage/emulated/0/xxx/... file. The path in our filepaths.xml must have the xxx path, so that the file can be found without error. I don't know too much. Anyway, the problem of error reporting is finally solved.
 

Guess you like

Origin blog.csdn.net/qq_26280383/article/details/115064168