精华内容
下载资源
问答
  • 之前有很多朋友都问过我,在Android系统中怎样才能实现静默安装呢?所谓的静默安装,就是不用弹出系统的安装界面,在不影响用户任何操作的情况下不知不觉地将程序装好。虽说这种方式看上去不打搅用户,但是却存在着...
  • 本项目是一个Android静默安装实现项目源码,仿360手机助手、百度助手、豌豆荚、等应用助手类秒装和智能安装功能的功能,所谓的秒装其实就是需要ROOT权限的静默安装,其实静默安装的原理很简单,就是调用Android系统...
  • Android逆向助手

    2018-03-12 17:12:14
    以前的工具不好使了 网上的都是不能安装 或者库缺失 这个没问题 能正常使用
  • Windows下最小巧的安卓投屏工具,功能强大且易用,支持将Android屏幕实时投射到PC上,画面清晰,支持全屏显示。兼容Android4.4及以上版本,内置丰富的adb调试命令,支持远程文件浏览功能,便于Android开发及测试。
  • 之前有很多朋友都问过我,在Android系统中怎样才能实现静默安装呢?所谓的静默安装,就是不用弹出系统的安装界面,在不影响用户任何操作的情况下不知不觉地将程序装好。虽说这种方式看上去不打搅用户,但是却存在着...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/47803149


    之前有很多朋友都问过我,在Android系统中怎样才能实现静默安装呢?所谓的静默安装,就是不用弹出系统的安装界面,在不影响用户任何操作的情况下不知不觉地将程序装好。虽说这种方式看上去不打搅用户,但是却存在着一个问题,因为Android系统会在安装界面当中把程序所声明的权限展示给用户看,用户来评估一下这些权限然后决定是否要安装该程序,但如果使用了静默安装的方式,也就没有地方让用户看权限了,相当于用户被动接受了这些权限。在Android官方看来,这显示是一种非常危险的行为,因此静默安装这一行为系统是不会开放给开发者的。


    但是总是弹出一个安装对话框确实是一种体验比较差的行为,这一点Google自己也意识到了,因此Android系统对自家的Google Play商店开放了静默安装权限,也就是说所有从Google Play上下载的应用都可以不用弹出安装对话框了。这一点充分说明了拥有权限的重要性,自家的系统想怎么改就怎么改。借鉴Google的做法,很多国内的手机厂商也采用了类似的处理方式,比如说小米手机在小米商店中下载应用也是不需要弹出安装对话框的,因为小米可以在MIUI中对Android系统进行各种定制。因此,如果我们只是做一个普通的应用,其实不太需要考虑静默安装这个功能,因为我们只需要将应用上架到相应的商店当中,就会自动拥有静默安装的功能。


    但是如果我们想要做的也是一个类似于商店的平台呢?比如说像360手机助手,它广泛安装于各种各样的手机上,但都是作为一个普通的应用存在的,而没有Google或小米这样的特殊权限,那360手机助手应该怎样做到更好的安装体验呢?为此360手机助手提供了两种方案, 秒装(需ROOT权限)和智能安装,如下图示:




    因此,今天我们就模仿一下360手机助手的实现方式,来给大家提供一套静默安装的解决方案。


    一、秒装


    所谓的秒装其实就是需要ROOT权限的静默安装,其实静默安装的原理很简单,就是调用Android系统的pm install命令就可以了,但关键的问题就在于,pm命令系统是不授予我们权限调用的,因此只能在拥有ROOT权限的手机上去申请权限才行。


    下面我们开始动手,新建一个InstallTest项目,然后创建一个SilentInstall类作为静默安装功能的实现类,代码如下所示:

    /**
     * 静默安装的实现类,调用install()方法执行具体的静默安装逻辑。
     * 原文地址:http://blog.csdn.net/guolin_blog/article/details/47803149
     * @author guolin
     * @since 2015/12/7
     */
    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;
        }
    
    }

    可以看到,SilentInstall类中只有一个install()方法,所有静默安装的逻辑都在这个方法中了,那么我们具体来看一下这个方法。首先在第21行调用了Runtime.getRuntime().exec("su")方法,在这里先申请ROOT权限,不然的话后面的操作都将失败。然后在第24行开始组装静默安装命令,命令的格式就是pm install -r <apk路径>,-r参数表示如果要安装的apk已经存在了就覆盖安装的意思,apk路径是作为方法参数传入的。接下来的几行就是执行上述命令的过程,注意安装这个过程是同步的,因此我们在下面调用了process.waitFor()方法,即安装要多久,我们就要在这里等多久。等待结束之后说明安装过程结束了,接下来我们要去读取安装的结果并进行解析,解析的逻辑也很简单,如果安装结果中包含Failure字样就说明安装失败,反之则说明安装成功。


    整个方法还是非常简单易懂的,下面我们就来搭建调用这个方法的环境。修改activity_main.xml中的代码,如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.installtest.MainActivity">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="onChooseApkFile"
                android:text="选择安装包" />
    
            <TextView
                android:id="@+id/apkPathText"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_gravity="center_vertical"
                />
    
        </LinearLayout>
    
    
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@android:color/darker_gray" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onSilentInstall"
            android:text="秒装" />
    
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@android:color/darker_gray" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onForwardToAccessibility"
            android:text="开启智能安装服务" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onSmartInstall"
            android:text="智能安装" />
    </LinearLayout>

    这里我们先将程序的主界面确定好,主界面上拥有四个按钮,第一个按钮用于选择apk文件的,第二个按钮用于开始秒装,第三个按钮用于开启智能安装服务,第四个按钮用于开始智能安装,这里我们暂时只能用到前两个按钮。那么调用SilentInstall的install()方法需要传入apk路

    径,因此我们需要先把文件选择器的功能实现好,新建activity_file_explorer.xml和list_item.xml作为文件选择器的布局文件,代码分别如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ListView
            android:id="@+id/list_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
             />
    
    </LinearLayout>
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="4dp"
        android:orientation="horizontal">
    
        <ImageView android:id="@+id/img"
            android:layout_width="32dp"
            android:layout_margin="4dp"
            android:layout_gravity="center_vertical"
            android:layout_height="32dp"/>
    
    
        <TextView android:id="@+id/name"
            android:textSize="18sp"
            android:textStyle="bold"
            android:layout_width="match_parent"
            android:gravity="center_vertical"
            android:layout_height="50dp"/>
    
    </LinearLayout>
    然后新建FileExplorerActivity作为文件选择器的Activity,代码如下:
    public class FileExplorerActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
    
        ListView listView;
        SimpleAdapter adapter;
        String rootPath = Environment.getExternalStorageDirectory().getPath();
        String currentPath = rootPath;
        List<Map<String, Object>> list = new ArrayList<>();
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_file_explorer);
            listView = (ListView) findViewById(R.id.list_view);
            adapter = new SimpleAdapter(this, list, R.layout.list_item,
                    new String[]{"name", "img"}, new int[]{R.id.name, R.id.img});
            listView.setAdapter(adapter);
            listView.setOnItemClickListener(this);
            refreshListItems(currentPath);
        }
    
        private void refreshListItems(String path) {
            setTitle(path);
            File[] files = new File(path).listFiles();
            list.clear();
            if (files != null) {
                for (File file : files) {
                    Map<String, Object> map = new HashMap<>();
                    if (file.isDirectory()) {
                        map.put("img", R.drawable.directory);
                    } else {
                        map.put("img", R.drawable.file_doc);
                    }
                    map.put("name", file.getName());
                    map.put("currentPath", file.getPath());
                    list.add(map);
                }
            }
            adapter.notifyDataSetChanged();
        }
    
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            currentPath = (String) list.get(position).get("currentPath");
            File file = new File(currentPath);
            if (file.isDirectory())
                refreshListItems(currentPath);
            else {
                Intent intent = new Intent();
                intent.putExtra("apk_path", file.getPath());
                setResult(RESULT_OK, intent);
                finish();
            }
    
        }
    
        @Override
        public void onBackPressed() {
            if (rootPath.equals(currentPath)) {
                super.onBackPressed();
            } else {
                File file = new File(currentPath);
                currentPath = file.getParentFile().getPath();
                refreshListItems(currentPath);
            }
        }
    }

    这部分代码由于和我们本篇文件的主旨没什么关系,主要是为了方便demo展示的,因此我就不进行讲解了。


    接下来修改MainActivity中的代码,如下所示:

    /**
     * 仿360手机助手秒装和智能安装功能的主Activity。
     * 原文地址:http://blog.csdn.net/guolin_blog/article/details/47803149
     * @author guolin
     * @since 2015/12/7
     */
    public class MainActivity extends AppCompatActivity {
    
        TextView apkPathText;
    
        String apkPath;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            apkPathText = (TextView) findViewById(R.id.apkPathText);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == 0 && resultCode == RESULT_OK) {
                apkPath = data.getStringExtra("apk_path");
                apkPathText.setText(apkPath);
            }
        }
    
        public void onChooseApkFile(View view) {
            Intent intent = new Intent(this, FileExplorerActivity.class);
            startActivityForResult(intent, 0);
        }
    
        public void onSilentInstall(View view) {
            if (!isRoot()) {
                Toast.makeText(this, "没有ROOT权限,不能使用秒装", Toast.LENGTH_SHORT).show();
                return;
            }
            if (TextUtils.isEmpty(apkPath)) {
                Toast.makeText(this, "请选择安装包!", Toast.LENGTH_SHORT).show();
                return;
            }
            final Button button = (Button) view;
            button.setText("安装中");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SilentInstall installHelper = new SilentInstall();
                    final boolean result = installHelper.install(apkPath);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (result) {
                                Toast.makeText(MainActivity.this, "安装成功!", Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(MainActivity.this, "安装失败!", Toast.LENGTH_SHORT).show();
                            }
                            button.setText("秒装");
                        }
                    });
    
                }
            }).start();
    
        }
    
        public void onForwardToAccessibility(View view) {
    
        }
    
        public void onSmartInstall(View view) {
    
        }
    
        /**
         * 判断手机是否拥有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;
        }
    
    }

    可以看到,在MainActivity中,我们对四个按钮点击事件的回调方法都进行了定义,当点击选择安装包按钮时就会调用onChooseApkFile()方法,当点击秒装按钮时就会调用onSilentInstall()方法。在onChooseApkFile()方法方法中,我们通过Intent打开了FileExplorerActivity,然后在onActivityResult()方法当中读取选择的apk文件路径。在onSilentInstall()方法当中,先判断设备是否ROOT,如果没有ROOT就直接return,然后判断安装包是否已选择,如果没有也直接return。接下来我们开启了一个线程来调用SilentInstall.install()方法,因为安装过程会比较耗时,如果不开线程的话主线程就会被卡住,不管安装成功还是失败,最后都会使用Toast来进行提示。


    代码就这么多,最后我们来配置一下AndroidManifest.xml文件:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.installtest">
    
        <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>
    
            <activity android:name=".FileExplorerActivity"/>
        </application>
    
    </manifest>

    并没有什么特殊的地方,由于选择apk文件需要读取SD卡,因此在AndroidManifest.xml文件中要记得声明读SD卡权限。


    另外还有一点需要注意,在Android 6.0系统中,读写SD卡权限被列为了危险权限,因此如果将程序的targetSdkVersion指定成了23则需要做专门的6.0适配,这里简单起见,我把targetSdkVersion指定成了22,因为6.0的适配工作也不在文章的讲解范围之内。


    现在运行程序,就可以来试一试秒装功能了,切记手机一定要ROOT,效果如下图所示:




    可以看到,这里我们选择的网易新闻安装包已成功安装到手机上了,并且没有弹出系统的安装界面,由此证明秒装功能已经成功实现了。


    二、智能安装


    那么对于ROOT过的手机,秒装功能确实可以避免弹出系统安装界面,在不影响用户操作的情况下实现静默安装,但是对于绝大部分没有ROOT的手机,这个功能是不可用的。那么我们应该怎么办呢?为此360手机助手提供了一种折中方案,就是借助Android提供的无障碍服务来实现智能安装。所谓的智能安装其实并不是真正意义上的静默安装,因为它还是要弹出系统安装界面的,只不过可以在安装界面当中释放用户的操作,由智能安装功能来模拟用户点击,安装完成之后自动关闭界面。这个功能是需要用户手动开启的,并且只支持Android 4.1之后的手机,如下图所示:




    好的,那么接下来我们就模仿一下360手机助手,来实现类似的智能安装功能。


    智能安装功能的实现原理要借助Android提供的无障碍服务,关于无障碍服务的详细讲解可参考官方文档:http://developer.android.com/guide/topics/ui/accessibility/services.html


    首先在res/xml目录下新建一个accessibility_service_config.xml文件,代码如下所示:

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

    其中,packageNames指定我们要监听哪个应用程序下的窗口活动,这里写com.android.packageinstaller表示监听Android系统的安装界面。description指定在无障碍服务当中显示给用户看的说明信息,上图中360手机助手的一大段内容就是在这里指定的。accessibilityEventTypes指定我们在监听窗口中可以模拟哪些事件,这里写typeAllMask表示所有的事件都能模拟。accessibilityFlags可以指定无障碍服务的一些附加参数,这里我们传默认值flagDefault就行。accessibilityFeedbackType指定无障碍服务的反馈方式,实际上无障碍服务这个功能是Android提供给一些残疾人士使用的,比如说盲人不方便使用手机,就可以借助无障碍服务配合语音反馈来操作手机,而我们其实是不需要反馈的,因此随便传一个值就可以,这里传入feedbackGeneric。最后canRetrieveWindowContent指定是否允许我们的程序读取窗口中的节点和内容,必须写true。


    记得在string.xml文件中写一下description中指定的内容,如下所示:

    <resources>
        <string name="app_name">InstallTest</string>
        <string name="accessibility_service_description">智能安装服务,无需用户的任何操作就可以自动安装程序。</string>
    </resources>
    
    接下来修改AndroidManifest.xml文件,在里面配置无障碍服务:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.installtest">
    
        <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">
            ......
    
            <service
                android:name=".MyAccessibilityService"
                android:label="我的智能安装"
                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>
    

    这部分配置的内容多数是固定的,必须要声明一个android.permission.BIND_ACCESSIBILITY_SERVICE的权限,且必须要有一个值为android.accessibilityservice.AccessibilityService的action,然后我们通过<meta-data>将刚才创建的配置文件指定进去。


    接下来就是要去实现智能安装功能的具体逻辑了,创建一个MyAccessibilityService类并继承自AccessibilityService,代码如下所示:

    /**
     * 智能安装功能的实现类。
     * 原文地址:http://blog.csdn.net/guolin_blog/article/details/47803149
     * @author guolin
     * @since 2015/12/7
     */
    public class MyAccessibilityService extends AccessibilityService {
    
        Map<Integer, Boolean> handledMap = new HashMap<>();
    
        public MyAccessibilityService() {
        }
    
        @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 (handledMap.get(event.getWindowId()) == null) {
                        boolean handled = iterateNodesAndHandle(nodeInfo);
                        if (handled) {
                            handledMap.put(event.getWindowId(), true);
                        }
                    }
                }
            }
        }
    
        private boolean iterateNodesAndHandle(AccessibilityNodeInfo nodeInfo) {
            if (nodeInfo != null) {
                int childCount = nodeInfo.getChildCount();
                if ("android.widget.Button".equals(nodeInfo.getClassName())) {
                    String nodeContent = nodeInfo.getText().toString();
                    Log.d("TAG", "content is " + nodeContent);
                    if ("安装".equals(nodeContent)
                            || "完成".equals(nodeContent)
                            || "确定".equals(nodeContent)) {
                        nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                        return true;
                    }
                } 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;
        }
    
        @Override
        public void onInterrupt() {
        }
    
    }
    
    代码并不复杂,我们来解析一下。每当窗口有活动时,就会有消息回调到onAccessibilityEvent()方法中,因此所有的逻辑都是从这里开始的。首先我们可以通过传入的AccessibilityEvent参数来获取当前事件的类型,事件的种类非常多,但是我们只需要监听TYPE_WINDOW_CONTENT_CHANGED和TYPE_WINDOW_STATE_CHANGED这两种事件就可以了,因为在整个安装过程中,这两个事件必定有一个会被触发。当然也有两个同时都被触发的可能,那么为了防止二次处理的情况,这里我们使用了一个Map来过滤掉重复事件。


    接下来就是调用iterateNodesAndHandle()方法来去解析当前界面的节点了,这里我们通过递归的方式将安装界面中所有的子节点全部进行遍历,当发现按钮节点的时候就进行判断,按钮上的文字是不是“安装”、“完成”、“确定”这几种类型,如果是的话就模拟一下点击事件,这样也就相当于帮用户自动操作了这些按钮。另外从Android 4.4系统开始,用户需要将应用申请的所有权限看完才可以点击安装,因此如果我们在节点中发现了ScrollView,那就模拟一下滑动事件,将界面滑动到最底部,这样安装按钮就可以点击了。


    最后,回到MainActivity中,来增加对智能安装功能的调用,如下所示:

    /**
     * 仿360手机助手秒装和智能安装功能的主Activity。
     * 原文地址:http://blog.csdn.net/guolin_blog/article/details/47803149
     * @author guolin
     * @since 2015/12/7
     */
    public class MainActivity extends AppCompatActivity {
    
        ......
    
        public void onForwardToAccessibility(View view) {
            Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
            startActivity(intent);
        }
    
        public void onSmartInstall(View view) {
            if (TextUtils.isEmpty(apkPath)) {
                Toast.makeText(this, "请选择安装包!", Toast.LENGTH_SHORT).show();
                return;
            }
            Uri uri = Uri.fromFile(new File(apkPath));
            Intent localIntent = new Intent(Intent.ACTION_VIEW);
            localIntent.setDataAndType(uri, "application/vnd.android.package-archive");
            startActivity(localIntent);
        }
    
    }

    当点击了开启智能安装服务按钮时,我们通过Intent跳转到系统的无障碍服务界面,在这里启动智能安装服务。当点击了智能安装按钮时,我们通过Intent跳转到系统的安装界面,之后所有的安装操作都会自动完成了。


    现在可以重新运行一下程序,效果如下图所示:




    可以看到,当打开网易新闻的安装界面之后,我们不需要进行任何的手动操作,界面的滑动、安装按钮、完成按钮的点击都是自动完成的,最终会自动回到手机原来的界面状态,这就是仿照360手机助手实现的智能安装功能。


    好的,本篇文章的所有内容就到这里了,虽说不能说完全实现静默安装,但是我们已经在权限允许的范围内尽可能地去完成了,并且360手机助手也只能实现到这一步而已,那些被产品经理逼着去实现静默安装的程序员们也有理由交差了吧?


    源码下载,请点击这里


    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • 因为目前多数手机自带的电脑连接套件都不能直接安装apk程序到手机中,所以手机乐园官方为广大的Android手机用户开发了一款小巧简单的apk软件安装助手,只要您在电脑上安装好了手机驱动,使用手机乐园APK安装助手可以...
  • 叉叉开发助手Android

    2020-12-14 10:11:39
    叉叉开发助手(Android版)与叉叉集成开发环境配套使用,配合叉叉脚本特有的函数命令,可以实现机器上找图、找色、触摸等高级功能 使用方法: 1.安装打开雷电模拟器并依次点击:设置->网络设置->桥接开启->安装驱动->...
  • Android远程桌面助手的主要功能如下: 0.免ROOT,支持Android4.4~Android 10.0 1.远程显示Android设备的界面并控制Android 2.截屏并保存成png图片,录制Android视频 3.复制文本到Android,PC端快速输入中文...
  • Android逆向助手是一款针对安卓平台的强大逆向辅助软件,功能涵盖apk反编译打包签名;dex/jar互转替换提取修复;so反编译;xml、txt加密;字符串编码等。支持直接将文件拖放到源和目标文件,不用每次都点浏览选择。...
  • ARDC安卓投屏助手

    2019-01-11 13:27:41
    ARDC(B1385)安卓投屏助手,可同步显示手机端APP内容,并进行APP各种操作,功能很丰富
  • #DNSCrypt安装程序 在android设备上安装dnscrypt的助手。 #建造 $ ./depending_repos.sh $ ./gradlew build 许可证:GNU GPLv3 版权所有(c)2015宅男
  • Android 逆向助手是一款针对安卓平台的强大逆向辅助软件,功能涵盖apk反编译打包签名;dex/jar互转替换提取修复;so反编译;xml、txt加密;字符串编码等。支持直接将文件拖放到源和目标文件这,不用每次都点浏览选择...
  • 用于安卓电视盒子adb连接。可以给电视盒子安装软件,可以直接推送文件到电视盒子里,还有可以目录浏览功能,或者删除没用的系统软件等等。
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼当Android固件版本大于等于2.2时,应用的安装位置是有三种不同的选择的,分别为默认位置、手机存储中以及SD卡中,手机助手可以根据用户的选择将应用安装到相应的位置。...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

    当Android固件版本大于等于2.2时,应用的安装位置是有三种不同的选择的,分别为默认位置、手机存储中以及SD卡中,手机助手可以根据用户的选择将应用安装到相应的位置。

    但是由于Android本身和应用开发者的限制,手机助手还是建议用户谨慎考虑应用安装位置的选择,以避免造成一些不必要的错误和失败。

    一、默认位置:

    选择默认位置,手机助手会根据apk应用安装包中规定的位置进行安装。

    二、手机存储:

    选择安装到手机存储中,手机助手会将应用安装到手机的ROM中,它的优势在于无论SD卡是否挂载在手机上,该应用都是可以正常工作的,并且如果应用设为开机启动项的话,手机开机时这些应用都会加载正常,但是缺点和风险在于,如果安装过多应用到手机存储中的话,会导致手机存储不足,不只无法安装其他应用到手机存储中,也会影响到其他一些应用正常工作(读写数据的缓存空间不足)。

    三、SD卡:

    选择安装到SD卡中,手机助手会将应用安装到手机的SD卡上,它的优势在于在安装一些诸如游戏之类的容量比较大的应用时,如果安装到SD卡中,可以节省手机存储空间,手机助手也推荐将一些大容量应用安装到SD卡中;但是安装应用到SD卡同样存在缺点和风险。

    根据Android官方说明(http://developer.android.com/guide/appendix/install-location.html),对于一些应用(例如带有后台服务的应用、输入法、动态壁纸、桌面小控件程序等)在安装到SD卡后,当用户把手机以大容量存储的形式连接至电脑时,SD卡会从手机中卸载掉并挂载到电脑上,这样这些安装到SD卡的应用将暂时无法在手机上使用,直到用户取消大容量存储的形式连接电脑或拔掉数据线,SD卡重新挂载到手机上时,这些应用才有可能恢复使用,一些应用、桌面小控件等即使SD卡重新挂载到手机上一样无法使用,需要重新启动手机或将小控件重新添加到桌面才可能恢复正常。还有一些应用例如设置为开机启动项的应用需要在开机的时候很快加载,但是android手机在启动完毕后才会挂载SD卡,如果被设为开机启动项的应用或桌面小控件安装在SD卡中的话,那么当需要启动它的时候SD卡很有可能还没有加载,导致该应用或小控件启动失效。

    所以请用户谨慎选择应用的安装位置,以达到最好的体验和效果。

    展开全文
  • android逆向助手v2.2

    2018-11-19 10:06:16
    android逆向助手v2.2,需要就下载,需要安装jdk,具体jdk配置自行百度
  • 本项目是一个Android静默安装实现项目源码,仿360手机助手、百度助手、豌豆荚、等应用助手类秒装和智能安装功能的功能,所谓的秒装其实就是需要ROOT权限的静默安装,其实静默安装的原理很简单,就是调用Android系统...
  • 自己开发的手机助手软件,实现了完整功能,完全实现了市面上手机助手的功能,具备手机自动识别,驱动安装,以及获取手机各种信息,传输数据等功能。 由于网站目前没有维护了,所以PC 端内嵌的网页已经不能使用了。
  • Android 手机助手自动识别

    热门讨论 2013-03-18 22:06:13
    前几天的版本有问题,安装驱动和备份联系人有问题,这个版本重新整理了一下,以及使用了最新的adb,会稳定很多。
  • 批量安装APK,我想还是比较简单的,借助android助手,很容易做到这一点(个人不喜各类助手连接Android时强制安装助手软件);通过adb命令执行多条安装命令也可以直接搞定。电子城里面一般都是借助“安装盒子”进行...
  • Android助手

    2021-06-07 09:51:19
    18大功能助您轻松,高效的管理您的Android手机这个工具软件可以帮助你终止进程,释放内存,加快手机运行速度,降低功耗,缓存清理,以帮助您的手机更高效,稳定的工作.18大功能:1监控状态(cpu,内存,电池:android助手提供...

    18大功能助您轻松,高效的管理您的Android手机

    这个工具软件可以帮助你终止进程,释放内存,加快手机运行速度,降低功耗,缓存清理,以帮助您的手机更高效,稳定的工作.

    18大功能:

    1 监控状态(cpu, 内存, 电池:android助手提供实时的CPU,内存和电池状态,可以帮助您及时监测系统的性能.

    2 进程管理:可以区分出不同类别的进程, 避免误杀,快速优化和自动优化可以智能的关闭无用进程,忽略列表可以进行个性化设置.

    3 缓存清理

    4 系统清理:浏览器历史记录,剪贴板,市场历史,Gmail历史记录,谷歌地球历史,谷歌地图历史.

    5 省电设置:通过关闭蓝牙, wifi, gps, 自动同步, 自动旋转屏幕, 触感和设置屏幕亮度, 屏幕超时进行省电.

    6 文件管理器

    7 开机后优化

    8 批量卸载

    9 耗电情况

    10 开机时间

    11 开关机静音

    12 音量设置

    13 情景模式设置

    14 系统信息

    15 窗口小部件

    16 批量安装

    17 移至SD卡(支持android2.2以后的版本)

    18 应用程序备份还原

    【基本信息】作者:Aaron

    更新时间:2019-05-18

    版本:23.53

    系统:Android 以上

    语言:中文

    【更新内容】- 优化系统清理。

    – 修复部分手机强制关闭问题。

    – 修复 android5.1.1内核手机问题。

    展开全文
  • Android安装

    千次阅读 2020-02-05 11:32:07
    01.Unity中的Android Build Support下载 ...或在Unity官网下载对应版本的Unity安装助手自行追加安装 02.JDK下载(请勿使用JDK9,JDK8u152,JDK8u151任选,x64版本出现签名错误的话可以尝试x86版本) http:...

    01.Unity中的Android Build Support下载
    在Unity中的File>Building Settings>Android>Open Download Page
    或在Unity官网下载对应版本的Unity安装助手自行追加安装
    02.JDK下载(请勿使用JDK9,JDK8u152,JDK8u151任选,x64版本出现签名错误的话可以尝试x86版本)
    http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
    03.Android Studio下载(能打开哪个用哪个)
    https://developer.android.com/
    https://developer.android.google.cn/index.html
    http://www.androiddevtools.cn/
    04.
    安装jdk jre 不是同一目录
    在这里插入图片描述
    05.在这里插入图片描述
    07.在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    安装JDK与JRE,目录随意,不是同一个且记住就行。

    安装完成后,此电脑(Win7叫计算机),右键,属性,高级系统选项,环境变量

    系统变量,新建,JAVA_HOME变量
    变量值选择或填写JDK的安装目录

    系统变量,找到Path变量(已经存在的),编辑
    在变量值最后输入JDK安装目录下的bin目录(可以直接输入也可以写成%JAVA_HOME%\bin)与JRE安装目录下的bin目录
    注意:原Path变量最后若已经有分号则不用加,否则先加一个分号再输入

    系统变量,新建,CLASSPATH变量
    变量值填写(可直接复制下一行内容)
    .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar

    运行cmd 输入 java -version与javac -version
    java或javac和 -version 之间有空格
    若显示版本信息 则说明安装和配置成功
    在这里插入图片描述
    09.安装 android studio
    在这里插入图片描述
    10
    Unity中设置AndroidSDK与JDK的目录
    下载
    https://services.gradle.org/distributions/gradle-5.4.1-all.zip
    安装
    C:\Users\Administrator.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx
    11.
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    12.发布APP
    在这里插入图片描述
    gradle发布APP创建自己的密钥库用于签名
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    13
    文件 tang.store
    密匙 123456

    展开全文
  • 手机安卓自带软件可以覆盖安装吗1、可能手机里面,软件残留的东西太多了,建议先用360手机卫士之类的管理软件清理一下。2、之前安装过同类的软件,但是出现过问题,导致安装发生问题。3、安装包下载的不完全或者有...
  • Android远程桌面助手

    2021-06-02 20:18:02
    ARDC也叫做Android远程桌面助手,是一款安卓远程控制软件,它可以通过wifi或者是USB数据线连接到你的Android设备,比如说手机、pad、电视等等,画质非常清晰,连接后,你就可以通过软件来控制所连接的Android设备,...
  • 如果用过一些手机助手的朋友都知道,手机助手下载其他软件的更新程序后会自动静默更新。APK静默安装是指实现了在APK文件安装过程中不会出现系统安装对话框。不仅可以安装新的apk,也适用于更新旧的apk。更新apk必须...
  • 玩转手机 Android手机助手是一款免费的、简单易用的在电脑上管理Android手机的软件。具有以下特点和功能:1. 连接方便:支持"USB数据线连接"和"Wi-Fi无线连接"两种连接方式。能自动检测并安装USB数据线驱动程序,...
  • usb调试助手.apk

    2020-09-20 14:55:20
    android手机的调试usb工 ,目前测试了的可在android8.1,android 9,android10运行。可看到usb的interface,根据usb的interface发送接收
  • 手机安卓自带软件可以覆盖安装吗1、可能手机里面,软件残留的东西太多了,建议先用360手机卫士之类的管理软件清理一下。2、之前安装过同类的软件,但是出现过问题,导致安装发生问题。3、安装包下载的不完全或者有...
  • Android代码-红包助手

    2019-08-06 07:27:17
    使用AccessibilityService功能,所以需要API Level 19(Android 4.4.2)级以上。当有微信红包消息时,自动跳转到红包界面,由于微信对于自动抢有封号措施,代码里有这个功能,只是注释了。 使用方法: 第一步,安装app...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,317
精华内容 6,126
关键字:

安卓安装助手