diff --git a/CHANGELOG.md b/CHANGELOG.md index e729975..a1c4c32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0 +* add silent install, fix google play release issues. +## 0.3.9 +* fixed download file not exist error. ## 0.3.8+2 * fixed download file not exist error. ## 0.3.8+1 diff --git a/README.md b/README.md index a766a09..ca8e4c4 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Android and IOS upgrade plugin. ## Getting Started ### 1. Use Plugin: -add this code in `pubspec.yaml` +- add this code in `pubspec.yaml` ```yaml dependencies: @@ -103,7 +103,11 @@ dependencies: > make sure your application had this permission and request dynamic permission. ```xml + + + + ``` @@ -182,6 +186,15 @@ enum RUpgradeFlavor { bool isSuccess=await RUpgrade.installByPath(path); } ``` +- install type +```dart +/// [RUpgrade.upgradeWithId]、[RUpgrade.upgrade]、[RUpgrade.install]、[RUpgrade.installByPath] +enum RUpgradeInstallType { + normal,//normal install + silent,//silent install + none,// not install +} +``` #### 5. Pause Download ```dart diff --git a/README_CN.md b/README_CN.md index bdbf626..a4cbddb 100644 --- a/README_CN.md +++ b/README_CN.md @@ -18,6 +18,7 @@ Android和IOS的升级应用插件==Flutter应用升级插件 - [✔] 修改通知栏显示的信息 - [✔] `Android`热更新 - [✔] `Android`增量升级 +- [✔] `Android`普通安装,静默安装 - [✔] `IOS`根据APPID跳转AppStore升级 - [✔] `IOS`根据APPID获取AppStore当前上架版本 @@ -104,9 +105,14 @@ dependencies: > 注意,在Android应用中,请确保`AndroidManifest.xml`中声明以下权限,并在6.0系统上进行动态授权,不然会调用升级方法将抛出权限异常 ```xml + + + + + ``` #### 1.添加升级下载进度监听 @@ -183,6 +189,15 @@ enum RUpgradeFlavor { bool isSuccess=await RUpgrade.installByPath(path); } ``` +- 新增安装类型 +```dart +/// [RUpgrade.upgradeWithId]、[RUpgrade.upgrade]、[RUpgrade.install]、[RUpgrade.installByPath] +enum RUpgradeInstallType { + normal,//普通安装 + silent,//静默安装 + none,// 不进行安装 +} +``` #### 5. 暂停下载 ```dart diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 6c3109f..0a2902f 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,13 +1,13 @@ - - - - + package="com.example.r_upgrade"> - - + + + + + + + @@ -18,7 +18,7 @@ android:grantUriPermissions="true"> + android:resource="@xml/provider_paths" /> diff --git a/android/src/main/java/com/example/r_upgrade/RUpgradePlugin.java b/android/src/main/java/com/example/r_upgrade/RUpgradePlugin.java index 5072f0a..85a802d 100644 --- a/android/src/main/java/com/example/r_upgrade/RUpgradePlugin.java +++ b/android/src/main/java/com/example/r_upgrade/RUpgradePlugin.java @@ -1,14 +1,12 @@ package com.example.r_upgrade; import android.app.Activity; -import android.content.Context; import android.content.Intent; import androidx.annotation.NonNull; -import com.example.r_upgrade.common.HotUpgradeManager; import com.example.r_upgrade.common.StoragePermissions; -import com.example.r_upgrade.common.UpgradeManager; +import com.example.r_upgrade.common.manager.UpgradeManager; import com.example.r_upgrade.common.UpgradeService; import com.example.r_upgrade.method.RUpgradeMethodCallHandler; diff --git a/android/src/main/java/com/example/r_upgrade/common/StoragePermissions.java b/android/src/main/java/com/example/r_upgrade/common/StoragePermissions.java index c8bd55f..ffd07ef 100644 --- a/android/src/main/java/com/example/r_upgrade/common/StoragePermissions.java +++ b/android/src/main/java/com/example/r_upgrade/common/StoragePermissions.java @@ -15,14 +15,14 @@ public interface PermissionsRegistry { void addListener(PluginRegistry.RequestPermissionsResultListener handler); } - interface ResultCallback { + public interface ResultCallback { void onResult(String errorCode, String errorDescription); } private static final int STORAGE_REQUEST_ID = 9790; private boolean ongoing = false; - void requestPermissions( + public void requestPermissions( Activity activity, PermissionsRegistry permissionsRegistry, final ResultCallback callback) { @@ -60,7 +60,7 @@ private boolean hasWritePermission(Activity activity) { } @VisibleForTesting - static final class StorageRequestPermissionsListener + public static final class StorageRequestPermissionsListener implements PluginRegistry.RequestPermissionsResultListener { // There's no way to unregister permission listeners in the v1 embedding, so we'll be called diff --git a/android/src/main/java/com/example/r_upgrade/common/UpgradeNotification.java b/android/src/main/java/com/example/r_upgrade/common/UpgradeNotification.java index 219e887..0ee09ba 100644 --- a/android/src/main/java/com/example/r_upgrade/common/UpgradeNotification.java +++ b/android/src/main/java/com/example/r_upgrade/common/UpgradeNotification.java @@ -13,13 +13,14 @@ import androidx.core.app.NotificationManagerCompat; import com.example.r_upgrade.R; +import com.example.r_upgrade.common.manager.UpgradeManager; public class UpgradeNotification { public static final String TAG = "r_upgrade.Notification"; private static String CHANNEL_NAME; - static void createNotification(Context context, int id, String title,boolean indeterminate, Double percent, String contentText, int status) { + public static void createNotification(Context context, int id, String title,boolean indeterminate, Double percent, String contentText, int status) { if (CHANNEL_NAME == null) { try { CHANNEL_NAME = context.getPackageName() + "_notification"; @@ -112,8 +113,6 @@ static void createNotification(Context context, int id, String title,boolean ind notificationManager.createNotificationChannel(createNotificationChannel()); } compat.notify(id, notification); - -// notificationManager.notify(id, notification); } private static int getPendingIntentFlag() { @@ -124,7 +123,7 @@ private static int getPendingIntentFlag() { return pendingFlag; } - static void removeNotification(Context context, long id) { + public static void removeNotification(Context context, long id) { NotificationManagerCompat compat = NotificationManagerCompat.from(context); compat.cancel((int) id); } diff --git a/android/src/main/java/com/example/r_upgrade/common/UpgradeNotificationStyle.java b/android/src/main/java/com/example/r_upgrade/common/UpgradeNotificationStyle.java index a31b140..e0ce99f 100644 --- a/android/src/main/java/com/example/r_upgrade/common/UpgradeNotificationStyle.java +++ b/android/src/main/java/com/example/r_upgrade/common/UpgradeNotificationStyle.java @@ -12,7 +12,7 @@ public enum UpgradeNotificationStyle { none; - String getNotificationStyleString(Context context, double speech, double planTime) { + public String getNotificationStyleString(Context context, double speech, double planTime) { String speechString = context.getResources().getString(R.string.r_upgrade_download_speech, speech); String planTimeString = context.getResources().getString(R.string.r_upgrade_download_planTime, planTime); switch (this) { diff --git a/android/src/main/java/com/example/r_upgrade/common/UpgradeSQLite.java b/android/src/main/java/com/example/r_upgrade/common/UpgradeSQLite.java index 5277178..8dd980e 100644 --- a/android/src/main/java/com/example/r_upgrade/common/UpgradeSQLite.java +++ b/android/src/main/java/com/example/r_upgrade/common/UpgradeSQLite.java @@ -123,7 +123,7 @@ public Map queryById(long id) { } - Integer queryStatusById(int id) { + public Integer queryStatusById(int id) { SQLiteDatabase readableDatabase = getReadableDatabase(); Cursor cursor = readableDatabase.rawQuery("select * from " + VERSION_MANAGER + " where " + ID + "=?", new String[]{String.valueOf(id)}); boolean canMoveNext = cursor.moveToNext(); @@ -139,7 +139,7 @@ Integer queryStatusById(int id) { //创建记录 - long createRecord(Context context, String url, String apk_name, String header, int status, int upgradeFlavor) { + public long createRecord(Context context, String url, String apk_name, String header, int status, int upgradeFlavor) { String versionName = ""; int versionCode = 0; try { diff --git a/android/src/main/java/com/example/r_upgrade/common/UpgradeService.java b/android/src/main/java/com/example/r_upgrade/common/UpgradeService.java index 5227203..5459302 100644 --- a/android/src/main/java/com/example/r_upgrade/common/UpgradeService.java +++ b/android/src/main/java/com/example/r_upgrade/common/UpgradeService.java @@ -26,7 +26,6 @@ import java.io.RandomAccessFile; import java.math.BigDecimal; import java.net.HttpURLConnection; -import java.net.ProtocolException; import java.net.URL; import java.util.HashMap; import java.util.Iterator; @@ -40,17 +39,17 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSocketFactory; -import static com.example.r_upgrade.common.UpgradeManager.DOWNLOAD_STATUS; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_APK_NAME; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_CURRENT_LENGTH; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_ID; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_MAX_LENGTH; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_PACKAGE; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_PATH; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_PERCENT; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_PLAN_TIME; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_SPEED; -import static com.example.r_upgrade.common.UpgradeManager.PARAMS_STATUS; +import static com.example.r_upgrade.common.manager.UpgradeManager.DOWNLOAD_STATUS; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_APK_NAME; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_CURRENT_LENGTH; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_ID; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_MAX_LENGTH; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_PACKAGE; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_PATH; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_PERCENT; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_PLAN_TIME; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_SPEED; +import static com.example.r_upgrade.common.manager.UpgradeManager.PARAMS_STATUS; public class UpgradeService extends Service { public static final String DOWNLOAD_ID = "download_id"; @@ -139,6 +138,9 @@ public void onLost(Network network) { } private void handleNetworkChange(boolean isConnected) { + if (runnable == null || runnable.isFinish) { + return; + } if (isConnected) { RUpgradeLogger.get().d(TAG, "onReceive: 当前网络正在连接"); if (isFirst) { @@ -153,6 +155,7 @@ private void handleNetworkChange(boolean isConnected) { isFirst = false; return; } + runnable.handlerDownloadFinish(); runnable.pause(-1); isFirst = false; RUpgradeLogger.get().d(TAG, "onReceive: 当前网络已断开"); @@ -219,6 +222,8 @@ private static class UpgradeRunnable implements Runnable { private boolean isNewDownload; + private boolean isFinish; + UpgradeRunnable(boolean isReStart, Long id, String url, Map header, String apkName, UpgradeService upgradeService, UpgradeSQLite sqLite) { this.id = id; this.url = url; @@ -227,12 +232,22 @@ private static class UpgradeRunnable implements Runnable { this.upgradeService = upgradeService; this.sqLite = sqLite; this.isReStart = isReStart; + this.isFinish = false; } + /** + * cancel timer + */ + private void cancelTimer() { + if (timer != null) { + timer.cancel(); + } + } private void cancel(int id) { + if (isFinish) return; if (this.id == id) { - timer.cancel(); + cancelTimer(); if (httpsURLConnection != null) { httpsURLConnection.disconnect(); } @@ -248,6 +263,8 @@ private void cancel(int id) { } private void pause(int id) { + if (isFinish) return; + if (id == -1 || this.id == id) { if (httpsURLConnection != null) { httpsURLConnection.disconnect(); @@ -381,9 +398,7 @@ private void handlerDownloadRunning() { private void handlerDownloadCancel() { RUpgradeLogger.get().d(TAG, "handlerDownloadCancel: "); - if (timer != null) { - timer.cancel(); - } + cancelTimer(); Intent intent = new Intent(); intent.setAction(DOWNLOAD_STATUS); intent.putExtra(PARAMS_ID, id); @@ -397,9 +412,7 @@ private void handlerDownloadCancel() { private void handlerDownloadPause() { RUpgradeLogger.get().d(TAG, "handlerDownloadPause: downloadFile:" + downloadFile); - if (timer != null) { - timer.cancel(); - } + cancelTimer(); Intent intent = new Intent(); intent.setAction(DOWNLOAD_STATUS); intent.putExtra(PARAMS_ID, id); @@ -419,9 +432,7 @@ private void handlerDownloadPause() { private void handlerDownloadFinish() { RUpgradeLogger.get().d(TAG, "handlerDownloadFinish: finish"); - if (timer != null) { - timer.cancel(); - } + cancelTimer(); Intent intent = new Intent(); intent.setAction(DOWNLOAD_STATUS); intent.putExtra(PARAMS_ID, id); @@ -432,6 +443,7 @@ private void handlerDownloadFinish() { upgradeService.sendBroadcast(intent); sqLite.update(id, null, null, DownloadStatus.STATUS_SUCCESSFUL.getValue()); lastCurrentLength = 0; + isFinish = true; } private void handlerDownloadFailure() { diff --git a/android/src/main/java/com/example/r_upgrade/common/install/BaseInstallFactory.java b/android/src/main/java/com/example/r_upgrade/common/install/BaseInstallFactory.java new file mode 100644 index 0000000..e5c2394 --- /dev/null +++ b/android/src/main/java/com/example/r_upgrade/common/install/BaseInstallFactory.java @@ -0,0 +1,14 @@ +package com.example.r_upgrade.common.install; + +import android.content.Context; +import android.content.ContextWrapper; +import android.net.Uri; + +public abstract class BaseInstallFactory extends ContextWrapper { + + public BaseInstallFactory(Context base) { + super(base); + } + + public abstract boolean install(Uri uri); +} diff --git a/android/src/main/java/com/example/r_upgrade/common/install/NormalInstallFactory.java b/android/src/main/java/com/example/r_upgrade/common/install/NormalInstallFactory.java new file mode 100644 index 0000000..4c0fade --- /dev/null +++ b/android/src/main/java/com/example/r_upgrade/common/install/NormalInstallFactory.java @@ -0,0 +1,32 @@ +package com.example.r_upgrade.common.install; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; + +import com.example.r_upgrade.common.RUpgradeLogger; + +public class NormalInstallFactory extends BaseInstallFactory { + + private static final String TAG = "NormalInstall"; + + public NormalInstallFactory(Context base) { + super(base); + } + + @Override + public boolean install(Uri uri) { + Intent install = new Intent(Intent.ACTION_VIEW); + RUpgradeLogger.get().d(TAG, uri.toString()); + install.setDataAndType(uri, "application/vnd.android.package-archive"); + install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + } else { + install.addCategory(Intent.CATEGORY_DEFAULT); + } + startActivity(install); + return true; + } +} diff --git a/android/src/main/java/com/example/r_upgrade/common/install/SilentInstallFactory.java b/android/src/main/java/com/example/r_upgrade/common/install/SilentInstallFactory.java new file mode 100644 index 0000000..04d02f1 --- /dev/null +++ b/android/src/main/java/com/example/r_upgrade/common/install/SilentInstallFactory.java @@ -0,0 +1,150 @@ +package com.example.r_upgrade.common.install; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; + +import androidx.annotation.RequiresApi; + +import com.example.r_upgrade.common.RUpgradeLogger; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class SilentInstallFactory extends BaseInstallFactory { + private static final String TAG = "SilentInstall"; + + public SilentInstallFactory(Context base) { + super(base); + } + + @Override + public boolean install(Uri uri) { + if (uri == null) return false; + File apkFile = new File(uri.getPath()); + if (!apkFile.exists()) { + return false; + } + RUpgradeLogger.get().d(TAG, "startSilentInstall:file path" + apkFile.getPath()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + PackageInstaller installer = getPackageManager().getPackageInstaller(); + PackageInfo packageInfo = getPackageManager().getPackageArchiveInfo(apkFile.getPath(), PackageManager.GET_ACTIVITIES | + PackageManager.GET_SERVICES); + PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( + PackageInstaller.SessionParams.MODE_FULL_INSTALL + ); + if (packageInfo != null) { + String packageName = packageInfo.packageName; + params.setAppPackageName(packageName); + } + params.setSize(apkFile.length()); + int sessionId = createSession(installer, params); + + PackageInstaller.Session session = copyInstallFile(installer, sessionId, apkFile.getPath()); + if (session != null) { + PendingIntent broadCastTest = PendingIntent.getBroadcast( + this, + sessionId, + new Intent(Intent.ACTION_PACKAGE_ADDED), + getPendingIntentFlag()); + session.commit(broadCastTest.getIntentSender()); + session.close(); + } + } + return true; + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void closeQuietly(Object obj) { + if (obj != null) { + if (obj instanceof PackageInstaller.Session) { + ((PackageInstaller.Session) obj).close(); + } else if (obj instanceof FileOutputStream) { + try { + ((FileOutputStream) obj).close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else if (obj instanceof FileInputStream) { + try { + ((FileInputStream) obj).close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else if (obj instanceof OutputStream) { + try { + ((OutputStream) obj).close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else if (obj instanceof InputStream) { + try { + ((InputStream) obj).close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private int createSession(PackageInstaller packageInstaller, + PackageInstaller.SessionParams sessionParams) { + int sessionId = -1; + try { + sessionId = packageInstaller.createSession(sessionParams); + } catch (IOException e) { + e.printStackTrace(); + } + return sessionId; + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private PackageInstaller.Session copyInstallFile(PackageInstaller packageInstaller, + int sessionId, String apkFilePath) { + InputStream in = null; + OutputStream out = null; + PackageInstaller.Session session = null; + try { + File apkFile = new File(apkFilePath); + session = packageInstaller.openSession(sessionId); + out = session.openWrite("app_store_session", 0, apkFile.length()); + in = new FileInputStream(apkFile); + int total = 0; + byte[] buffer = new byte[65536]; + int len; + while ((len = in.read(buffer)) != -1) { + total += len; + out.write(buffer, 0, len); + RUpgradeLogger.get().d(TAG, "Write install session:" + len); + } + RUpgradeLogger.get().d(TAG, "Finish session total size:" + total); + session.fsync(out); + return session; + } catch (IOException e) { + e.printStackTrace(); + } finally { + closeQuietly(in); + closeQuietly(session); + closeQuietly(out); + } + return null; + } + + private static int getPendingIntentFlag() { + int pendingFlag = PendingIntent.FLAG_UPDATE_CURRENT; + if (Build.VERSION.SDK_INT >= 31) { + pendingFlag = PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT; + } + return pendingFlag; + } +} diff --git a/android/src/main/java/com/example/r_upgrade/common/HotUpgradeManager.java b/android/src/main/java/com/example/r_upgrade/common/manager/HotUpgradeManager.java similarity index 99% rename from android/src/main/java/com/example/r_upgrade/common/HotUpgradeManager.java rename to android/src/main/java/com/example/r_upgrade/common/manager/HotUpgradeManager.java index 29cca84..52629c6 100644 --- a/android/src/main/java/com/example/r_upgrade/common/HotUpgradeManager.java +++ b/android/src/main/java/com/example/r_upgrade/common/manager/HotUpgradeManager.java @@ -1,4 +1,4 @@ -package com.example.r_upgrade.common; +package com.example.r_upgrade.common.manager; import android.content.Context; import android.content.ContextWrapper; diff --git a/android/src/main/java/com/example/r_upgrade/common/IncrementUpgradeManager.java b/android/src/main/java/com/example/r_upgrade/common/manager/IncrementUpgradeManager.java similarity index 94% rename from android/src/main/java/com/example/r_upgrade/common/IncrementUpgradeManager.java rename to android/src/main/java/com/example/r_upgrade/common/manager/IncrementUpgradeManager.java index 57b0a41..dfd7182 100644 --- a/android/src/main/java/com/example/r_upgrade/common/IncrementUpgradeManager.java +++ b/android/src/main/java/com/example/r_upgrade/common/manager/IncrementUpgradeManager.java @@ -1,4 +1,4 @@ -package com.example.r_upgrade.common; +package com.example.r_upgrade.common.manager; import android.content.Context; import android.content.ContextWrapper; @@ -6,6 +6,7 @@ import android.util.Log; +import com.example.r_upgrade.common.RUpgradeLogger; import com.example.r_upgrade_lib.RUpgradeLib; import java.io.File; diff --git a/android/src/main/java/com/example/r_upgrade/common/UpgradeManager.java b/android/src/main/java/com/example/r_upgrade/common/manager/UpgradeManager.java similarity index 91% rename from android/src/main/java/com/example/r_upgrade/common/UpgradeManager.java rename to android/src/main/java/com/example/r_upgrade/common/manager/UpgradeManager.java index 74337e4..b519553 100644 --- a/android/src/main/java/com/example/r_upgrade/common/UpgradeManager.java +++ b/android/src/main/java/com/example/r_upgrade/common/manager/UpgradeManager.java @@ -1,4 +1,4 @@ -package com.example.r_upgrade.common; +package com.example.r_upgrade.common.manager; import android.app.Activity; import android.app.DownloadManager; @@ -19,6 +19,17 @@ import androidx.annotation.Nullable; +import com.example.r_upgrade.common.DownloadStatus; +import com.example.r_upgrade.common.RUpgradeLogger; +import com.example.r_upgrade.common.ResultMap; +import com.example.r_upgrade.common.StoragePermissions; +import com.example.r_upgrade.common.UpgradeNotification; +import com.example.r_upgrade.common.UpgradeNotificationStyle; +import com.example.r_upgrade.common.UpgradeSQLite; +import com.example.r_upgrade.common.UpgradeService; +import com.example.r_upgrade.common.install.BaseInstallFactory; +import com.example.r_upgrade.common.install.NormalInstallFactory; +import com.example.r_upgrade.common.install.SilentInstallFactory; import com.example.r_upgrade.common.tasks.CheckGooglePlayVersionTask; import com.example.r_upgrade.common.tasks.CheckTencentStoreVersionTask; import com.example.r_upgrade.common.tasks.CheckXiaoMiStoreVersionTask; @@ -64,7 +75,7 @@ public class UpgradeManager extends ContextWrapper { private Timer timer; - private boolean isAutoRequestInstall; + private BaseInstallFactory installFactory; private boolean isUseDownloadManager = false; @@ -101,8 +112,8 @@ public UpgradeManager(Activity base, MethodChannel channel, StoragePermissions s } - public void upgrade(final String url, final Map header, final String apkName, final Integer notificationVisibility, Integer notificationStyle, Boolean isAutoRequestInstall, Boolean useDownloadManager, final Integer upgradeFlavor, final MethodChannel.Result result) { - this.isAutoRequestInstall = Boolean.TRUE == isAutoRequestInstall; + public void upgrade(final String url, final Map header, final String apkName, final Integer notificationVisibility, Integer notificationStyle, Integer installType, Boolean useDownloadManager, final Integer upgradeFlavor, final MethodChannel.Result result) { + installFactory = installTypeToFactory(installType); this.isUseDownloadManager = Boolean.TRUE == useDownloadManager; if (notificationStyle != null) { this.notificationStyle = UpgradeNotificationStyle.values()[notificationStyle]; @@ -280,9 +291,7 @@ public void queryTask(long id) { timer.cancel(); timer = null; } - if (isAutoRequestInstall) { - installApkById((int) id); - } + installApkById((int) id); intent.setAction(DOWNLOAD_STATUS); intent.putExtra(PARAMS_STATUS, DownloadStatus.STATUS_SUCCESSFUL.getValue()); intent.putExtra(PARAMS_ID, id); @@ -308,16 +317,19 @@ public void queryTask(long id) { public void installApkById(int id) { - installApkById(id, null); + installApkById(id, -1, null); } - public void installApkById(final int id, final MethodChannel.Result result) { + public void installApkById(final int id, int installType, final MethodChannel.Result result) { + if (installType != -1) { + installFactory = installTypeToFactory(installType); + } + if (installFactory == null) return; storagePermissions.requestPermissions(activity, permissionsRegistry, new StoragePermissions.ResultCallback() { @Override public void onResult(String errorCode, String errorDescription) { if (errorCode == null) { - new GenerateAndInstallAsyncTask(activity, isUseDownloadManager, result).execute(id); - + new GenerateAndInstallAsyncTask(activity, isUseDownloadManager, result, installFactory).execute(id); } else { if (result != null) { result.error(errorCode, errorDescription, null); @@ -327,14 +339,29 @@ public void onResult(String errorCode, String errorDescription) { }); } - public void installApkByPath(final String path, final int upgradeFlavor, final MethodChannel.Result result) { + private BaseInstallFactory installTypeToFactory(int installType) { + BaseInstallFactory installFactory; + if (installType == 0) { + installFactory = new NormalInstallFactory(this); + } else if (installType == 1) { + installFactory = new SilentInstallFactory(this); + } else { + installFactory = null; + } + return installFactory; + } + + + public void installApkByPath(final String path, final int upgradeFlavor, int installType, final MethodChannel.Result result) { + installFactory = installTypeToFactory(installType); + storagePermissions.requestPermissions(activity, permissionsRegistry, new StoragePermissions.ResultCallback() { @Override public void onResult(String errorCode, String errorDescription) { if (errorCode == null) { File installPath = new File(path); if (installPath.exists()) { - new GenerateAndInstallByPathAsyncTask(activity, path, upgradeFlavor, result).execute(); + new GenerateAndInstallByPathAsyncTask(activity, path, upgradeFlavor, result, installFactory).execute(); } else { result.error("file not exists", "file path:" + path + " is not exists", null); @@ -392,7 +419,7 @@ public void onReceive(Context context, Intent intent) { } else if (status == DownloadStatus.STATUS_SUCCESSFUL.getValue() && notificationVisibility == 3) { UpgradeNotification.createNotification(context, (int) id, apkName, max_length == -1, percent, contentText, status); } - if (isAutoRequestInstall && status == DownloadStatus.STATUS_SUCCESSFUL.getValue()) { + if (status == DownloadStatus.STATUS_SUCCESSFUL.getValue()) { installApkById((int) id); } } @@ -431,9 +458,10 @@ public Integer getLastUpgradedId() { return UpgradeSQLite.getInstance(this).queryIdByVersionNameAndVersionCode(versionName, versionCode); } - public void upgradeWithId(final Integer id, Integer notificationVisibility, Boolean isAutoRequestInstall, final MethodChannel.Result methodResult) { + public void upgradeWithId(final Integer id, Integer notificationVisibility, int installType, final MethodChannel.Result methodResult) { this.notificationVisibility = notificationVisibility; - this.isAutoRequestInstall = isAutoRequestInstall; + installFactory = installTypeToFactory(installType); + final Map result = UpgradeSQLite.getInstance(this).queryById(id); if (result == null) { methodResult.success(false); @@ -465,7 +493,7 @@ public void onResult(String errorCode, String errorDescription) { } }); } else if (status == DownloadStatus.STATUS_SUCCESSFUL.getValue()) { - installApkById(id, methodResult); + installApkById(id, -1, methodResult); } else { // not known methodResult.success(false); diff --git a/android/src/main/java/com/example/r_upgrade/common/tasks/GenerateAndInstallAsyncTask.java b/android/src/main/java/com/example/r_upgrade/common/tasks/GenerateAndInstallAsyncTask.java index c4a08a9..4ff0e7d 100644 --- a/android/src/main/java/com/example/r_upgrade/common/tasks/GenerateAndInstallAsyncTask.java +++ b/android/src/main/java/com/example/r_upgrade/common/tasks/GenerateAndInstallAsyncTask.java @@ -2,16 +2,16 @@ import android.app.DownloadManager; import android.content.Context; -import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; -import android.util.Log; import com.example.r_upgrade.RUpgradeFileProvider; -import com.example.r_upgrade.common.HotUpgradeManager; -import com.example.r_upgrade.common.IncrementUpgradeManager; +import com.example.r_upgrade.common.install.BaseInstallFactory; +import com.example.r_upgrade.common.install.SilentInstallFactory; +import com.example.r_upgrade.common.manager.HotUpgradeManager; +import com.example.r_upgrade.common.manager.IncrementUpgradeManager; import com.example.r_upgrade.common.RUpgradeLogger; import com.example.r_upgrade.common.UpgradeSQLite; @@ -28,11 +28,14 @@ public class GenerateAndInstallAsyncTask extends AsyncTask contextWrapper; boolean isUserDownloadManager; MethodChannel.Result result; + private BaseInstallFactory installFactory; - public GenerateAndInstallAsyncTask(Context context, boolean isUserDownloadManager, MethodChannel.Result result) { + public GenerateAndInstallAsyncTask(Context context, boolean isUserDownloadManager, MethodChannel.Result result, + BaseInstallFactory installFactory) { this.contextWrapper = new WeakReference(context); this.isUserDownloadManager = isUserDownloadManager; this.result = result; + this.installFactory = installFactory; } @Override @@ -63,6 +66,9 @@ protected Uri doInBackground(Integer... integers) { } else { uri = Uri.fromFile(file); } + if (installFactory != null && installFactory instanceof SilentInstallFactory) { + uri = Uri.parse(file.getPath()); + } if (upgradeFlavor == UpgradeSQLite.UPGRADE_FLAVOR_INCREMENT) { String newPath = new IncrementUpgradeManager(contextWrapper.get()).mixinAndGetNewApk(path); RUpgradeLogger.get().d(TAG, "合成成功,新的安装包路径:" + newPath); @@ -73,6 +79,9 @@ protected Uri doInBackground(Integer... integers) { } else { uri = Uri.fromFile(file); } + if (installFactory != null && installFactory instanceof SilentInstallFactory) { + uri = Uri.parse(file.getPath()); + } } else if (upgradeFlavor == UpgradeSQLite.UPGRADE_FLAVOR_HOT_UPDATE) { boolean isSuccess = new HotUpgradeManager(contextWrapper.get()).hotUpgrade(uri); if (isSuccess) { @@ -85,6 +94,7 @@ protected Uri doInBackground(Integer... integers) { } catch (Exception e) { e.printStackTrace(); } + return uri; } @@ -117,20 +127,7 @@ private void postResult(boolean isSuccess) { //安装apk private boolean installApk(Uri uri) { - Intent install = new Intent(Intent.ACTION_VIEW); - if (uri != null) { - RUpgradeLogger.get().d(TAG, uri.toString()); - install.setDataAndType(uri, "application/vnd.android.package-archive"); - install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } else { - install.addCategory(Intent.CATEGORY_DEFAULT); - } - contextWrapper.get().startActivity(install); - return true; - } else { - return false; - } + if (installFactory == null) return true; + return installFactory.install(uri); } } diff --git a/android/src/main/java/com/example/r_upgrade/common/tasks/GenerateAndInstallByPathAsyncTask.java b/android/src/main/java/com/example/r_upgrade/common/tasks/GenerateAndInstallByPathAsyncTask.java index 192f792..9edfcf8 100644 --- a/android/src/main/java/com/example/r_upgrade/common/tasks/GenerateAndInstallByPathAsyncTask.java +++ b/android/src/main/java/com/example/r_upgrade/common/tasks/GenerateAndInstallByPathAsyncTask.java @@ -2,20 +2,20 @@ import android.content.Context; import android.content.Intent; -import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import com.example.r_upgrade.RUpgradeFileProvider; -import com.example.r_upgrade.common.HotUpgradeManager; -import com.example.r_upgrade.common.IncrementUpgradeManager; +import com.example.r_upgrade.common.install.BaseInstallFactory; +import com.example.r_upgrade.common.install.SilentInstallFactory; +import com.example.r_upgrade.common.manager.HotUpgradeManager; +import com.example.r_upgrade.common.manager.IncrementUpgradeManager; import com.example.r_upgrade.common.RUpgradeLogger; import com.example.r_upgrade.common.UpgradeSQLite; import java.io.File; import java.lang.ref.WeakReference; -import java.util.Map; import io.flutter.plugin.common.MethodChannel; @@ -25,12 +25,14 @@ public class GenerateAndInstallByPathAsyncTask extends AsyncTask(context); this.path = path; this.upgradeFlavor = upgradeFlavor; this.result = result; + this.installFactory = installFactory; } @Override @@ -43,9 +45,12 @@ protected Uri doInBackground(String... integers) { } else { uri = Uri.fromFile(file); } + if(installFactory != null && installFactory instanceof SilentInstallFactory){ + uri= Uri.parse(file.getPath()); + } if (upgradeFlavor == UpgradeSQLite.UPGRADE_FLAVOR_INCREMENT) { String newPath = new IncrementUpgradeManager(contextWrapper.get()).mixinAndGetNewApk(path); - RUpgradeLogger.get().d(TAG,"合成成功,新的安装包路径:"+newPath); + RUpgradeLogger.get().d(TAG, "合成成功,新的安装包路径:" + newPath); if (newPath == null) return null; file = new File(newPath); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { @@ -53,6 +58,9 @@ protected Uri doInBackground(String... integers) { } else { uri = Uri.fromFile(file); } + if(installFactory != null && installFactory instanceof SilentInstallFactory){ + uri= Uri.parse(file.getPath()); + } } else if (upgradeFlavor == UpgradeSQLite.UPGRADE_FLAVOR_HOT_UPDATE) { boolean isSuccess = new HotUpgradeManager(contextWrapper.get()).hotUpgrade(uri); if (isSuccess) { @@ -96,20 +104,7 @@ private void postResult(boolean isSuccess) { //安装apk private boolean installApk(Uri uri) { - Intent install = new Intent(Intent.ACTION_VIEW); - if (uri != null) { - RUpgradeLogger.get().d(TAG, uri.toString()); - install.setDataAndType(uri, "application/vnd.android.package-archive"); - install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } else { - install.addCategory(Intent.CATEGORY_DEFAULT); - } - contextWrapper.get().startActivity(install); - return true; - } else { - return false; - } + if (installFactory == null) return true; + return installFactory.install(uri); } } diff --git a/android/src/main/java/com/example/r_upgrade/method/IRUpgradeMethodHandler.java b/android/src/main/java/com/example/r_upgrade/method/IRUpgradeMethodHandler.java index fba7981..07075d2 100644 --- a/android/src/main/java/com/example/r_upgrade/method/IRUpgradeMethodHandler.java +++ b/android/src/main/java/com/example/r_upgrade/method/IRUpgradeMethodHandler.java @@ -1,8 +1,7 @@ package com.example.r_upgrade.method; -import com.example.r_upgrade.common.HotUpgradeManager; -import com.example.r_upgrade.common.UpgradeManager; +import com.example.r_upgrade.common.manager.UpgradeManager; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; diff --git a/android/src/main/java/com/example/r_upgrade/method/RUpgradeMethodCallHandler.java b/android/src/main/java/com/example/r_upgrade/method/RUpgradeMethodCallHandler.java index e79c07f..3d4ccd2 100644 --- a/android/src/main/java/com/example/r_upgrade/method/RUpgradeMethodCallHandler.java +++ b/android/src/main/java/com/example/r_upgrade/method/RUpgradeMethodCallHandler.java @@ -2,14 +2,13 @@ import androidx.annotation.NonNull; -import com.example.r_upgrade.common.HotUpgradeManager; -import com.example.r_upgrade.common.UpgradeManager; +import com.example.r_upgrade.common.manager.UpgradeManager; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; public class RUpgradeMethodCallHandler implements MethodChannel.MethodCallHandler { - private UpgradeManager upgradeManager; + private final UpgradeManager upgradeManager; public RUpgradeMethodCallHandler(UpgradeManager upgradeManager) { this.upgradeManager = upgradeManager; diff --git a/android/src/main/java/com/example/r_upgrade/method/RUpgradeMethodEnum.java b/android/src/main/java/com/example/r_upgrade/method/RUpgradeMethodEnum.java index ccaaf92..15a0a5e 100644 --- a/android/src/main/java/com/example/r_upgrade/method/RUpgradeMethodEnum.java +++ b/android/src/main/java/com/example/r_upgrade/method/RUpgradeMethodEnum.java @@ -2,7 +2,7 @@ import com.example.r_upgrade.common.RUpgradeLogger; -import com.example.r_upgrade.common.UpgradeManager; +import com.example.r_upgrade.common.manager.UpgradeManager; import java.util.Map; @@ -26,7 +26,7 @@ public void handler(UpgradeManager upgradeManager, MethodCall call, MethodChanne (String) call.argument("fileName"), (Integer) call.argument("notificationVisibility"), (Integer) call.argument("notificationStyle"), - (Boolean) call.argument("isAutoRequestInstall"), + (Integer) call.argument("installType"), (Boolean) call.argument("useDownloadManager"), (Integer) call.argument("upgradeFlavor"), result); } }, @@ -47,13 +47,13 @@ public void handler(UpgradeManager upgradeManager, MethodCall call, MethodChanne install { @Override public void handler(UpgradeManager upgradeManager, MethodCall call, MethodChannel.Result result) { - upgradeManager.installApkById((Integer) call.argument("id"), result); + upgradeManager.installApkById((Integer) call.argument("id"),(Integer) call.argument("installType"), result); } }, installByPath { @Override public void handler(UpgradeManager upgradeManager, MethodCall call, MethodChannel.Result result) { - upgradeManager.installApkByPath((String) call.argument("path"), (Integer) call.argument("flavor"), result); + upgradeManager.installApkByPath((String) call.argument("path"), (Integer) call.argument("flavor"), (Integer) call.argument("installType"), result); } }, pause { @@ -66,7 +66,7 @@ public void handler(UpgradeManager upgradeManager, MethodCall call, MethodChanne @Override public void handler(UpgradeManager upgradeManager, MethodCall call, MethodChannel.Result result) { upgradeManager.upgradeWithId((Integer) call.argument("id"), (Integer) call.argument("notificationVisibility"), - (Boolean) call.argument("isAutoRequestInstall"), result); + (Integer) call.argument("installType"), result); } }, getDownloadStatus { diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index f59f17e..e7b818d 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -32,9 +32,6 @@ android { main.java.srcDirs += 'src/main/kotlin' } - lintOptions { - disable 'InvalidPackage' - } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). @@ -52,6 +49,10 @@ android { signingConfig signingConfigs.debug } } + lint { + disable 'InvalidPackage' + } + namespace 'com.example.r_upgrade_example' } flutter { diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml index dc7cec2..f880684 100644 --- a/example/android/app/src/debug/AndroidManifest.xml +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 887334c..528f0fa 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,10 +1,13 @@ + xmlns:tools="http://schemas.android.com/tools"> + + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml index dc7cec2..f880684 100644 --- a/example/android/app/src/profile/AndroidManifest.xml +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/example/android/build.gradle b/example/android/build.gradle index 31e9577..87841cc 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 38c8d45..94adc3a 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M -android.enableR8=true android.useAndroidX=true android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 595fb86..cc5527d 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index f2872cf..4f8d4d2 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 11.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 1e8c3c9..88359b2 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +# platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index ececf54..33ff98a 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -155,7 +155,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -339,7 +339,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -425,7 +425,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -474,7 +474,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140c..3db53b6 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + diff --git a/example/lib/generated/intl/messages_en.dart b/example/lib/generated/intl/messages_en.dart index 474ca32..6b59a86 100644 --- a/example/lib/generated/intl/messages_en.dart +++ b/example/lib/generated/intl/messages_en.dart @@ -90,6 +90,16 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Incremental updating"), "Incremental_updating_failed": MessageLookupByLibrary.simpleMessage( "Incremental updating failed!"), + "Install_Related": + MessageLookupByLibrary.simpleMessage("Install Related"), + "Install_Type": MessageLookupByLibrary.simpleMessage("Install Type"), + "Install_Type_None": MessageLookupByLibrary.simpleMessage("None"), + "Install_Type_Normal": + MessageLookupByLibrary.simpleMessage("Normal Install"), + "Install_Type_Silent": + MessageLookupByLibrary.simpleMessage("Silent Install"), + "Install_Type_Silent_Tip": MessageLookupByLibrary.simpleMessage( + "Please note that this installation type requires system permissions!"), "Install_all_updates": MessageLookupByLibrary.simpleMessage("Install all updates"), "Jump_to_the_app_store": diff --git a/example/lib/generated/intl/messages_zh.dart b/example/lib/generated/intl/messages_zh.dart index 8cc6da2..91fca3d 100644 --- a/example/lib/generated/intl/messages_zh.dart +++ b/example/lib/generated/intl/messages_zh.dart @@ -67,6 +67,13 @@ class MessageLookup extends MessageLookupByLibrary { "Incremental_updating": MessageLookupByLibrary.simpleMessage("增量更新"), "Incremental_updating_failed": MessageLookupByLibrary.simpleMessage("增量更新失败!"), + "Install_Related": MessageLookupByLibrary.simpleMessage("安装相关"), + "Install_Type": MessageLookupByLibrary.simpleMessage("安装类型"), + "Install_Type_None": MessageLookupByLibrary.simpleMessage("无"), + "Install_Type_Normal": MessageLookupByLibrary.simpleMessage("普通安装"), + "Install_Type_Silent": MessageLookupByLibrary.simpleMessage("静默安装"), + "Install_Type_Silent_Tip": + MessageLookupByLibrary.simpleMessage("请注意,该安装类型需要系统权限!"), "Install_all_updates": MessageLookupByLibrary.simpleMessage("安装全量更新"), "Jump_to_the_app_store": MessageLookupByLibrary.simpleMessage("跳转到应用商店"), diff --git a/example/lib/generated/l10n.dart b/example/lib/generated/l10n.dart index 605ff17..197ae65 100644 --- a/example/lib/generated/l10n.dart +++ b/example/lib/generated/l10n.dart @@ -531,6 +531,66 @@ class S { args: [], ); } + + /// `Install Related` + String get Install_Related { + return Intl.message( + 'Install Related', + name: 'Install_Related', + desc: '', + args: [], + ); + } + + /// `Install Type` + String get Install_Type { + return Intl.message( + 'Install Type', + name: 'Install_Type', + desc: '', + args: [], + ); + } + + /// `Normal Install` + String get Install_Type_Normal { + return Intl.message( + 'Normal Install', + name: 'Install_Type_Normal', + desc: '', + args: [], + ); + } + + /// `Silent Install` + String get Install_Type_Silent { + return Intl.message( + 'Silent Install', + name: 'Install_Type_Silent', + desc: '', + args: [], + ); + } + + /// `None` + String get Install_Type_None { + return Intl.message( + 'None', + name: 'Install_Type_None', + desc: '', + args: [], + ); + } + + /// `Please note that this installation type requires system permissions!` + String get Install_Type_Silent_Tip { + return Intl.message( + 'Please note that this installation type requires system permissions!', + name: 'Install_Type_Silent_Tip', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/example/lib/l10n/intl_en.arb b/example/lib/l10n/intl_en.arb index 2f7aecd..2da5f94 100644 --- a/example/lib/l10n/intl_en.arb +++ b/example/lib/l10n/intl_en.arb @@ -46,5 +46,11 @@ "Full_quantity_update": "Full quantity update", "Hot_update": "Hot update", "getAndroidStore": "Get Android Store", - "getVersionFromAndroidStore": "Get Version From Android Store" + "getVersionFromAndroidStore": "Get Version From Android Store", + "Install_Related": "Install Related", + "Install_Type": "Install Type", + "Install_Type_Normal": "Normal Install", + "Install_Type_Silent": "Silent Install", + "Install_Type_None": "None", + "Install_Type_Silent_Tip": "Please note that this installation type requires system permissions!" } diff --git a/example/lib/l10n/intl_zh.arb b/example/lib/l10n/intl_zh.arb index bebc861..357ca6a 100644 --- a/example/lib/l10n/intl_zh.arb +++ b/example/lib/l10n/intl_zh.arb @@ -21,7 +21,6 @@ "Please_click_on_start_hot_update": "请点击开始热更新", "Hot_update_is_successful_exit_the_application_after_3_s_please_re_enter": "热更新成功,3s后退出应用,请重新进入", "Hot_update_failed_please_wait_for_update_the_download_is_complete": "热更新失败,请等待更新包下载完成", - "Incremental_updating": "增量更新", "Began_to_download_the_incremental_updating": "开始下载增量更新", "Please_click_on_start_incremental_updates": "请点击开始增量更新", "Incremental_updating_failed": "增量更新失败!", @@ -47,5 +46,11 @@ "Hot_update": "热更新", "Incremental_updating": "增量更新", "getAndroidStore": "获取应用市场列表", - "getVersionFromAndroidStore": "获取版本号(应用宝)" + "getVersionFromAndroidStore": "获取版本号(应用宝)", + "Install_Related": "安装相关", + "Install_Type": "安装类型", + "Install_Type_Normal": "普通安装", + "Install_Type_Silent": "静默安装", + "Install_Type_None": "无", + "Install_Type_Silent_Tip": "请注意,该安装类型需要系统权限!" } \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart index 838535e..91a6328 100755 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -79,8 +79,7 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { int? id; - bool? isAutoRequestInstall = false; - + RUpgradeInstallType installType = RUpgradeInstallType.normal; UpgradeMethod? upgradeMethod; String? iosVersion = ""; @@ -145,6 +144,51 @@ class _MyAppState extends State { children: [ _buildDownloadWindow(), Divider(), + ListTile( + title: Text( + S.of(context).Install_Related, + style: Theme.of(context).textTheme.headline6!.copyWith( + fontWeight: FontWeight.w600, + ), + ), + ), + ListTile( + title: Text( + S.of(context).Install_Type, + ), + trailing: DropdownButton( + items: [ + DropdownMenuItem( + child: Text(S.of(context).Install_Type_Normal), + value: RUpgradeInstallType.normal, + ), + DropdownMenuItem( + child: Text(S.of(context).Install_Type_Silent), + value: RUpgradeInstallType.silent, + ), + DropdownMenuItem( + child: Text(S.of(context).Install_Type_None), + value: RUpgradeInstallType.none, + ), + ], + value: installType, + onChanged: (value) { + if (value == null) return; + setState(() { + installType = value; + }); + }, + ), + ), + if (installType == RUpgradeInstallType.silent) + ListTile( + title: Text( + S.of(context).Install_Type_Silent_Tip, + style: Theme.of(context).textTheme.subtitle2?.copyWith( + color: Theme.of(context).errorColor, + ), + ), + ), ListTile( title: Text( S.of(context).Update_the_related, @@ -220,9 +264,9 @@ class _MyAppState extends State { id = await RUpgrade.upgrade( // "http://192.168.1.105:8888/files/static/kuan.apk", // 'http://dl-cdn.coolapkmarket.com/down/apk_file/2020/0308/Coolapk-v10.0.3-2003081-coolapk-app-release.apk?_upt=b210caeb1585012557', - 'https://mydata-1252536312.cos.ap-guangzhou.myqcloud.com/r_upgrade.apk', + 'https://dl-tc.coolapkmarket.com/down/apk_file/2022/1031/Coolapk-12.5.1-2210311-coolapk-app-sign.apk?t=1675873958&sign=c2eed2272fe3ac07435a555dbbd5bfe4', fileName: 'r_upgrade.apk', - isAutoRequestInstall: isAutoRequestInstall!, + installType: installType!, notificationStyle: NotificationStyle.speechAndPlanTime, useDownloadManager: false); upgradeMethod = UpgradeMethod.all; @@ -249,7 +293,8 @@ class _MyAppState extends State { final status = await RUpgrade.getDownloadStatus(id!); if (status == DownloadStatus.STATUS_SUCCESSFUL) { - bool? isSuccess = await RUpgrade.install(id!); + bool? isSuccess = + await RUpgrade.install(id!, installType: installType); if (isSuccess != null && isSuccess) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(S.of(context).The_request_is_successful))); @@ -260,15 +305,6 @@ class _MyAppState extends State { } }, ), - CheckboxListTile( - value: isAutoRequestInstall, - onChanged: (bool? value) { - setState(() { - isAutoRequestInstall = value; - }); - }, - title: Text(S.of(context).After_download_to_install), - ), ListTile( title: Text(S.of(context).Continue_to_update), onTap: () async { @@ -336,7 +372,7 @@ class _MyAppState extends State { 'https://mydata-1252536312.cos.ap-guangzhou.myqcloud.com/r_upgrade.zip', fileName: 'r_upgrade.zip', useDownloadManager: false, - isAutoRequestInstall: false, + installType: installType, upgradeFlavor: RUpgradeFlavor.hotUpgrade); upgradeMethod = UpgradeMethod.hot; setState(() {}); @@ -363,7 +399,8 @@ class _MyAppState extends State { final status = await RUpgrade.getDownloadStatus(id!); if (status == DownloadStatus.STATUS_SUCCESSFUL) { - bool? isSuccess = await RUpgrade.install(id!); + bool? isSuccess = + await RUpgrade.install(id!, installType: installType); if (isSuccess != null && isSuccess) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(S @@ -407,7 +444,7 @@ class _MyAppState extends State { 'https://mydata-1252536312.cos.ap-guangzhou.myqcloud.com/r_upgrade.patch', fileName: 'r_upgrade.patch', useDownloadManager: false, - isAutoRequestInstall: false, + installType: installType, upgradeFlavor: RUpgradeFlavor.incrementUpgrade, ); upgradeMethod = UpgradeMethod.increment; @@ -436,7 +473,7 @@ class _MyAppState extends State { try { final status = await RUpgrade.getDownloadStatus(id!); if (status == DownloadStatus.STATUS_SUCCESSFUL) { - await RUpgrade.install(id!); + await RUpgrade.install(id!, installType: installType); } else { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: diff --git a/example/pubspec.lock b/example/pubspec.lock index c8d1aec..77209d5 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,58 +5,51 @@ packages: dependency: transitive description: name: async - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" characters: dependency: transitive description: name: characters - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.3.1" + version: "1.2.1" clock: dependency: transitive description: name: clock - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "0.1.3" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter @@ -76,44 +69,44 @@ packages: dependency: "direct main" description: name: intl - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "0.17.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "0.1.5" meta: dependency: transitive description: name: meta - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" path: dependency: transitive description: name: path - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.2" r_upgrade: dependency: "direct dev" description: path: ".." relative: true source: path - version: "0.3.8+2" + version: "0.3.9" sky_engine: dependency: transitive description: flutter @@ -123,58 +116,51 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.9.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.4.8" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "0.4.12" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" sdks: - dart: ">=2.14.0 <3.0.0" + dart: ">=2.17.0-0 <3.0.0" flutter: ">=1.12.0" diff --git a/lib/r_upgrade.dart b/lib/r_upgrade.dart index 1c0fc8c..aa09245 100755 --- a/lib/r_upgrade.dart +++ b/lib/r_upgrade.dart @@ -103,7 +103,7 @@ class RUpgrade { /// * [fileName] download filename and notification title name. /// * [notificationVisibility] download running notification visibility mode. /// * [notificationStyle] download notification show style about content text, only support [useDownloadManager]==false. - /// * [isAutoRequestInstall] download completed will install apk. + /// * [installType] download completed will install apk, use [RUpgradeInstallType.none] can not install. /// * [useDownloadManager] if true will use DownloadManager,false will use my service , /// * if true will no use [pause] , [upgradeWithId] , [getDownloadStatus] , [getLastUpgradedId] methods. /// * [upgradeFlavor] you can use [RUpgradeFlavor.normal] , [RUpgradeFlavor.hotUpgrade] , [RUpgradeFlavor.incrementUpgrade] flavor @@ -114,7 +114,7 @@ class RUpgrade { NotificationVisibility notificationVisibility = NotificationVisibility.VISIBILITY_VISIBLE, NotificationStyle notificationStyle = NotificationStyle.planTime, - bool isAutoRequestInstall = true, + RUpgradeInstallType installType = RUpgradeInstallType.normal, bool useDownloadManager = false, RUpgradeFlavor upgradeFlavor = RUpgradeFlavor.normal, }) { @@ -125,7 +125,7 @@ class RUpgrade { "fileName": fileName, "notificationVisibility": notificationVisibility.value, "notificationStyle": notificationStyle.index, - "isAutoRequestInstall": isAutoRequestInstall, + "installType": installType.index, "useDownloadManager": useDownloadManager, "upgradeFlavor": upgradeFlavor.index, }); @@ -146,10 +146,14 @@ class RUpgrade { /// /// Install your apk by [id]. /// - static Future install(int id) async { + static Future install( + int id, { + RUpgradeInstallType installType = RUpgradeInstallType.normal, + }) async { assert(Platform.isAndroid, 'This method only support android application'); return await _methodChannel!.invokeMethod("install", { 'id': id, + 'installType': installType.index, }); } @@ -157,12 +161,16 @@ class RUpgrade { /// /// Install your apk by [path]. /// - static Future installByPath(String path, - {RUpgradeFlavor flavor = RUpgradeFlavor.normal}) async { + static Future installByPath( + String path, { + RUpgradeFlavor flavor = RUpgradeFlavor.normal, + RUpgradeInstallType installType = RUpgradeInstallType.normal, + }) async { assert(Platform.isAndroid, 'This method only support android application'); return await _methodChannel!.invokeMethod("installByPath", { 'path': path, 'flavor': flavor.index, + 'installType': installType, }); } @@ -190,13 +198,13 @@ class RUpgrade { int id, { NotificationVisibility notificationVisibility = NotificationVisibility.VISIBILITY_VISIBLE, - bool isAutoRequestInstall = true, + RUpgradeInstallType installType = RUpgradeInstallType.normal, }) async { assert(Platform.isAndroid, 'This method only support android application'); return await _methodChannel!.invokeMethod("upgradeWithId", { "id": id, "notificationVisibility": notificationVisibility.value, - "isAutoRequestInstall": isAutoRequestInstall, + "installType": installType.index, }); } @@ -417,6 +425,13 @@ enum RUpgradeFlavor { incrementUpgrade, } +/// Install Type +enum RUpgradeInstallType { + normal, + silent, + none, +} + /// /// Android application store. /// diff --git a/pubspec.lock b/pubspec.lock index 420a408..d72c8ab 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,51 +5,44 @@ packages: dependency: transitive description: name: async - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" characters: dependency: transitive description: name: characters - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.3.1" + version: "1.2.1" clock: dependency: transitive description: name: clock - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter @@ -64,30 +57,30 @@ packages: dependency: transitive description: name: matcher - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "0.1.5" meta: dependency: transitive description: name: meta - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" path: dependency: transitive description: name: path - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.2" sky_engine: dependency: transitive description: flutter @@ -97,58 +90,51 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.9.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.4.8" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "0.4.12" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.flutter-io.cn" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" sdks: - dart: ">=2.14.0 <3.0.0" + dart: ">=2.17.0-0 <3.0.0" flutter: ">=1.12.0" diff --git a/pubspec.yaml b/pubspec.yaml index fec342d..0f3e8ba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: r_upgrade description: A plugin for upgrade and install application ,Support Android and IOS. -version: 0.3.8+2 +version: 0.4.0 homepage: https://github.com/rhymelph/r_upgrade environment: