Android 静默安装和智能安装的实现方法

1 简介

最近研究了Android的静默安装和智能安装,于是写博客记录一下。

静默安装就是无声无息的在后台安装apk,没有任何界面提示。

智能安装就是有安装界面,但全部是自动的,不需要用户去点击。

首先强调两点:

  1. 静默安装必须要root权限
  2. 智能安装必须要用户手动开启无障碍服务

2 原理

  1. 静默安装、卸载的原理就是利用pm install命令来安装apk,pm uninstall 来卸载apk.
  2. 智能安装是利用android系统提供的无障碍服务AccessibilityService,来模拟用户点击,从而自动安装.

3 pm命令介绍

(1) pm install

pm install 命令的用法及参数解释如下:

pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH

Options:
  -l: install the package with FORWARD_LOCK.
  -r: reinstall an exisiting app, keeping its data.
  -t: allow test .apks to be installed.
  -i: specify the installer package name.
  -s: install package on sdcard.
  -f: install package on internal flash.

(2) pm uninstall

pm uninstall 命令的用法及参数解释如下:

pm uninstall [-k] PACKAGE

Options:
  -k: keep the data and cache directories around.

上面英语很简单,不解释了.

4 静默安装

为了方便演示,我把爱奇艺的安装包重命名为test.apk后放在了sdcard上。你可以自己去爱奇艺官网去下载,也可以自己找一个apk放到sdcard上,但是要知道apk的包名,后面卸载的时候要用到。

先上代码:

//静默安装
    private void installSlient() {
        String cmd = "pm install -r /mnt/sdcard/test.apk";
        Process process = null;
        DataOutputStream os = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;
        try {
            //静默安装需要root权限
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.write(cmd.getBytes());
            os.writeBytes("\n");
            os.writeBytes("exit\n");
            os.flush();
            //执行命令
            process.waitFor();
            //获取返回结果
            successMsg = new StringBuilder();
            errorMsg = new StringBuilder();
            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String s;
            while ((s = successResult.readLine()) != null) {
                successMsg.append(s);
            }
            while ((s = errorResult.readLine()) != null) {
                errorMsg.append(s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (process != null) {
                    process.destroy();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //显示结果
        tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());
    }

这段代码就是在程序中执行pm命令,和在adb下执行 pm install -r /mnt/sdcard/test.apk 效果是一样的, 关键的代码是 Runtime.getRuntime().exec(“su”) ,这段代码会要求获取root权限,所以你的手机必须root,不想root的话,直接用模拟器也可以。

通过 Runtime.getRuntime().exec(“su”) 获取到 process 对象后就可以写入命令了,每写入一条命令就要换行,写入 ‘\n’ 即可,最后写入exit后离开命令执行的环境.

5 静默卸载

静默卸载和静默安装是一样的,只是命令不同,静默卸载需要用到包名,同样,静默卸载也需要root权限

看代码:

//爱奇艺apk的包名
private static final String PACKAGE_NAME = "com.qiyi.video";
//静默卸载
    private void uninstallSlient() {
        String cmd = "pm uninstall " + PACKAGE_NAME;
        Process process = null;
        DataOutputStream os = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;
        try {
            //卸载也需要root权限
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.write(cmd.getBytes());
            os.writeBytes("\n");
            os.writeBytes("exit\n");
            os.flush();
            //执行命令
            process.waitFor();
            //获取返回结果
            successMsg = new StringBuilder();
            errorMsg = new StringBuilder();
            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String s;
            while ((s = successResult.readLine()) != null) {
                successMsg.append(s);
            }
            while ((s = errorResult.readLine()) != null) {
                errorMsg.append(s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (process != null) {
                    process.destroy();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //显示结果
        tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());
    }

和静默安装一样的代码就不解释了。还有,如果你不知道一个apk的包名,那么请反编译后去看AndroidManifest.xml文件,如果这个文件打开全是乱码,说明是被混淆过的,那么直接安装它,然后到/data/data下面去找它的包,当然,手机得root才能进/data/data目录。

6 智能安装

智能安装就稍微麻烦点了,原理是用到了android提供的AccessibilityService服务,这个服务可以获取屏幕上的节点,一个节点也就是一个view,我们写的xml文件中每个标签就是一个节点,然后可以模拟用户的操作,对这些节点进行点击、滑动等操作。我们就是利用这个原理,来自动点击安装按钮的,当然使用这个服务必须用户手动开启无障碍服务。下面我们来看具体的实现方法。

(1) 创建AccessibilityService配置文件

在res目录下创建xml目录,然后在xml目录下创建一个accessibility_service_config.xml文件,内容如下

res/xml/accessibility_service_config.xml:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
                       android:accessibilityEventTypes="typeAllMask"
                       android:accessibilityFeedbackType="feedbackGeneric"
                       android:accessibilityFlags="flagDefault"
                       android:canRetrieveWindowContent="true"
                       android:description="@string/desc"
                       android:packageNames="com.android.packageinstaller"
    />

accessibilityEventTypes:指定我们在监听窗口中可以模拟哪些事件,typeAllMask表示所有的事件都能模拟.

accessibilityFeedbackType:指定无障碍服务的反馈方式.

canRetrieveWindowContent:指定是否允许我们的程序读取窗口中的节点和内容,当然是true.

description: 当用户手动配置服务时,会显示给用户看.

packageNames: 指定我们要监听哪个应用程序下的窗口活动,这里写com.android.packageinstaller表示监听Android系统的安装界面。

其余参数照写即可。

res/strings.xml:

<resources>
    <string name="app_name">SlientInstallTest</string>
    <string name="desc">智能安装app功能演示</string>
</resources>

(2) 创建AccessibilityService服务

public class MyAccessibilityService extends AccessibilityService {

    private static final String TAG = "[TAG]";
    private Map<Integer, Boolean> handleMap = new HashMap<>();

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        AccessibilityNodeInfo nodeInfo = event.getSource();
        if (nodeInfo != null) {
            int eventType = event.getEventType();
            if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                if (handleMap.get(event.getWindowId()) == null) {
                    boolean handled = iterateNodesAndHandle(nodeInfo);
                    if (handled) {
                        handleMap.put(event.getWindowId(), true);
                    }
                }
            }

        }
    }

    @Override
    public void onInterrupt() {

    }

    //遍历节点,模拟点击安装按钮
    private boolean iterateNodesAndHandle(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo != null) {
            int childCount = nodeInfo.getChildCount();
            if ("android.widget.Button".equals(nodeInfo.getClassName())) {
                String nodeCotent = nodeInfo.getText().toString();
                Log.d(TAG, "content is: " + nodeCotent);
                if ("安装".equals(nodeCotent) || "完成".equals(nodeCotent) || "确定".equals(nodeCotent)) {
                    nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    return true;
                }
            }
            //遇到ScrollView的时候模拟滑动一下
            else if ("android.widget.ScrollView".equals(nodeInfo.getClassName())) {
                nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
            }
            for (int i = 0; i < childCount; i++) {
                AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);
                if (iterateNodesAndHandle(childNodeInfo)) {
                    return true;
                }
            }
        }
        return false;
    }
}

当进入apk安装界面就会回调onAccessibilityEvent()这个方法,我们只关心TYPE_WINDOW_CONTENT_CHANGED和TYPE_WINDOW_STATE_CHANGED两个事件,为了防止重复处理事件,用一个map来过滤事件,后面递归遍历节点,找到’安装’ ‘完成’ ‘确定’ 的按钮,就点击,由于安装界面需要滚动一下才能出现安装按钮,所以遇到ScrollView的时候就滚动一下.

(3) 在AndroidManifest中配置服务

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <service
            android:name=".MyAccessibilityService"
            android:label="智能安装App"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
            >
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService"/>
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessibility_service_config"
                />
        </service>
    </application>

重点是后面的service标签:

android:label:这个就是用户看到的无障碍服务的名称

android:permission: 需要用到BIND_ACCESSIBILITY_SERVICE这个权限.

action: android.accessibilityservice.AccessibilityService 有了这个action,用户才能在设置里面看到我们的服务,否则用户无法开启我们写的服务,也就不能进到我们写的MyAccessibilityService里面了.所以,注意不要写错了,如果你发现无障碍服务里面没有我们写的服务,请检查这里.

(4) 调用智能安装代码

前面准备工作完毕后,现在要用了,调用智能安装的代码如下:

 //智能安装
    private void smartInstall() {
        Uri uri = Uri.fromFile(new File("/mnt/sdcard/test.apk"));
        Intent localIntent = new Intent(Intent.ACTION_VIEW);
        localIntent.setDataAndType(uri, "application/vnd.android.package-archive");
        startActivity(localIntent);
    }

(5) 手动配置智能安装服务

代码运行之后,还要用户选择开启智能安装服务,让用户自己去找是不明智的,因此,我们要主动跳到配置界面,代码如下:

//跳转到开启智能安装服务的界面
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(intent);

配置如下图:

看到了吗,上面显示的就是Service里面的label的值,如果你没有上面的选项,请检查AndroidManifest里面Service的配置.

点击’智能安装App’,开启服务,如下图:

其中的提示文字就是我们在res/xml/accessibility_service_config.xml文件中配置的description属性

7 只能我们写的app可以自动安装

这样写完代码可以运行,点击按钮自动安装sdcard上的test.apk.但是你会发现,所有apk都会自动安装,这就不符合我们的要求了,我们要求只能通过我们写的app来自动安装,其他apk还是要用户手动去点。怎么解决这个问题呢?

思路是:在MainActivity中创建一个public static boolean flag,在MyAccessibilityService的onAccessibilityEvent()中加一个flag判断,然后调用智能安装前flag设为true,创建apk安装事件的广播接收器,当apk安装完成后,设置falg为false,这样其他apk就不能自动安装了,就解决了这个问题

下面上完整代码.

8 完整代码

app/MainActivity.java:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "[TAG][MainActivity]";
    private static final String PACKAGE_NAME = "com.qiyi.video";
    private String apkPath = "/mnt/sdcard/test.apk";
    public static boolean flag = false;//控制只能自己的app才能执行智能安装
    private TextView tvTest;
    private MyInstallReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvTest = (TextView) findViewById(R.id.tv_test);
        findViewById(R.id.btn_install).setOnClickListener(this);
        findViewById(R.id.btn_uninstall).setOnClickListener(this);
        findViewById(R.id.btn_set).setOnClickListener(this);
        findViewById(R.id.btn_smart_install).setOnClickListener(this);
        //注册apk安装监听
        receiver = new MyInstallReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.intent.action.PACKAGE_ADDED");
        filter.addAction("android.intent.action.PACKAGE_REMOVED");
        filter.addDataScheme("package");
        this.registerReceiver(receiver, filter);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            //静默安装
            case R.id.btn_install:
                installSlient();
                break;
            //静默卸载
            case R.id.btn_uninstall:
                uninstallSlient();
                break;
            //设置无障碍服务
            case R.id.btn_set:
                //跳转到开启无障碍服务的界面
                Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
                startActivity(intent);
                break;
            //智能安装
            case R.id.btn_smart_install:
                //控制只能自己的app才能智能安装
                flag = true;
                smartInstall();
                break;
        }
    }

    //静默安装
    private void installSlient() {
        String cmd = "pm install -r /mnt/sdcard/test.apk";
        Process process = null;
        DataOutputStream os = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;
        try {
            //静默安装需要root权限
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.write(cmd.getBytes());
            os.writeBytes("\n");
            os.writeBytes("exit\n");
            os.flush();
            //执行命令
            process.waitFor();
            //获取返回结果
            successMsg = new StringBuilder();
            errorMsg = new StringBuilder();
            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String s;
            while ((s = successResult.readLine()) != null) {
                successMsg.append(s);
            }
            while ((s = errorResult.readLine()) != null) {
                errorMsg.append(s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (process != null) {
                    process.destroy();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //显示结果
        tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());
    }

    //静默卸载
    private void uninstallSlient() {
        String cmd = "pm uninstall " + PACKAGE_NAME;
        Process process = null;
        DataOutputStream os = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;
        try {
            //卸载也需要root权限
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.write(cmd.getBytes());
            os.writeBytes("\n");
            os.writeBytes("exit\n");
            os.flush();
            //执行命令
            process.waitFor();
            //获取返回结果
            successMsg = new StringBuilder();
            errorMsg = new StringBuilder();
            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String s;
            while ((s = successResult.readLine()) != null) {
                successMsg.append(s);
            }
            while ((s = errorResult.readLine()) != null) {
                errorMsg.append(s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (process != null) {
                    process.destroy();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //显示结果
        tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());
    }

    //智能安装
    private void smartInstall() {
        Uri uri = Uri.fromFile(new File(apkPath));
        Intent localIntent = new Intent(Intent.ACTION_VIEW);
        localIntent.setDataAndType(uri, "application/vnd.android.package-archive");
        startActivity(localIntent);
    }

    //监听apk安装
    private class MyInstallReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {     // install
                String packageName = intent.getDataString();
                Log.i(TAG, "安装了 :" + packageName);
                //安装完毕,设置flag,从而使得其余的apk不能自动安装
                flag = false;
            }
            if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {   // uninstall
                String packageName = intent.getDataString();
                Log.i(TAG, "卸载了 :" + packageName);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (receiver != null) {
            unregisterReceiver(receiver);
        }
    }
}

界面上就三个按钮

res/layout/activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/tv_test"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text=""
        />

    <Button
        android:id="@+id/btn_install"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="安装"
        />

    <Button
        android:id="@+id/btn_uninstall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/btn_install"
        android:text="卸载"
        />

    <Button
        android:id="@+id/btn_set"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/btn_uninstall"
        android:text="开启智能安装功能"
        />

    <Button
        android:id="@+id/btn_smart_install"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/btn_set"
        android:text="智能安装"
        />
</RelativeLayout>

服务配置文件

res/xml/accessibility_service_config.xml

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
                       android:accessibilityEventTypes="typeAllMask"
                       android:accessibilityFeedbackType="feedbackGeneric"
                       android:accessibilityFlags="flagDefault"
                       android:canRetrieveWindowContent="true"
                       android:description="@string/desc"
                       android:packageNames="com.android.packageinstaller"
    />

智能安装服务

app/MyAccessibilityService.java:

public class MyAccessibilityService extends AccessibilityService {

    private static final String TAG = "[TAG]";
    private Map<Integer, Boolean> handleMap = new HashMap<>();

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        AccessibilityNodeInfo nodeInfo = event.getSource();
        if (nodeInfo != null && MainActivity.flag) {
            int eventType = event.getEventType();
            if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                if (handleMap.get(event.getWindowId()) == null) {
                    boolean handled = iterateNodesAndHandle(nodeInfo);
                    if (handled) {
                        handleMap.put(event.getWindowId(), true);
                    }
                }
            }

        }
    }

    @Override
    public void onInterrupt() {

    }

    //遍历节点,模拟点击安装按钮
    private boolean iterateNodesAndHandle(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo != null) {
            int childCount = nodeInfo.getChildCount();
            if ("android.widget.Button".equals(nodeInfo.getClassName())) {
                String nodeCotent = nodeInfo.getText().toString();
                Log.d(TAG, "content is: " + nodeCotent);
                if ("安装".equals(nodeCotent) || "完成".equals(nodeCotent) || "确定".equals(nodeCotent)) {
                    nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    return true;
                }
            }
            //遇到ScrollView的时候模拟滑动一下
            else if ("android.widget.ScrollView".equals(nodeInfo.getClassName())) {
                nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
            }
            for (int i = 0; i < childCount; i++) {
                AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);
                if (iterateNodesAndHandle(childNodeInfo)) {
                    return true;
                }
            }
        }
        return false;
    }
}

最后是配置文件AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.slientinstalltest">

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <service
            android:name=".MyAccessibilityService"
            android:label="智能安装App"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
            >
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService"/>
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessibility_service_config"
                />
        </service>
    </application>

</manifest>

注意:请把自己要安装的apk放到sdcard上,并且修改代码中的apk路径和包名

9 运行效果

10 代码下载

演示代码已经上传,下载地址:

http://download.csdn.net/detail/fuchaosz/9570881

11 总结

Android智能安装的原理就是利用了类似钩子的服务,这个服务还可以用于微信抢红包的开发,怎么样,是不是比ios好玩儿的多呢.

12 转载请注明来自”梧桐那时雨”的博客:http://blog.csdn.net/fuchaosz/article/details/51852442

Tips

如果觉得这篇博客对你有帮助或者喜欢博主的写作风格,就给博主留个言或者顶一下呗,鼓励博主创作出更多优质博客,Thank you.

时间: 2024-08-24 00:50:38

Android 静默安装和智能安装的实现方法的相关文章

android静默安装和智能安装(转)

Android 静默安装和智能安装的实现方法 http://blog.csdn.net/fuchaosz/article/details/51852442 Android静默安装实现方案,仿360手机助手秒装和智能安装功能 http://blog.csdn.net/guolin_blog/article/details/47803149 5.0以上 静默安装的安装包放在根目录下,如:Environment.getRootDirectory().toString()+"/xxx.apk"

Android静默安装实现方案,仿360手机助手秒装和智能安装功能

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/47803149 之前有很多朋友都问过我,在Android系统中怎样才能实现静默安装呢?所谓的静默安装,就是不用弹出系统的安装界面,在不影响用户任何操作的情况下不知不觉地将程序装好.虽说这种方式看上去不打搅用户,但是却存在着一个问题,因为Android系统会在安装界面当中把程序所声明的权限展示给用户看,用户来评估一下这些权限然后决定是否要安装该程序,但如果使用了静默安装的方式,也就没

Android静默安装和静默卸载

静默顾名思义就是静静的默默地,静默安装和静默卸载的意思也就是说在后台默默地安装和卸载. 最近的一个app应用分发的项目中app下载的模块,下载完成之后,用户可以通过这个app进行安装,为了提高用户的体验,我就加入了静默安装和卸载功能,然后还加入了使用am命令启动某个Activity. 这个项目中静默的方式实现代码如下: 首先判断是否有root权限,如果有利用静默方式,否则利用意图实现app安装和卸载操作. package com.example.test; import java.io.File

绕过身份检测,破解Android SU(android静默安装)

由于Android底层是Linux内核,故了解了Linux的权限管理后就可以知道ROOT的原理,具体可以访问<Android系统权限和root权限>一文,而一般的Androd下的su命令只支持在ROOT用户和SHELL用户下才有权限让程序以root用户身份运行,其实看完Android源码下的system/extras/su/su.c代码即可清楚,而我们绕过了其中的当前运行用户判断来让所有的用户都可以将以自己身份运行的程序尝试去设置以root用户身份运行,即运行su命令不需判断运行程序的当前用户

Android 静默安装/后台安装&amp; Root permission

Android 静默安装/后台安装& Root permission 静默安装其实很简单,今天在网上找资料找半天都说的很复杂,什么需要系统安装权限.调用系统隐藏的api.需要系统环境下编译.需要跟systemUI同进程什么的.我不知道他们真的实现了静默安装实现方式,亲测效果跟豌豆荚一样,并且实现起来非常简单: 1.支持静默安装的机器必须Root,这个不需要我多讲了. 2.使用pm指令安装即可.     3.特别注意 PM指令不支持中文,也就说路径中有中文会导致安装失败! 关键代码如下: exec

Android 静默安装Apk

参考链接 android 静默安装 [Android]实现静默安装APK的两种方法

Android菜鸟笔记- 获取未安装的APK图标、版本、包名、名称、是否安装、安装、打开

周末闲来无事,把Android的基础知识拿出来复习复习,今天主题是<获取未安装的APK图标.版本.包名.名称.是否安装.跳转安装.打开> 一.获取APK图标 通常读取APK的图标可以用,PackageManager里面的getApplicationIcon(ApplicationInfo)来得到一个drawable.但实际使用的时候经常只能得到一个默认的图标,根本不是APK的图标. 参考小米开源文件管理器,结合实践,代码如下: /* * 采用了新的办法获取APK图标,之前的失败是因为andro

.Net 转战 Android 4.4 日常笔记(5)--新软件Android Studio 0.5.8安装与配置及问题解决

原文:.Net 转战 Android 4.4 日常笔记(5)--新软件Android Studio 0.5.8安装与配置及问题解决 说真心话,Eclipse跟我们.net的VS比起来就是屌丝比高富帅,一切都是那么的难用,速度慢得我无法忍受 于是想试试Google钦点的Android Studio IDE工具,这跟ADT一样也是一套集成工具,也需要安装java JDK 1.下载最新的JDKhttp://developers.sun.com/downloads/ 我是下载JDK1.7版本,安装过程可

Android Studio 1.1的安装和遇到的坑

Google的Android Studio 出1.0稳定版本也有很久的时间了,一直喜欢Jetbrains公司的IDE,不同语言的IDE操作习惯都比较统一. 而Android Studio 是基于IntelliJ IDEA的社区版开发的 ,怎么也要尝尝鲜才行. 今天安装了下,被几个小坑卡住了,最终解决,发现类似博客过多的记录了安装过程,而没有针对遇到的问题做出统一的解答,故把自己的安装过程记录博客备忘,或可帮助一些朋友减少不必要的麻烦. 一.下载地址: 先附上官方地址:http://develop