[dev_opt_2.15.0] patch升级代码提交

This commit is contained in:
renwj
2023-03-06 19:50:41 +08:00
parent 91547ae873
commit 3c58608ca6
55 changed files with 2100 additions and 156 deletions

View File

@@ -37,5 +37,11 @@
</provider>
<receiver android:name=".NetworkUtils$NetworkChangedReceiver" />
<receiver android:name=".AppInstallReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.mogo.launcher.f.action.SESSION_API_PACKAGE_INSTALLED" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -73,6 +73,7 @@ public class DownloadService implements InitThread.InitCallBack, DownloadCallBac
FileBean fileBean = (FileBean) intent.getSerializableExtra("FileBean");
if (fileBean == null) {
Log.e(DOWN_LOAD_TAG, "onStartCommand bean is null");
return;
}

View File

@@ -12,6 +12,7 @@ import com.mogo.eagle.core.utilcode.breakpoint.db.dao.ThreadDao;
import com.mogo.eagle.core.utilcode.breakpoint.db.impl.ThreadDaoImpl;
import com.mogo.eagle.core.utilcode.breakpoint.event.DownloadData;
import com.mogo.eagle.core.utilcode.breakpoint.services.DownloadService;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import java.util.ArrayList;
import java.util.List;
@@ -73,7 +74,7 @@ public class DownloadTask implements DownloadCallBack {
DownloadService.executorService.execute(downloadThread);
downloadThreads.add(downloadThread);
}
downloadCallBack.startDownload(fileBean.getUrl());
UiThreadHandler.post(() -> downloadCallBack.startDownload(fileBean.getUrl()));
Log.d(DOWN_LOAD_TAG, " 开始下载:" + finishedProgress);
}
@@ -100,7 +101,7 @@ public class DownloadTask implements DownloadCallBack {
@Override
public void startDownload(String url) {
downloadCallBack.startDownload(url);
UiThreadHandler.post(() -> downloadCallBack.startDownload(url));
}
@Override
@@ -108,7 +109,7 @@ public class DownloadTask implements DownloadCallBack {
//保存下载进度到数据库
Log.d(DOWN_LOAD_TAG, "保存数据:" + threadBean.toString());
dao.updateThread(threadBean.getUrl(), threadBean.getId(), threadBean.getFinished());
downloadCallBack.pauseCallBack(url,threadBean);
UiThreadHandler.post(() -> downloadCallBack.pauseCallBack(url,threadBean));
}
private long curTime = 0;
@@ -117,18 +118,17 @@ public class DownloadTask implements DownloadCallBack {
public void progressCallBack(String url, int length) {
finishedProgress += length;
//每500毫秒发送刷新进度事件
Log.d(DOWN_LOAD_TAG, "process:" + finishedProgress);
if (System.currentTimeMillis() - curTime > 500 || finishedProgress == fileBean.getLength()) {
int progress = (int) (finishedProgress * 1.0 / fileBean.getLength() * 100);
// Log.d(DOWN_LOAD_TAG, "DownloadTask ----length = " + length + " ---progress = " + progress);
Log.d(DOWN_LOAD_TAG, "DownloadTask ----length = " + length + " ---progress = " + progress);
fileBean.setFinished(finishedProgress);
DownloadData downloadData = new DownloadData();
downloadData.setUrl(fileBean.getUrl());
downloadData.setProgress(progress);
downloadData.setLength(fileBean.getLength());
downloadData.setMsg("下载进度回调");
downloadCallBack.progressCallBack(url,progress);
UiThreadHandler.post(() -> downloadCallBack.progressCallBack(url,progress));
curTime = System.currentTimeMillis();
}
}
@@ -151,8 +151,7 @@ public class DownloadTask implements DownloadCallBack {
downloadData.setUrl(fileBean.getUrl());
downloadData.setMsg("下载完成");
downloadData.setFilePath(fileBean.getSavePath() + fileBean.getFileName());
downloadCallBack.threadDownLoadFinished(url,threadBean);
UiThreadHandler.post(() -> downloadCallBack.threadDownLoadFinished(url,threadBean));
}
}

View File

@@ -10,6 +10,8 @@ import com.mogo.eagle.core.utilcode.breakpoint.bean.FileBean;
import com.mogo.eagle.core.utilcode.breakpoint.bean.ThreadBean;
import com.mogo.eagle.core.utilcode.breakpoint.callback.DownloadCallBack;
import com.mogo.eagle.core.utilcode.breakpoint.event.DownloadData;
import com.mogo.eagle.core.utilcode.util.ThreadUtils;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import java.io.File;
import java.io.InputStream;
@@ -63,21 +65,22 @@ public class DownloadThread extends Thread {
while ((len = inputStream.read(bytes))!=-1){
raf.write(bytes,0,len);
//将加载的进度回调出去
callback.progressCallBack(this.fileBean.getUrl(),len);
callback.progressCallBack(fileBean.getUrl(), len);
//保存进度
threadBean.setFinished(threadBean.getFinished()+len);
//在下载暂停的时候将下载进度保存到数据库
if(isPause){
callback.pauseCallBack(this.fileBean.getUrl(),threadBean);
UiThreadHandler.post(() -> callback.pauseCallBack(this.fileBean.getUrl(),threadBean));
return;
}
}
//下载完成
callback.threadDownLoadFinished(this.fileBean.getUrl(),threadBean);
UiThreadHandler.post(() -> callback.threadDownLoadFinished(this.fileBean.getUrl(),threadBean));
}
} catch (Exception e) {
e.printStackTrace();
Log.e(DOWN_LOAD_TAG, "error: " + e.getMessage());
DownloadData downloadData = new DownloadData();
downloadData.setUrl(fileBean.getUrl());
downloadData.setMsg(e.getMessage());
@@ -90,6 +93,7 @@ public class DownloadThread extends Thread {
connection.disconnect();
}catch (Exception e){
e.printStackTrace();
Log.e(DOWN_LOAD_TAG, "error2: " + e.getMessage());
DownloadData downloadData = new DownloadData();
downloadData.setUrl(fileBean.getUrl());
downloadData.setMsg(e.getMessage());

View File

@@ -0,0 +1,164 @@
package com.mogo.eagle.core.utilcode.util
import android.annotation.*
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentSender
import android.content.pm.PackageInstaller
import android.content.pm.PackageInstaller.Session
import android.content.pm.PackageInstaller.SessionCallback
import android.content.pm.PackageInstaller.SessionParams
import android.os.*
import android.util.Log
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.*
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.lang.ref.WeakReference
import java.util.concurrent.ConcurrentHashMap
class ApkInstaller {
companion object {
private const val TAG = "ApkInstaller"
const val INSTALL_CODE_INVLID = -2
@JvmStatic
fun installApp(context: Context, apkFile: File, block: ((Int, String) -> Unit)?) {
if (!apkFile.exists()) {
val msg = "要安装的apk文件不存在"
block?.invoke(INSTALL_CODE_INVLID, msg)
return
}
val isApk = try {
context.packageManager.getPackageArchiveInfo(apkFile.absolutePath, 0)?.versionName != null
} catch (t: Throwable) {
false
}
if (!isApk) {
val msg = "文件: ${apkFile.absolutePath}, 不是一个有效的安装包"
block?.invoke(INSTALL_CODE_INVLID, msg)
return
}
installApp(context, FileInputStream(apkFile), block)
}
@JvmStatic
fun installApp(context: Context, input: InputStream, block: ((Int, String) -> Unit)?) {
ProcessLifecycleOwner.get().lifecycleScope.launch(Dispatchers.IO) {
var session: Session? = null
try {
val installer = context.packageManager.packageInstaller
installer.registerSessionCallback(object : SessionCallback() {
override fun onCreated(sessionId: Int) {
Log.d(TAG, "onCreate: sessionId -> $sessionId")
}
override fun onBadgingChanged(sessionId: Int) {
Log.d(TAG, "onBadgingChanged: sessionId -> $sessionId")
}
override fun onActiveChanged(sessionId: Int, active: Boolean) {
Log.d(TAG, "onActiveChanged: sessionId -> $sessionId, active: $active")
}
override fun onProgressChanged(sessionId: Int, progress: Float) {
Log.d(TAG, "onProgressChanged: sessionId -> $sessionId, process: $progress")
}
override fun onFinished(sessionId: Int, success: Boolean) {
Log.d(TAG, "onFinished: sessionId -> $sessionId, success: $success")
}
}, Handler(Looper.getMainLooper()))
val params = SessionParams(SessionParams.MODE_FULL_INSTALL)
val sessionId = installer.createSession(params)
session = installer.openSession(sessionId)
val output = session.openWrite("install.apk", 0, -1)
output.use { o ->
input.copyTo(o)
}
withContext(Dispatchers.Main) {
session.commit(createIntent(context, sessionId))
}
block?.also {
AppInstallReceiver.listeners[sessionId] = WeakReference(it)
}
} catch (t: Throwable) {
block?.invoke(-2, t.message ?: "未知异常")
session?.close()
}
}
}
@SuppressLint("UnspecifiedImmutableFlag")
private fun createIntent(context: Context, sessionId: Int): IntentSender {
val intent = Intent(context, AppInstallReceiver::class.java)
intent.action = AppInstallReceiver.INTENT_ACTION_SESSION_INSTALL
intent.putExtra(AppInstallReceiver.INTENT_EXTRA_SESSION_ID, sessionId)
return PendingIntent.getBroadcast(context, sessionId, intent, PendingIntent.FLAG_UPDATE_CURRENT).intentSender
}
}
}
class AppInstallReceiver: BroadcastReceiver() {
companion object {
const val TAG = "AppInstallReceiver"
const val INTENT_ACTION_SESSION_INSTALL = "com.mogo.launcher.f.action.SESSION_API_PACKAGE_INSTALLED"
const val INTENT_EXTRA_SESSION_ID = "intent.extra.session_id"
val listeners by lazy { ConcurrentHashMap<Int, WeakReference<((Int, String) -> Unit)>>() }
}
override fun onReceive(context: Context?, intent: Intent?) {
val c = context ?: return
val i = intent ?: return
val a = i.action ?: return
if (a == INTENT_ACTION_SESSION_INSTALL) {
val e = i.extras ?: return
val sessionId = e.getInt(INTENT_EXTRA_SESSION_ID, 0)
Log.d(TAG, "action -> $a, sessionId: $sessionId")
when(val status = e.getInt(PackageInstaller.EXTRA_STATUS)) {
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
val confirm = e.get(Intent.EXTRA_INTENT) as? Intent
if (confirm != null) {
Log.d(TAG, "confirm -> status:$status, sessionID: $sessionId")
val activityInfo = c.packageManager.resolveActivity(confirm, 0)?.activityInfo
if (activityInfo != null) {
confirm.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
c.startActivity(confirm)
} else {
notifyListeners(status, "action: ${confirm.action} 不存在")
}
} else {
notifyListeners(status, "需要用户确认的应用程序不存在")
}
}
PackageInstaller.STATUS_FAILURE_ABORTED,
PackageInstaller.STATUS_FAILURE,
PackageInstaller.STATUS_FAILURE_BLOCKED,
PackageInstaller.STATUS_FAILURE_CONFLICT,
PackageInstaller.STATUS_FAILURE_INCOMPATIBLE,
PackageInstaller.STATUS_FAILURE_INVALID,
PackageInstaller.STATUS_FAILURE_STORAGE -> {
Log.d(TAG, "failed -> status:$status, sessionID: $sessionId")
notifyListeners(status, "安装失败: $status")
}
else -> {
Log.d(TAG, "other status:$status, sessionID: $sessionId")
notifyListeners(status, "未知状态")
}
}
}
}
private fun notifyListeners(code: Int, reason: String) {
listeners.values.forEach {
it.get()?.invoke(code, reason)
}
}
}

View File

@@ -27,6 +27,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* <pre>
@@ -40,6 +41,12 @@ public final class AppUtils {
private static final String MOGO_MAP_SDK_VERSION = "MAP_SDK_VERSION";
private static final AtomicReference<Integer> sVersionCode = new AtomicReference<>();
private static final AtomicReference<String> sVersionName = new AtomicReference<>();
private static final AtomicReference<String> sAppApkMd5 = new AtomicReference<>();
private AppUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
@@ -180,6 +187,12 @@ public final class AppUtils {
Utils.getApp().startActivity(installAppIntent);
}
public static void installApp(Activity activity, File apk, int requestCode) {
Intent installAppIntent = UtilsBridge.getInstallAppIntent(apk);
if (installAppIntent == null) return;
activity.startActivityForResult(installAppIntent, requestCode);
}
/**
* Install the app.
* <p>Target APIs greater than 25 must hold
@@ -556,6 +569,27 @@ public final class AppUtils {
}
}
public static String getAppApkMd5() {
if (sAppApkMd5.get() != null) {
return sAppApkMd5.get();
}
try {
String apkPath = Utils.getApp().getPackageManager().getPackageInfo(Utils.getApp().getPackageName(), 0).applicationInfo.sourceDir;
File apk = new File(apkPath);
if (apk.exists()) {
String ret = Md5Util.getMd5FromFile(apk);
if (!TextUtils.isEmpty(ret)) {
sAppApkMd5.set(ret);
}
return ret;
}
} catch (Throwable t) {
t.printStackTrace();
return "";
}
return "";
}
/**
* Return the application's version name.
*
@@ -575,10 +609,17 @@ public final class AppUtils {
@NonNull
public static String getAppVersionName(final String packageName) {
if (UtilsBridge.isSpace(packageName)) return "";
if (sVersionName.get() != null) {
return sVersionName.get();
}
try {
PackageManager pm = Utils.getApp().getPackageManager();
PackageInfo pi = pm.getPackageInfo(packageName, 0);
return pi == null ? "" : pi.versionName;
String s = pi == null ? "" : pi.versionName;
if (!TextUtils.isEmpty(s)) {
sVersionName.set(s);
}
return s;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return "";
@@ -602,10 +643,18 @@ public final class AppUtils {
*/
public static int getAppVersionCode(final String packageName) {
if (UtilsBridge.isSpace(packageName)) return -1;
Integer oldVersionCode = sVersionCode.get();
if (oldVersionCode != null && oldVersionCode > 0) {
return oldVersionCode;
}
try {
PackageManager pm = Utils.getApp().getPackageManager();
PackageInfo pi = pm.getPackageInfo(packageName, 0);
return pi == null ? -1 : pi.versionCode;
int ret = pi == null ? -1 : pi.versionCode;
if (ret > 0) {
sVersionCode.set(ret);
}
return ret;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return -1;

View File

@@ -0,0 +1,43 @@
package com.mogo.eagle.core.utilcode.util
import java.io.*
import java.nio.channels.FileChannel.MapMode
import java.security.*
class Md5Util {
companion object {
/**
* 获取单个文件的MD5值
* @param file
* @return
* 解决首位0被省略问题
*/
@JvmStatic
fun getMd5FromFile(file: File): String? {
var stringbuffer: StringBuffer? = null
try {
val hexDigits = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')
val input = FileInputStream(file)
val ch = input.channel
val byteBuffer = ch.map(MapMode.READ_ONLY, 0, file.length())
val digest = MessageDigest.getInstance("MD5")
digest.update(byteBuffer)
val bytes = digest.digest()
val n = bytes.size
stringbuffer = StringBuffer(2 * n)
for (l in 0 until n) {
val bt = bytes[l]
val c0 = hexDigits[bt.toInt() and 0xf0 shr 4]
val c1 = hexDigits[bt.toInt() and 0xf]
stringbuffer.append(c0)
stringbuffer.append(c1)
}
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
return stringbuffer?.toString()
}
}
}