zoukankan      html  css  js  c++  java
  • android开发,关于android app实现静默安装自己(系统签名)

    产品需求,木有办法。android系统是跟厂商定制的,保证系统开机就运行我们的app,并且实现自己静默安装,完全自动化,无需人工操作。

    网上有很多办法,

    1、要么要通过android 源码拿到密钥文件,参考:http://www.cnblogs.com/brucenan/archive/2012/10/04/2711817.html

    2、通过root权限,可以参考代码(已测试安装别人的apk可以,但是不能安装自己):

    import java.io.File;
    import java.io.PrintWriter;
    import android.content.Context;
    import android.content.Intent;
    import android.net.Uri;
    import android.util.Log;
    
    public class ApkController {
        /**
         * 描述: 安装
         */
        public static boolean install(String apkPath,Context context){
            // 先判断手机是否有root权限
            if(hasRootPerssion()){
                // 有root权限,利用静默安装实现
                return clientInstall(apkPath);
            }else{
                // 没有root权限,利用意图进行安装
                File file = new File(apkPath);
                if(!file.exists())
                    return false; 
                Intent intent = new Intent();
                intent.setAction("android.intent.action.VIEW");
                intent.addCategory("android.intent.category.DEFAULT");
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
                context.startActivity(intent);
                return true;
            }
        }
         
        /**
         * 描述: 卸载
         */
        public static boolean uninstall(String packageName,Context context){
            if(hasRootPerssion()){
                // 有root权限,利用静默卸载实现
                return clientUninstall(packageName);
            }else{
                Uri packageURI = Uri.parse("package:" + packageName);
                Intent uninstallIntent = new Intent(Intent.ACTION_DELETE,packageURI);
                uninstallIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(uninstallIntent);
                return true;
            }
        }
         
        /**
         * 判断手机是否有root权限
         */
        public static boolean hasRootPerssion(){
            PrintWriter PrintWriter = null;
            Process process = null;
            try {
                process = Runtime.getRuntime().exec("su");
                PrintWriter = new PrintWriter(process.getOutputStream());
                PrintWriter.flush();
                PrintWriter.close();
                int value = process.waitFor();  
                return returnResult(value);
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if(process!=null){
                    process.destroy();
                }
            }
            return false;
        }
         
        /**
         * 静默安装
         */
        public static boolean clientInstall(String apkPath){
            PrintWriter PrintWriter = null;
            Process process = null;
            try {
                process = Runtime.getRuntime().exec("su");
                PrintWriter = new PrintWriter(process.getOutputStream());
                PrintWriter.println("chmod 777 "+apkPath);
                PrintWriter.println("export LD_LIBRARY_PATH=/vendor/lib:/system/lib");
                PrintWriter.println("pm install -r "+apkPath);
    //          PrintWriter.println("exit");
                PrintWriter.flush();
                PrintWriter.close();
                int value = process.waitFor();  
                return returnResult(value);
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if(process!=null){
                    process.destroy();
                }
            }
            return false;
        }
         
        /**
         * 静默卸载
         */
        public static boolean clientUninstall(String packageName){
            PrintWriter PrintWriter = null;
            Process process = null;
            try {
                process = Runtime.getRuntime().exec("su");
                PrintWriter = new PrintWriter(process.getOutputStream());
                PrintWriter.println("LD_LIBRARY_PATH=/vendor/lib:/system/lib ");
                PrintWriter.println("pm uninstall "+packageName);
                PrintWriter.flush();
                PrintWriter.close();
                int value = process.waitFor();  
                return returnResult(value); 
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if(process!=null){
                    process.destroy();
                }
            }
            return false;
        }
         
        /**
         * 启动app
         * com.exmaple.client/.MainActivity
         * com.exmaple.client/com.exmaple.client.MainActivity
         */
        public static boolean startApp(String packageName,String activityName){
            boolean isSuccess = false;
            String cmd = "am start -n " + packageName + "/" + activityName + " 
    ";
            Process process = null;
            try {
               process = Runtime.getRuntime().exec(cmd);
               int value = process.waitFor();  
               return returnResult(value);
            } catch (Exception e) {
              e.printStackTrace();
            } finally{
                if(process!=null){
                    process.destroy();
                }
            }
            return isSuccess;
        }
        
        private static boolean returnResult(int value){
            // 代表成功  
            if (value == 0) {
                return true;
            } else if (value == 1) { // 失败
                return false;
            } else { // 未知情况
                return false;
            }  
        }
    }

    3、通过走系统应用的方法(因为机器是我们定制生产,所以可以将app预置到system/app目录下,无需安装,直接重启,可以看到系统再次开机时会显示系统升级,然后就可以看到我们的app安装成功),可以试着先adb命令执行,再复制到代码中去执行。注意,如果app的lib中有.so文件,则还需要将.so文件拷贝到system/libs目录,否则报错(我的解决办法是暂时将用到.so文件的地方注释掉,等有时间再做)

    adb 命令:

     $ adb push SecureSetting.apk /sdcard/  // 上传要安装的文件,为安装做准备。
     $ adb shell $ su // 切换到 root 用户。如果没有获得 Root 权限,这一步不会成功。
     # mount //显示当前mount情况
     # mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system // 让分区可写。 
     # cat /sdcard/SecureSetting.apk > /system/app/SecureSetting.apk // 这一步可以用 cp 实现,但一般设备中没有包含该命令。如果使用 mv 会出现错误:failed on '/sdcard/NetWork.apk' - Cross-device link。 
     chmod 777 chetou.apk
     # mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system // 还原分区属性,只读。 
     # exit $ exit

    代码执行:

    /**
         * 将文件复制到system/app 目录
         * @param apkPath 特别注意格式:该路径不能是:/storage/emulated/0/app/QDemoTest4.apk 需要是:/sdcard/app/QDemoTest4.apk
         * @return
         */
        public static boolean copy2SystemApp(String apkPath){
            PrintWriter PrintWriter = null;
            Process process = null;
            String appName = "test.apk",cmd;
            
            try {
                process = Runtime.getRuntime().exec("su");
                PrintWriter = new PrintWriter(process.getOutputStream());
                cmd = "mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system";
                Log.e("copy2SystemApp", cmd);
                PrintWriter.println(cmd);
                
                cmd = "cat "+apkPath+" > /system/app/"+appName;
                Log.e("copy2SystemApp", cmd);
                PrintWriter.println(cmd);
                
                cmd = "chmod 777 /system/app/"+appName +" -R";
                Log.e("copy2SystemApp", cmd);
                PrintWriter.println(cmd);
                
                cmd = "mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system";
                Log.e("copy2SystemApp", cmd);
                PrintWriter.println(cmd);
                PrintWriter.println("reboot");  //重启
                PrintWriter.println("exit");
                PrintWriter.flush();
                PrintWriter.close();
                int value = process.waitFor();
                return returnResult(value);
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if(process!=null){
                    process.destroy();
                }
            }
            return false;
        }

    注意代码里有差异性,因为需要给文件 chmod 777权限,否则不会自动升级安装。流程可以参考:http://blog.163.com/wwj0925@126/blog/static/19120110201522242241563/

  • 相关阅读:
    第一道题:无头苍蝇装头术(望不吝赐教)
    jdk8 list是否包含某值的一些应用
    Failed to close server connection after message failures; nested exception is javax.mail.MessagingException: Can't send command to SMTP host
    itext pdf加密
    TiDB-禁用遥测功能
    TiDB-配置调整
    DM-表空间
    DM-INI参数配置
    DM-DSC集群配置
    PG-并行查询
  • 原文地址:https://www.cnblogs.com/feijian/p/5160575.html
Copyright © 2011-2022 走看看