Descarga de la actualización de la aplicación de Android, realice la notificación de progreso en la barra de notificaciones, haga clic en instalar después de que se complete la descarga

 Simplemente crea una pequeña herramienta para que la aplicación detecte actualizaciones, lo cual es un poco tosco. No puede reanudar la carga en ningún momento. Es solo por un sentimiento personal de que no es necesario. Puede agregar más funciones de acuerdo con sus ideas. Esto es solo para principiantes y personas simples como yo.

   El efecto es el siguiente:

    

    La idea básica primero, tome mi desarrollo real como ejemplo: primero que todo, por supuesto, necesitamos una red para solicitar nuestro servidor, obtener la información de la versión apk y la ruta de descarga en el almacén, y compararla con su número de versión actual. Si el número de versión es menor que el número de versión en el almacén, se solicita al usuario que descargue y la operación de intensidad de descarga se realiza de acuerdo con el nivel de actualización (si la descarga es forzada o algo así). La próxima vez, supervise el progreso de la descarga del archivo para actualizar la barra de progreso y la información de progreso en la notificación. Cuando se complete la descarga, el usuario puede hacer clic en (cerrar la notificación) para ingresar a la interfaz de instalación del apk, de modo que esté terminado.

    Esta vez usé el framework de red okhttp (okgo) para descargar los archivos, me aseguré de descargar el apk sin filtrar información, solo descárgalo e instálalo directamente.

Lo primero que me viene a la mente es usar un singleton para la gestión de descargas, necesitamos pasar en un contexto.

  Contexto de contexto;
    AppUpdateService final estático privado INSTANCE = new AppUpdateService ();
 
    private static class LazyHolder {         public static AppUpdateService getThis (contexto de contexto) {             INSTANCE.context = context;             volver INSTANCIA;         }     }     getInstance público estático de AppUpdateService (contexto de contexto) {         return LazyHolder.getThis (contexto);     }初始化 Notificación 、 notificationCompat.Builder 和 notificationManager 





 



// Notificación inicial
    private void initNotification () {         notificationManager = (NotificationManager) MyApplication.getInstance (). GetSystemService (Context.NOTIFICATION_SERVICE);         builder = new NotificationCompat.Builder (MyApplication.getInstance ());         builder.setContentTitle ("Update. . ") // Establecer el                 título de notificación.setSmallIcon (R.mipmap.ic_launcher_round)                 .setLargeIcon (BitmapFactory.decodeResource (MyApplication.getInstance (). GetResources (), R.mipmap.ic_launcher_round)) // Establecer el icono grande del notification                 . setDefaults (Notification.DEFAULT_LIGHTS) // Establecer el método de recordatorio de la notificación: Breathing                 light.setPriority (NotificationCompat.PRIORITY_MAX) // Establecer la prioridad de la notificación:                 maximum.setAutoCancel (false) // Establecer si la notificación es automática cancelado cuando se hace clic una vez








                .setContentText ("Progreso de la descarga:" + "0%")
                .setProgress (100, 0, false);
        notification = builder.build (); // crear objeto de notificación
    }
Descarga el código central de la notificación de actualización, puedes elegir directamente si para actualizar Permita que el usuario haga clic para instalar o instalar directamente.

descarga pública void (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 ("haga clic para instalar ")                         .setAutoCancel (true); // Establecer si la notificación se cancela automáticamente cuando se hace clic una vez                 // Haga clic para instalar el bloque de código                 Intent intent = new Intent (Intent.ACTION_VIEW);                 intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
 











                intent.setDataAndType (Uri.parse ("archivo: //" + archivo.toString ()), "aplicación / vnd.android.package-archive");
                PendingIntent pi = PendingIntent.getActivity (contexto, 0, intención, 0);
                notificación = builder.setContentIntent (pi) .build ();
                notificationManager.notify (1, notificación);
 
                // 自动 安装
// installApk (archivo);
            }
 
            // 下载 进度
            @Override
            public void downloadProgress (Progreso de progreso) {                 super.downloadProgress (progreso);                 Log.e ("actualización", "downloadProgress:" + progress.fraction);


                builder.setProgress (100, (int) (progress.fraction * 100), falso);
                builder.setContentText ("下载 进度:" + (int) (progress.fraction * 100) + "%");
                notificación = constructor.build ();
                notificationManager.notify (1, notificación);
            }
 
            @Override
            public void onStart (Solicitud <Archivo,? Extiende Solicitud> solicitud) {                 super.onStart (solicitud);                 initNotification ();             }             @Override             public void onError (Response <File> response) {                 super.onError (respuesta);



 



                Toast.makeText (contexto, "Error de descarga", Toast.LENGTH_SHORT) .show ();
            }
 
        });
 
    }
Instalar apk

    private void installApk (File file) {         // Nueva descarga de la dirección de almacenamiento del archivo apk         Archivo 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); // Cancelar notificación     } Obtén el número de versión local







 

  public int getVersionCode () {         PackageManager packageManager = context.getPackageManager ();         int versionCode = 0;         intente {             PackageInfo packageInfo = packageManager.getPackageInfo (context.getPackageName (), 0);             versionCode = packageInfo.versionCode;         } catch (PackageManager.NameNotFoundException e) {             e.printStackTrace ();         }         return versionCode;     } Obtenga información actualizada y modifíquela de acuerdo con su propio marco de red.










 public void getUpdate () {         MyApplication.getInstance (). okGo. <String> post ("*****"). execute (new StringCallback () {             @Override             public void onSuccess (Response <String> respuesta) {                 ApkSer apkSer = new ApkSer ();                     apkSer = new Gson (). fromJson (response.body (), ApkSer.class);                 CustomDialog ("Es necesario actualizar una nueva versión", 3, apkSer.getUpdatePath ());             }         }) ;     } La información del cuadro de aviso solicita al usuario.
 








 

 public void CustomDialog (cadena final cominit, int actualizadorv, cadena final url) {         CustomDialog.Builder dialog = new CustomDialog.Builder (contexto);         dialog.setTitle ("Actualización de versión")                 .setMessage (cominit);         dialog.setCancelable (false) ;         // Nivel de actualización 0: Normal 1: Actualización de corrección de errores clave 2: Actualización de nueva función 3: Actualización de configuración 4: Actualización especial, lo que obliga a los usuarios a actualizar         if (updates == 0 || updates == 2) {             dialog.setCancelBtn ( "Siguiente recordatorio", nuevo 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, "Agregado a la tarea de descarga", Toast.LENGTH_SHORT) .show ();                 dialog.dismiss ();                 download (url, "path");             }         });         dialog.create (). Show ();     } Campo de objeto de información de versión









public class ApkSer {         public String type; // Actualizar el tipo de contenido, paquete de instalación apk res resource         public String apkName;         public String packageName; // apk nombre del paquete         public Long versionCode; // número de versión de la biblioteca         public String versionName; // nombre de la versión de la biblioteca         public int important; // Nivel de actualización 0: Normal 1: Actualización de corrección de errores clave 2: Actualización de nueva función 3: Actualización de configuración 4: Actualización especial, que obliga a los usuarios a actualizar         el compromiso de cadena pública; // Actualizar contenido         public String updatePath; // Actualizar download Address         public String updateTime; // Update time } El código completo es el siguiente, bienvenido a comentar.










importar android.app.Notification;
import android.app.NotificationManager;
importar android.app.PendingIntent;
importar android.content.Context;
importar android.content.DialogInterface;
importar android.content.Intent;
importar android.content.pm.PackageInfo;
importar android.content.pm.PackageManager;
importar android.graphics.BitmapFactory;
importar android.net.Uri;
importar android.support.v4.app.NotificationCompat;
importar android.util.Log;
importar 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; notificación de notificación     privada; //     Aviso de progreso de notificación de descarga generador privado NotificationCompat.Builder;     marca booleana privada = false; // Envíe una notificación después de que desaparezca el cuadro de progreso y marque     public static boolean isUpdate = false; // ¿Se está actualizando el     contexto de contexto?     Private static final AppUpdateService INSTANCE = new AppUpdateService ();
 





 


 
    private static class LazyHolder {         public static AppUpdateService getThis (contexto de contexto) {             INSTANCE.context = context;             volver INSTANCIA;         }     }     getInstance público estático de AppUpdateService (contexto de contexto) {         return LazyHolder.getThis (contexto);     }     private AppUpdateService () {     }     public void getUpdate () {         MyApplication.getInstance (). okGo. <String> publicación (AppConfig.updateAPP_url)                .upJson ("{'paquete': '包 名'}")                 .execute (nuevo StringCallback () {             @Override





 



 

 

 

 




            public void onSuccess (Response <String> response) {                 ApkSer apkSer = new ApkSer ();                     apkSer = new Gson (). fromJson (response.body (), ApkSer.class);                 CustomDialog ("Es necesario actualizar una nueva versión" , 3, apkSer.getUpdatePath ());             }         });     }     public void CustomDialog (cadena final cominit, int update, final String url) {         CustomDialog.Builder dialog = new CustomDialog.Builder (contexto);         dialog.setTitle ("Versión update ")                 .setMessage (cominit);         dialog.setCancelable (false);         // Nivel de actualización 0: Normal 1: Actualización de corrección de errores clave 2: Actualización de nueva función 3: Actualización de configuración 4: Actualización especial, actualización obligatoria para el usuario         si (updatedv = = 0 || actualizatelv == 2) {





 

 







            dialog.setCancelBtn ("下次 提醒", nuevo DialogInterface.OnClickListener () {                 @Override                 public void onClick (DialogInterface dialog, int i) {                     dialog.dismiss ();                 }             });         } else {             dialog.setCanceledOnTouchOutside (falso);         }         dialog.setCancelBtn ("重点 更新", new DialogInterface.OnClickListener () {             @Override             public void onClick (DialogInterface dialog, int i) {                 Toast.makeText (context, "已 添加 到 下载 任务", Toast.LENGTH_SHORT) .show ();                 dialog.dismiss ();                 descargar (url, "ruta"














            }
        });
        dialog.create (). show ();
    }
 
 
    // Inicializar notificación
    private void initNotification () {         notificationManager = (NotificationManager) MyApplication.getInstance (). getSystemService (Context.NOTIFICATION_SERVICE);         constructor = nuevo NotificationCompat.Builder ( MyApplication.getInstance ());         builder.setContentTitle ("Actualizar ...") // Establecer el                 título de la notificación.setSmallIcon (R.mipmap.ic_launcher_round)                 .setLargeIcon (BitmapFactory.decodeResource (MyApplication.getInstance (). GetResources (), R.mipmap.ic_launcher_round)) // Establecer el icono de notificación grande.                 SetDefaults (Notification.DEFAULT_LIGHTS) // Establecer el método de notificación: luz de respiración






                .setPriority (NotificationCompat.PRIORITY_MAX) // Establezca la prioridad de la notificación:
                máxima.setAutoCancel (false) // Establezca si la notificación se cancela automáticamente cuando se
                hace clic una vez.setContentText ("Progreso de la descarga:" + "0%")
                .setProgress (100, 0, falso);
        notificación = builder.build (); // Crear objeto de notificación
    }
 
    descarga pública void (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 ("Descarga completa")
 






                        .setContentText ("Haga clic para instalar")
                        .setAutoCancel (true); // Establezca si la notificación se cancela automáticamente cuando se hace clic una vez
 
                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 (contexto, 0, intención, 0);
                notificación = builder.setContentIntent (pi) .build ();
                notificationManager.notify (1, notificación);
 
                // Instalación automática
// installApk (archivo);
            }
 
            // Progreso de descarga
            @Override
            downloadProgress public void (progreso de progreso) {                 super.downloadProgress (progreso);                 Log.e ("actualización", "downloadProgress:" + progress.fraction);                 builder.setProgress (100, (int) (progress.fraction * 100), falso);                 builder.setContentText ("下载 进度:" + (int) (progress.fraction * 100) + "%");                 notificación = constructor.build ();                 notificationManager.notify (1, notificación);             }             @Override             public void onStart (Solicitar <Archivo,? Extiende Solicitud> solicitud) {                 super.onStart (solicitud);                 initNotification ();







 





 
            @Override
            public void onError (Response <File> response) {                 super.onError (respuesta);                 Toast.makeText (contexto, "下载 错误", Toast.LENGTH_SHORT) .show ();             }         });     }     / **      * 安装 apk      * /     private void installApk (Archivo de archivo) {         // 新 下载 apk 文件 存储 地址         Archivo apkFile = archivo;         Intención Intención = nueva Intención (Intent.ACTION_VIEW);         intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);         intent.setDataAndType (Uri.parse ("archivo: //" + apkFile.toString ()), "aplicación / vnd.android.package-archive");         context.startActivity (intención);



 

 

 










        notificationManager.cancel (1); // 取消 通知
 
    }
 
    / **
     * 获取 本地 版本 号
     *
     * @return
     * /
    public int getVersionCode () {         PackageManager packageManager = context.getPackageManager ();         int versionCode = 0;         intente {             PackageInfo packageInfo = packageManager.getPackageInfo (context.getPackageName (), 0);             versionCode = packageInfo.versionCode;         } captura (PackageManager.NameNotFoundException e) {             e.printStackTrace ();         }         return versionCode;     } }










 

 
Finalmente, encontré que API> = 24 definitivamente no funciona con este método. Para file: /// storage / emulated / 0 / xxx, el acceso al archivo de Android N falla android.os.FileUriExposedException. Si desea conectarse, no repetirá la introducción de muchas formas. Consulte la introducción de los siguientes blogueros.

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

Finalmente encontrado para el archivo: /// almacenamiento / emulado / 0 / xxx / ... archivo. La ruta en nuestro filepaths.xml debe tener la ruta xxx, para que el archivo se pueda encontrar sin errores. No sé demasiado. De todos modos, el problema de la notificación de errores finalmente está resuelto.
 

Supongo que te gusta

Origin blog.csdn.net/qq_26280383/article/details/115064168
Recomendado
Clasificación