精华内容
下载资源
问答
  • 静默安装

    2020-12-29 09:29:06
    android8.0下实现静默安装 首先, 这篇文章主要讲的是在系统的安装器内增加一个服务来实现静默安装应用,想实现在第三方应用内静默安装,不在讲述范围。 我们需要拥有系统源码,系统安装器源码位置为androidO\...

    android8.0下实现静默安装

    首先, 这篇文章主要讲的是在系统的安装器内增加一个服务来实现静默安装应用,想实现在第三方应用内静默安装,不在讲述范围。
    我们需要拥有系统源码,系统安装器源码位置为androidO\packages\apps\PackageInstaller,在这个源码里面,添加一个SilentInstallationService服务来实现静默安装逻辑,增加一个广播接收器作为外界静默安装的入口,至于参数,只需要传需要安装的apk的路径,安装结果以广播的方式发出。正常情况下,如果在文件管理器里直接点击apk安装包,就会启动系统的安装器对apk进行安装,这种安装形式需要用户不断点击才能实现整个安装流程。 如果我们想在一个版本内预置一些第三方apk,又不想手动去点击,又想批量完成这些操作, 那么就需要静默安装,比如规定某个文件目录,在系统启动后,去检测这个目录下是否存放有apk文件, 如果有,则进行静默安装。 静默安装主要代码如下:

        class InstallRunnable implements Runnable{
    
            private String apkpath;
    
            public InstallRunnable(String apkpath) {
                this.apkpath = apkpath;
            }
    
            @Override
            public void run() {
                Log.i(TAG,"run >> to install " + apkpath);
                boolean result = false;
                int mSessionId = 0;
                int mInstallId = 0;
                PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                            PackageInstaller.SessionParams.MODE_FULL_INSTALL);
                    params.referrerUri = null;
                    params.originatingUri = null;
                    params.originatingUid = mUid;
    
                    File file = new File(apkpath);
                    try {
                        PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
                        params.setAppPackageName(pkg.packageName);
                        params.setInstallLocation(pkg.installLocation);
                        params.setSize(
                                PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
                        Log.i(TAG,"params.referrerUri =" + params.referrerUri + ", params.originatingUri =" + params.originatingUri
                        + ", params.originatingUid =" + params.originatingUid + ", params.appPackageName =" + params.appPackageName + ", params.installLocation =" + params.installLocation
                        + ", params.sizeBytes =" + params.sizeBytes);
                    } catch (PackageParser.PackageParserException e) {
                        Log.e(TAG, "Cannot parse package " + file + ". Assuming defaults.");
                        Log.e(TAG,
                                "Cannot calculate installed size " + file + ". Try only apk size.");
                        params.setSize(file.length());
                    } catch (IOException e) {
                        e.printStackTrace();
                        Log.e(TAG,
                                "Cannot calculate installed size " + file + ". Try only apk size.");
                        params.setSize(file.length());
                    }
    
    
                    try {
                         mInstallId = InstallEventReceiver
                                .addObserver(mContext, EventResultPersister.GENERATE_NEW_ID,
                                        new InstallObserver(apkpath));
                    } catch (EventResultPersister.OutOfIdsException e) {
                        e.printStackTrace();
                        result = false;
                        sendInstallState(apkpath,INSTALL_STATE_ERROR);
                        return;
                    }
    
                    try {
                        mSessionId = getPackageManager().getPackageInstaller().createSession(params);
                        mInstallList.add(new InstallInfo(mSessionId,apkpath,INSTALL_STATE_INSTALLING));
                    } catch (IOException e) {
                        result = false;
                        e.printStackTrace();
                        sendInstallState(apkpath,INSTALL_STATE_ERROR);
                        return;
                    }
                PackageInstaller.Session session = null;
                try {
                    session = getPackageManager().getPackageInstaller().openSession(mSessionId);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    session.setStagingProgress(0);
    
                    try (InputStream in = new FileInputStream(file)) {
                        long sizeBytes = file.length();
                        try (OutputStream out = session.openWrite("PackageInstaller", 0, sizeBytes)) {
                            byte[] buffer = new byte[1024 * 1024];
                            while (true) {
                                int numRead = in.read(buffer);
    
                                if (numRead == -1) {
                                    session.fsync(out);
                                    break;
                                }
    
                                //中断安装
    //                            if (isCancelled()) {
    //                                session.close();
    //                                break;
    //                            }
    
                                out.write(buffer, 0, numRead);
                                if (sizeBytes > 0) {
                                    float fraction = ((float) numRead / (float) sizeBytes);
                                    session.addProgress(fraction);
                                    Log.i(TAG,"numRead = " + numRead + " bytes");
                                }
                            }
                        }
                    }
                    result = true;
                } catch (IOException | SecurityException e) {
                    Log.e(TAG, "Could not write package", e);
    
                    session.close();
                    result = false;
                    sendInstallState(apkpath,INSTALL_STATE_ERROR);
                    return;
    
                } finally {
                    synchronized (this) {
                        Log.i(TAG, "session write finish!!!");
                    }
                }
    
                if (session != null && result) {
                    Log.i(TAG,"mInstallId =" + mInstallId);
                    Intent broadcastIntent = new Intent(BROADCAST_ACTION);
                    broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                    broadcastIntent.setPackage(
                            getPackageManager().getPermissionControllerPackageName());
                    broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);
    
                    PendingIntent pendingIntent = PendingIntent.getBroadcast(
                            mContext,
                            mInstallId,
                            broadcastIntent,
                            PendingIntent.FLAG_UPDATE_CURRENT);
                    session.commit(pendingIntent.getIntentSender());
                }else{
                    getPackageManager().getPackageInstaller().abandonSession(mSessionId);
                    sendInstallState(apkpath,INSTALL_STATE_ERROR);
                    return;
                }
            }
        }
    

    这个方法需要放入androidO\packages\apps\PackageInstaller这个包下的服务中执行,因为主要逻辑需要用到这个包中的类,当然这个服务需要自己创建,最好使用一个异步的Handler来post这个runnable,实例化这个runnable的时候传入需要安装的apk路径就好。 这里安装的时候直接对源文件进行读写操作,而从文件管理器点击进入有把源文件拷贝到临时文件目录下再对拷贝的apk进行读写操作, 应该在一定程度上防止了对源文件的损坏。 安装的时候需要uid,这里我们直接使用packageinstaller自身的UID。即:

            try{
                PackageManager pm = getPackageManager();
                ApplicationInfo ai = pm.getApplicationInfo(this.getPackageName(), PackageManager.GET_ACTIVITIES);
                mUid = ai.uid;
                Log.i(TAG,"uid =" + mUid);
            }catch (Exception e){
                e.printStackTrace();
            }
    

    需要注意的一些事项:
    1.android8.0不允许静态广播启动后台服务,应该使用startForegroundService的方式启动成前台服务,然后在服务的onStartCommand方法里调用startForeground方法,否则服务启动后会被系统杀掉。

        private void startForeground() {
            String CHANNEL_ONE_ID = "com.android.install";
            String CHANNEL_ONE_NAME = "install";
            Notification.Builder builder = new Notification.Builder(this.getApplicationContext()); //获取一个Notification构造器
            builder.setContentTitle("Install") // 设置下拉列表里的标题
                    .setSmallIcon(android.R.drawable.presence_busy) // 设置状态栏内的小图标
                    .setContentText("Install apk now...") // 设置上下文内容
                    .setWhen(System.currentTimeMillis()); // 设置该通知发生的时间
    
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                //修改安卓8.1以上系统报错
                NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN);
                notificationChannel.enableLights(false);//如果使用中的设备支持通知灯,则说明此通知通道是否应显示灯
                notificationChannel.setShowBadge(false);//是否显示角标
                notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
                NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                manager.createNotificationChannel(notificationChannel);
                builder.setChannelId(CHANNEL_ONE_ID);
            }
            Notification notification = builder.build(); // 获取构建好的Notification
            notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
            startForeground(1, notification);
        }
    

    2.当系统中有谷歌框架的时候,也就是存在com.android.vending这个包的时候,在安装的时候会弹出Turn on play protect?确认窗口,这个窗口弹出后如果没有点击会阻止安装进行,有一种做法是通过AccessibilityService 辅助系统点击确认按钮,这里没有去尝试,而是通过杀掉进程来防止这个软件阻止安装。

            new AsyncTask<Boolean, Object, Boolean>() {
                @Override
                protected Boolean doInBackground(Boolean... booleans) {
                    boolean result = false;
                    while (isNeedKillVending) {
                        //杀 后台进程
                        try {
                            Log.i(TAG, "forceStopPackage run, kill com.android.vending");
                            ActivityManager m = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
                            m.killBackgroundProcesses("com.android.vending");
                        } catch (Exception e) {
                           Log.e(TAG, "forceStopPackage =" + e.toString());
                        }
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    return result;
                }
    
                @Override
                protected void onPostExecute(Boolean aBoolean) {
                }
            }.execute();
    

    用这种发送杀进程,需要添加权限

        <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
    
    展开全文
  • 静默安装oracle

    2019-01-03 13:15:43
    利用oracle自带的自定义脚本,然后静默安装软件、静默建监听、静默建库等
  • 安卓静默安装

    2017-12-13 16:44:31
    静默安装

    好多公司有静默安装的需求(就是不用人去确认就把程序更新了)
    目前主流的技术有无障碍模式、辅助程序加pm命令模式、系统程序
    由于很多条件限制,我现在用的是第二种方案,其他的仅做思路探索,第三种 可行性在上家公司得到了实现。
    优缺点:
    1. 无障碍模式
    AccessibilityService ,具体使用方案有兴趣可以自己去查询下,
    优点:可以模拟人的点击操作
    缺点:不同手机和其他设备差异太大,土豪级别如360 和腾讯之类的可以N多情况都考虑到,中小型公司只能看看了。
    2.辅助程序加pm命令模式
    优点:成本简单,容易实现
    条件:安卓系统root,安装一个辅助程序,目前浪仔用的就是这种
    缺点:需要安装辅助程序
    3.将程序做成系统应用或做一个辅助型的系统应用
    系统应用可以做到开机启动
    优点:简单实用
    缺点:需要高度定制的系统

    下面将我的使用说明书贴出来,给大家一个思路上的参考,索要aar就暂免了,保密需要啊。

    流程信息

    1.在gradle 中添加okhttp 引用

    compile ‘com.squareup.okhttp3:okhttp:+’
    compile ‘com.squareup.okio:okio:+’
    compile(name:’update’,ext:’aar’)

    Android 目录下添加
    repositories {
    flatDir {
    dirs ‘libs’
    }
    }

    2.lib 中添加aar

    3.启动更新服务

    String url = “http://**/app.apk”;
    UpdateManager manager=new UpdateManager(MainActivity.this);
    manager.setDebug(true);
    manager.setUrl(url);
    manager.setApkFilePath(“install3”);
    manager.setApkPath(“zy.apk”);
    manager.start(MainActivity.this);

    4.安装辅助程序(辅助程序不需要启动)

    展开全文
  • 如果需要应用进行静默安装,则需要满足一下两个条件1 必须添加权限 2 必须是系统应用,或者系统签名应用方法 1 通过 adb install 安装/**** @param apkFilePath 安装包路径* @return true 、false*/public boolean ...

    如果需要应用进行静默安装,则需要满足一下两个条件

    1  必须添加权限

    2  必须是系统应用,或者系统签名应用

    方法 1 通过 adb install 安装

    /**

    *

    * @param apkFilePath 安装包路径

    * @return true 、false

    */

    public boolean installByADB(String apkFilePath){

    boolean success = false;

    if (apkFilePath == null || apkFilePath.equals("")) {return success;}

    File apkFile = new File(apkFilePath);

    if (!apkFile.exists() || apkFile.isDirectory()) {return success;}

    String[] args = { "pm", "install", "-r", "-d", apkFilePath };

    ByteArrayOutputStream eBAout = new ByteArrayOutputStream();

    ByteArrayOutputStream nBAout = new ByteArrayOutputStream();

    ProcessBuilder processBuilder = null;

    java.lang.Process process = null;

    InputStream eis = null;

    InputStream is = null;

    int num = 0;

    byte[] buffer = new byte[1024];

    try {

    processBuilder = new ProcessBuilder(args);

    process = processBuilder.start();

    eis = process.getErrorStream();

    while ((num = eis.read(buffer)) != -1) {

    eBAout.write(buffer, 0, num);

    }

    is = process.getInputStream();

    while ((num = is.read(buffer)) != -1) {

    nBAout.write(buffer, 0, num);

    }

    String error = eBAout.toString("UTF-8");

    String normal = nBAout.toString("UTF-8");

    if(normal != null && normal.contains("Success")){success = true;}

    } catch (IOException e) {

    } catch (Exception e) {

    } catch (Throwable t) {

    } finally {

    try {

    if (null != eis) {eis.close();}

    } catch (Exception e) {}

    try {

    if (null != is) {is.close();}

    } catch (Exception e) {}

    process.destroy();

    }

    return success;

    }

    方法2 通过PM安装

    这个方法的前提是将framework参与编译并排列第一

    /**

    * @param context

    * @param apkPath

    */

    public void installSilentlyBYPM(Context context, String apkPath) {

    if(apkPath == null || "".equals(apkPath)){return;}

    File apkFile = new File(apkPath);

    (!apkFile.exists() || apkFile.isDirectory()){return;}

    Uri apkPackageURI = Uri.fromFile(apkFile);

    int installFlags = PackageManager.INSTALL_ALL_USERS|PackageManager.INSTALL_REPLACE_EXISTING;

    PackageManager pm = context.getPackageManager();

    pm.installPackage(apkPackageURI, new PackageInstallObserver(){

    @Override

    public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras){

    super.onPackageInstalled(basePackageName, returnCode, msg, extras);

    if(returnCode == 1){

    //如果安装包的包名等于basePackageName; 则安装成功

    }

    }

    }, installFlags, context.getPackageName());

    }

    展开全文
  • android静默安装

    2016-12-16 10:45:30
    android静默安装
  • 批处理静默安装

    2016-11-10 14:32:51
    批处理静默安装
  • Oracle 19C的下载和安装部署(图形安装和静默安装
  • 静默安装.patch

    2020-05-11 11:31:05
    静默安装.patch
  • oracle静默安装

    2015-12-26 19:31:43
    oracle静默安装
  • Android 静默安装

    2017-10-26 20:45:17
    android 静默安装 需要系统签名使用,接口java反射获取
  • 主要介绍了Android 静默安装实现方法的相关资料,静默安装的方法,静默安装就是绕过安装程序时的提示窗口,直接在后台安装,需要的朋友可以参考下
  • 本篇基于已有系统证书(从Android设备厂家获得)的情况下实现静默安装与静默卸载,可分为三部分讲解:将apk内置为系统应用,apk静默安装与apk静默卸载。1.将apk内置为系统应用。内置的方法有共性,也有区别。基础操作...

    一.轰隆一声雳响,小编闪亮登场。

    本篇基于已有系统证书(从Android设备厂家获得)的情况下实现静默安装与静默卸载,可分为三部分讲解:将apk内置为系统应用,apk静默安装与apk静默卸载。

    1.将apk内置为系统应用。内置的方法有共性,也有区别。基础操作是共性,区别就在于Android4.4以上版本与Android4.4以下版本。

    A.内置为系统应用要做的第一步,就是在清单文件的根节点manifest上添加声明:android:sharedUserId="android.uid.system" 如下图

    1860fd278b16?from=groupmessage

    image.png

    B.内置为系统应用要做的第二步,就是给没有签名过的apk文件签名。

    a.若设备厂家有提供.keystore(系统证书)文件,则利用Android Studio的Build选项下Grnerate Signed Bundle/apk方式直接指定

    签名文件给apk签名即可。默认密码一般都为 android

    b.若没有设备厂家提供的系统证书,那么也可以从对应的Android版本中提取签名文件,只是适配性会有很大的局限。

    可参考https://blog.csdn.net/starhosea/article/details/78696460

    C.内置为系统应用要做的第三步,就是将声明好,签名过的apk,内置到Android系统中(划重点:内置操作所需的adb命令需要先将手机/设备

    ROOT):

    a. Android 4.4以下:4.4以下可利用adb命令将apk内置到 system/app 目录下,再重启系统即可生效。

    详情可参考 https://blog.csdn.net/m0_37135879/article/details/81134472

    b. Android 4.4以上:4.4以上版本将主要的系统应用更改到了system/priv-app目录下,导致很多小伙伴用4.4以下的方式尝试内置系统

    应用时产生了内置无效的情况。4.4以上版本与4.4以下版本内置apk为系统应用的方式是大同小异的,利用adb命令将apk内置到

    system/priv-app 目录下,再重启系统即可生效。

    详情可参考 https://blog.csdn.net/starhosea/article/details/78697007

    D.此步为知识补充,基础adb命令:

    安装:adb install apk路径

    重装:adb install -r 已安装过带签名的apk重装

    卸载:adb uninstall apk包名

    启动:adb shell am start -n 包名/包名.activity

    关闭:adb shell am force-stop 包名

    2.apk静默安装。

    /**

    * 21 * APK静默安装

    * 22 *

    * 23 * @param apkPath

    * 24 * APK安装包路径

    * 25 * @return true 静默安装成功 false 静默安装失败

    * 26

    */

    public static boolean install(String apkPath) {

    String[] args = {"pm", INSTALL_CMD, "-r", apkPath};

    String result = apkProcess(args);

    Log.e(TAG, "install log:" + result);

    if (result != null

    && (result.endsWith("Success") || result.endsWith("Success\n"))) {

    return true;

    }

    return false;

    }

    /**

    * 57 * 应用安装、卸载处理

    * 58 *

    * 59 * @param args

    * 60 * 安装、卸载参数

    * 61 * @return Apk安装、卸载结果

    * 62

    */

    public static String apkProcess(String[] args) {

    String result = null;

    ProcessBuilder processBuilder = new ProcessBuilder(args);

    Process process = null;

    InputStream errIs = null;

    InputStream inIs = null;

    try {

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    int read = -1;

    process = processBuilder.start();

    errIs = process.getErrorStream();

    while ((read = errIs.read()) != -1) {

    baos.write(read);

    }

    baos.write('\n');

    inIs = process.getInputStream();

    while ((read = inIs.read()) != -1) {

    baos.write(read);

    }

    byte[] data = baos.toByteArray();

    result = new String(data);

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    try {

    if (errIs != null) {

    errIs.close();

    }

    if (inIs != null) {

    inIs.close();

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    if (process != null) {

    process.destroy();

    }

    }

    return result;

    }

    3.apk静默卸载。

    /**

    * 39 * APK静默卸载

    * 40 *

    * 41 * @param packageName

    * 42 * 需要卸载应用的包名

    * 43 * @return true 静默卸载成功 false 静默卸载失败

    * 44

    */

    public static boolean uninstall(String packageName) {

    String[] args = {"pm", UNINSTALL_CMD, packageName};

    String result = apkProcess(args);

    Log.e(TAG, "uninstall log:" + result);

    if (result != null

    && (result.endsWith("Success") || result.endsWith("Success\n"))) {

    return true;

    }

    return false;

    }

    二.若您觉得本文对您有帮助,记得点个关注哟~

    展开全文
  • OFFICE2007静默安装

    2019-04-06 09:45:13
    静默安装OFFICE2007使用,直接使用完整版OFFICE2007 ,把文件覆盖到根目录,即可静默安装,安装到系统盘下。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,819
精华内容 3,127
关键字:

静默安装