LaborerYao丶
LaborerYao丶
  • 发布:2021-07-09 15:25
  • 更新:2021-07-14 17:04
  • 阅读:2580

uniapp真正实现App静默安装

分类:uni-app

uniapp静默更新

注意:这篇文章仅针对有Root权限的Android设备实现静默更新

先来看看uniapp端的静默更新效果:

什么鬼,需要我自己点算个什么静默更新....

于是就想到用Android原生实现静默更新再搞个插件什么的在uniapp上运行

一、准备开发环境
JAVA环境 jdk1.8
Android Studio
App离线SDK下载:请下载2.9.8 版本的android平台SDK
官网SDK解压后如下图

二、导入项目
导入uni插件原生项目 UniPlugin-Hello-AS工程请在App离线SDK中查找
点击Android Studio菜单选项File—>New—>Import Project。

三、创建插件Library

选择Android Library

输入 Library名称Update点击finish
然后在app目录下的build.gradle下引入 Update

将app libs目录下的 uniapp-v8-release.aar包(名字可能不一样)复制到 Update libs下

然后修改modle Update中的build.gradle文件 引入aar包 点击右上角同步即可

四、然后在modle目录下创建SilentInstallation类集成UniMoudle

package android.laboreryao.update;

import android.util.Log;
import android.widget.Toast;

import com.taobao.weex.bridge.JSCallback;

import java.io.File;

import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.common.UniModule;

/**

  • 功能介绍:静默安装<br/>
  • 调用方式: / <br/>
  • <p/>
  • 作 者: LaborerYao - 228598641@qq.com <br/>
  • 创建电脑: <br/>
  • 创建时间: 2021/6/25 18:01 <br/>
  • 最后编辑: 2021/6/25 - yyl
  • @author LaborerYao
    */
    public class SilentInstallation extends UniModule {
    /**

    • 静默安装
    • @param apkPath
    • @param jsCallback result true 安装成功 false 失败
      */
      @UniJSMethod(uiThread = true)
      public void UpdateLotteryMachineApp(String apkPath, JSCallback jsCallback) {
      Log.e("LaborerYao", "Update!!!apkPath==" apkPath);
      if (!isRoot()) {
      Toast.makeText(mWXSDKInstance.getContext(), "没有ROOT权限,不能使用静默安装", Toast.LENGTH_SHORT).show();
      jsCallback.invoke(false);
      }
      SilentInstall installHelper = new SilentInstall();
      final boolean result = installHelper.install(apkPath);
      jsCallback.invoke(result);
      }

    /**

    • 判断手机是否拥有Root权限。
    • @return 有root权限返回true,否则返回false。
      */
      public boolean isRoot() {
      boolean bool = false;
      try {
      bool = new File("/system/bin/su").exists() || new File("/system/xbin/su").exists();
      } catch (Exception e) {
      e.printStackTrace();
      }
      return bool;
      }
      }

五、创建静默安装实现类,调用"pm install -r"命令进行静默安装
package android.laboreryao.update;

/**

  • 功能介绍: <br/>
  • 调用方式: / <br/>
  • <p/>
  • 作 者: LaborerYao - 228598641@qq.com <br/>
  • 创建电脑: <br/>
  • 创建时间: 2021/6/25 14:49 <br/>
  • 最后编辑: 2021/6/25 - yyl
  • @author LaborerYao
    */

import android.util.Log;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

public class SilentInstall {

/**  
 * 执行具体的静默安装逻辑,需要手机ROOT。  
 * @param apkPath  
 *          要安装的apk文件的路径  
 * @return 安装成功返回true,安装失败返回false。  
 */  
public boolean install(String apkPath) {  
    boolean result = false;  
    DataOutputStream dataOutputStream = null;  
    BufferedReader errorStream = null;  
    try {  
        // 申请su权限  
        Process process = Runtime.getRuntime().exec("su");  
        dataOutputStream = new DataOutputStream(process.getOutputStream());  
        // 执行pm install命令  
        String command = "pm install -r "   apkPath   "\n";  
        dataOutputStream.write(command.getBytes(Charset.forName("utf-8")));  
        dataOutputStream.flush();  
        dataOutputStream.writeBytes("exit\n");  
        dataOutputStream.flush();  
        process.waitFor();  
        errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));  
        String msg = "";  
        String line;  
        // 读取命令的执行结果  
        while ((line = errorStream.readLine()) != null) {  
            msg  = line;  
        }  
        Log.d("TAG", "install msg is "   msg);  
        // 如果执行结果中包含Failure字样就认为是安装失败,否则就认为安装成功  
        if (!msg.contains("Failure")) {  
            result = true;  
        }  
    } catch (Exception e) {  
        Log.e("TAG", e.getMessage(), e);  
    } finally {  
        try {  
            if (dataOutputStream != null) {  
                dataOutputStream.close();  
            }  
            if (errorStream != null) {  
                errorStream.close();  
            }  
        } catch (IOException e) {  
            Log.e("TAG", e.getMessage(), e);  
        }  
    }  
    return result;  
}  

}

六、创建BootBroadcastReceiver 广播用来监听apk安装完成自动打开
package android.laboreryao.update;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**

  • 功能介绍:自启动Receiver<br/>
  • 调用方式: / <br/>
  • <p/>
  • 作 者: LaborerYao - 228598641@qq.com <br/>
  • 创建电脑: MaiyuanAndroid2 <br/>
  • 创建时间: 2021/6/25 18:01 <br/>
  • 最后编辑: 2021/6/25 - yyl
  • @author LaborerYao
    */
    public class BootBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "sjft";

    public static final String EXTRA_VOLUME_STATE =
    "android.os.storage.extra.VOLUME_STATE";

    public static final int STATE_UNMOUNTED = 0;
    public static final int STATE_CHECKING = 1;
    public static final int STATE_MOUNTED = 2;
    public static final int STATE_MOUNTED_READ_ONLY = 3;
    public static final int STATE_FORMATTING = 4;
    public static final int STATE_EJECTING = 5;
    public static final int STATE_UNMOUNTABLE = 6;
    public static final int STATE_REMOVED = 7;
    public static final int STATE_BAD_REMOVAL = 8;

    @Override
    public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    String action = intent.getAction();
    if (action.equals("android.intent.action.PACKAGE_REPLACED")) {
    String packageName = intent.getData().getSchemeSpecificPart();
    Log.v(TAG, "BootBroadcastReceiver packageName:" packageName);
    if (context.getPackageName().equals(packageName)) {
    //Intent launchIntent = new Intent(context, MainActivity.class);//重新启动应用
    //此处如果不想写死启动的Activity,也可以通过如下方法获取默认的启动Activity
    Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
    launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(launchIntent);
    }
    }
    }
    }
    七、在AndroidManifest注册广播 并添加对应权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="android.laboreryao.update">

<uses-permission  
    android:name="android.permission.INSTALL_PACKAGES"  
    tools:ignore="ProtectedPermissions"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

<application>  
    <receiver android:name=".BootBroadcastReceiver">  
        <intent-filter>  
            <action android:name="android.intent.action.PACKAGE_ADDED"/>  
            <action android:name="android.intent.action.PACKAGE_REPLACED"/>  
            <action android:name="android.intent.action.PACKAGE_REMOVED"/>  

            <data android:scheme="package"/>  
        </intent-filter>  
    </receiver>  
</application>  

</manifest>

八、打包插件arr包

九、将arr包放到uniapp项目 配置本地插件 打自定义基座 使用基座调试

0 关注 分享

要回复文章请先登录注册

LaborerYao丶

LaborerYao丶 (作者)

回复 土司 :
可能是我保存文章的时候 本地资源被删了,后续有空了补上!
2021-07-14 17:04
土司

土司

文章的图怎么没了
2021-07-12 17:20