博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 高仿豌豆荚 一键安装app 功能 实现
阅读量:7020 次
发布时间:2019-06-28

本文共 7368 字,大约阅读时间需要 24 分钟。

以往我们那些应用市场 帮我们安装app的时候  我们都得点确定,当然你如果 root 以后 不用点确定 也能自动安装了,后来豌豆荚 推出了一个功能 非root的手机也能不点确定 直接帮你安装好。(如果不理解我这段话意思的同学 赶紧试用豌豆荚就知道了)

实际上 这个功能还是蛮重要的,比如我们的app 如果需要强制升级 什么的,用户下载好 你启动installer 然后还要用户点确定才能安装,你看这就是用户体验不好吗 对吧,学会这个可以帮我们做很多事。

当然了 首先要感谢豌豆荚团队 在csdn做的采访,这是这篇文章的基础 http://www.csdn.net/article/1970-01-01/2824737 他透露了这个功能点的point。

好废话不多说 我们直接上代码吧,因为这个功能所涉及到的api 比较小众,我就不过多介绍了,有需要的同学可以参考 官方文档的这个training http://developer.android.com/intl/zh-cn/training/accessibility/service.html

我着重提一下,千万不要用这种方式去实现 流氓软件的流氓功能,作为android 开发,一个好的生态圈是要我们自己去维护的,不要学 百度 那种流氓apk!

首先 我们来定义一个特殊的服务:

1 package com.example.administrator.powertest; 2  3 import android.accessibilityservice.AccessibilityService; 4 import android.view.accessibility.AccessibilityEvent; 5 import android.view.accessibility.AccessibilityNodeInfo; 6  7 import java.util.List; 8  9 /**10  * 这个服务是不需要你在activity里去开启的,属于系统级别辅助服务 需要在设置里去手动开启 和我们平常app里11  * 经常使用的service 是有很大不同的 非常特殊12  * 你可以在 \sdk\samples\android-23\legacy\ApiDemos 这样的目录下 找到这个工程 这个工程下面有一个accessibility13  * 包 里面有关于这个服务的demo 当然他们那个demo 非常复杂,但是信息量很大,有兴趣深入研究的同学可以多看demo14  * 我这里只实现最基本的功能 且没有做冗余和异常处理,只包含基础功能,不能作为实际业务上线!15  */16 public class MyAccessibilityService extends AccessibilityService {17     public MyAccessibilityService() {18     }19 20     /**21      * AccessibilityService 这个服务可以关联很多属性,这些属性 一般可以通过代码在这个方法里进行设置,22      * 我这里偷懒 把这些设置属性的流程用xml 写好 放在manifest里,如果你们要使用的时候需要区分版本号23      * 做兼容,在老的版本里是无法通过xml进行引用的 只能在这个方法里手写那些属性 一定要注意.24      * 同时你的业务如果很复杂比如需要初始化广播啊之类的工作 都可以在这个方法里写。25      */26     @Override27     protected void onServiceConnected() {28         super.onServiceConnected();29     }30 31     /**32      * 当你这个服务正常开启的时候,就可以监听事件了,当然监听什么事件,监听到什么程度 都是由给这个服务的属性来决定的,33      * 我的那些属性写在xml里了。34      */35     @Override36     public void onAccessibilityEvent(AccessibilityEvent event) {37         /**38          * 事件是分很多种的,我这里是最简单的那种,只演示核心功能,如果要做成业务上线 这里推荐一个方法可以快速理解这里的type属性。39          * 把这个type的int 值取出来 并转成16进制,然后去AccessibilityEvent 源码里find。顺便看注释 ,这样是迅速理解type类型的方法40          */41         final int eventType = event.getEventType();42         switch (eventType) {43             case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:44                 //这个地方没什么好说的 你就理解成 找到当前界面 包含有安装 这个关键词的 所有节点就可以了。返回这些节点的list45                 //注意这里的find 其实是contains的意思,比如你界面上有2个节点,一个节点内容是安装1 一个节点内容是安装2,那这2个节点是都会返回过来的46                 //除了有根据Text找节点的方法 还有根据Id找节点的方法。考虑到众多手机rom都不一样,这里需要大家多测试一下,有的rom packageInstall47                 //定制的比较深入,可能和官方rom里差的很远 这里就要做冗余处理,可以告诉大家一个小技巧 你就把这些rom的 安装器打开 然后48                 //通过ddms里 看view结构的按钮 直接进去看就行了,可以直接看到那个界面属于哪个包名,也可以看到你要捕获的那个按钮的id是什么 很方便!49                 List
list = event.getSource().findAccessibilityNodeInfosByText("安装");50 if (null!=list){51 for (AccessibilityNodeInfo info : list) {52 if (info.getText().toString().equals("安装"))53 {54 //找到你的节点以后 就直接点击他就行了55 info.performAction(AccessibilityNodeInfo.ACTION_CLICK);56 }57 }58 }59 break;60 default:61 break;62 }63 }64 @Override65 public void onInterrupt() {66 67 }68 }

服务定义好了 就要在配置文件里配置一下,看manifest的主要代码:

1 
2
7
8
9
10
13

然后我们在res路径下 新建一个xml 文件夹 并在下面 新建一个xml文件取名为taskbackconfig.xml

1 
2
17
27

到此时就差不多了,我们再把activity的代码放上来:

1 package com.example.administrator.powertest;  2   3 import android.content.BroadcastReceiver;  4 import android.content.Context;  5 import android.content.Intent;  6 import android.content.IntentFilter;  7 import android.net.Uri;  8 import android.os.Bundle;  9 import android.provider.Settings; 10 import android.support.design.widget.FloatingActionButton; 11 import android.support.design.widget.Snackbar; 12 import android.support.v4.content.LocalBroadcastManager; 13 import android.support.v7.app.AppCompatActivity; 14 import android.support.v7.widget.Toolbar; 15 import android.util.Log; 16 import android.view.View; 17 import android.view.Menu; 18 import android.view.MenuItem; 19 import android.widget.TextView; 20  21 import java.io.File; 22  23 public class MainActivity extends AppCompatActivity { 24  25     private TextView tv,installTv; 26     /** 27      * 你得引导用户去设置界面吗,你不能让用户自己去找吧。 28      */ 29     private static final Intent sSettingsIntent = 30             new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); 31     //这里就假设想要安装的apk 是扇贝网 并且在sd卡根目录下面 32     private static final String FILE_PATH="/mnt/sdcard/shanbeidanci6.0.000.apk"; 33  34  35     @Override 36     protected void onCreate(Bundle savedInstanceState) { 37         super.onCreate(savedInstanceState); 38         setContentView(R.layout.activity_main); 39         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 40         setSupportActionBar(toolbar); 41  42         FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 43         fab.setOnClickListener(new View.OnClickListener() { 44             @Override 45             public void onClick(View view) { 46                 Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 47                         .setAction("Action", null).show(); 48             } 49         }); 50  51         tv = (TextView) findViewById(R.id.tv); 52         tv.setOnClickListener(new View.OnClickListener() { 53  54             @Override 55             public void onClick(View v) { 56                 startActivity(sSettingsIntent); 57             } 58         }); 59         installTv=(TextView)this.findViewById(R.id.tv2); 60         installTv.setOnClickListener(new View.OnClickListener(){ 61  62             @Override 63             public void onClick(View v) { 64                 //调用安装器去安装我们的apk 一键安装开始啦,如果用户把那个服务打开了的话。 65                 Intent intent = new Intent(Intent.ACTION_VIEW); 66                 intent.setDataAndType(Uri.fromFile(new File(FILE_PATH)), "application/vnd.android.package-archive"); 67                 startActivity(intent); 68             } 69         }); 70     } 71  72     @Override 73     public boolean onCreateOptionsMenu(Menu menu) { 74         // Inflate the menu; this adds items to the action bar if it is present. 75         getMenuInflater().inflate(R.menu.menu_main, menu); 76         return true; 77     } 78  79     private class ResponseReceiver extends BroadcastReceiver { 80  81         public void onReceive(Context context, Intent intent) { 82  83             tv.setText(intent.getStringExtra("msg")); 84         } 85     } 86  87     @Override 88     public boolean onOptionsItemSelected(MenuItem item) { 89         // Handle action bar item clicks here. The action bar will 90         // automatically handle clicks on the Home/Up button, so long 91         // as you specify a parent activity in AndroidManifest.xml. 92         int id = item.getItemId(); 93  94         //noinspection SimplifiableIfStatement 95         if (id == R.id.action_settings) { 96             return true; 97         } 98  99         return super.onOptionsItemSelected(item);100     }101 }

到此所有代码就结束了,如果你想做的好一点 ,请自己做冗余异常处理,我这里主要演示功能就不做的那么细致了,最后看下跑起来的效果吧:

 

转载于:https://www.cnblogs.com/punkisnotdead/p/4885572.html

你可能感兴趣的文章
Java-坦克大战
查看>>
SQL语法基础之CREATE语句
查看>>
java-组合优于继承
查看>>
Linux系统小技巧(6):组合wireshark和strace
查看>>
如何按非客户区移动窗体
查看>>
截取鼠标指针的图片
查看>>
更新处理函数在对话框的菜单中不能工作
查看>>
设计模式-适配器模式
查看>>
LeetCode-90-Subset II
查看>>
表之间数据复制语句
查看>>
QT中几个函数的使用方法
查看>>
TCP/IP协议
查看>>
Django框架 连接Oracle -ServerName方式报错
查看>>
Vue指令 常见的几个内置指令
查看>>
高中数学成绩的成因分析(来自网络)
查看>>
Bestcoder#5 1003
查看>>
android中的category
查看>>
chckBox样式的修改
查看>>
计算机网络 虚拟服务器
查看>>
轮胎魔术公式(Magic Fomula)模型
查看>>