[dev_opt_2.15.0] patch升级代码提交
This commit is contained in:
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user