当前位置:首页 > 教程 > Android > 安卓实战-高仿豌豆荚

安卓实战-高仿豌豆荚

我们都知道豌豆荚,豌豆荚是中国 Android用户中人气、活跃度很高的“移动内容搜索”,也是中国移动互联网领域的创新企业。诞生于 2009 年 12 月的豌豆荚迄今安装量已超过 4.2 亿。豌豆荚专注于「移动内容搜索」领域的创新,并通过「应用内搜索」技术让用户搜索到千万量级的不重复应用、游戏、视频、电子书、主题、电影票、问答、旅游等内容,随时随地享受全面准确和直达行动的内容搜索消费体验。

安卓

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- label 这个就是在设置界面显示的label 应该比较好理解了-->
        <service
            android:name=".MyAccessibilityService"
            android:exported="true"
            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/taskbackconfig" />
        </service>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright (C) 2011 The Android Open Source Project
 
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
 
       http://www.apache.org/licenses/LICENSE-2.0
 
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 -->
<!--
这个就是给我们的AccessibilityService 设置属性的,当然你也可以在代码里 的 connnect函数里 手动设置。可以向下兼容。
accessibilityFeedbackType 这个属性如果不设置的话 我们那个onAccessibilityEvent 这个回调函数 根本回调不了 所以这里要注意
packageNames 这个属性 就是捕获什么app的行为的,比如我这里写的包名是packageinstaller 那就肯定只能捕获安装器的 事件了
有的rom 安装器可能不是这个包名 那你就要进行特殊设置了,此外这个属性你如果什么都不写 就意味着 你可以捕获所有手机的动作
如果你要做流氓软件的话 可以packageNames 里面什么都不写。。。甚至可以操作支付宝 给你打钱。。。如果你知道用户密码的话。
当然你如果真这么做了 相信捕获一次用户输入密码的行为 也是很容易的。。细思极恐 我就不往下深入了。。。
 
description 这个就是对你那个申请服务的时候说明了,可以写的煽情一点 让用户打开这个服务的可能性更高一点。。。
-->
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:notificationTimeout="100"
    android:packageNames="com.android.packageinstaller"
    android:accessibilityFeedbackType="feedbackSpoken"
    android:canRetrieveWindowContent="true"
    android:description="@string/hint" />

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

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

如果你是按照我的步骤一步一步来的话,相信你一定也能做出类似豌豆荚那样的效果的。

  • << 我的程序员之路
  • Android内存优化:ArrayMap >>
  • 作者:
    除非注明,本文原创:知道91,欢迎转载!转载请以链接形式注明本文地址,谢谢。
    原文链接:http://www.zhidao91.com/android-wandoujia/

    相关文章 近期热评 最新文章

    • 怎样搭建安卓开发环境图文教程—安卓Android游戏开发新手入门教程
      手把手教你使用Android开发游戏,使用Android开发首先需要的是搭建Android开发环境。本篇就讲解关于如何搭建Android开发环境的图文教程。
    • 跨平台混合式App开发
      Phonegap是一款开源的开发框架,旨在让开发者使用HTML、Javascript、CSS等Web APIs开发跨平台的移动应用程序。原本由Nitobi公司开发,现在由Adobe拥有。
    • Android内存优化:ArrayMap
      其实如果我们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成了内存泄露。
    • 安卓开发-实现软键盘搜索
      安卓是现在最火的平台了,在实际开发中,调用系统的键盘是很容易,但是有些情况下,我们需要做出软键盘,这样用户的安全度会提高一个档次。
    • 23种设计模式简明教程
      学习设计模式的方法有很多。全面深入地学习,可以选择经典设计模式书籍。或者通过简短、清晰的教程快速了解设计模式。本文整理了23个设计模式的简明教程,其中多篇以讲...
    • .NET 获取客户端的操作系统版本和浏览器版本
      本文讲解了通过.NET 获取客户端的操作系统版本和浏览器版本的方法,可以获取到最新的Windows 10、Win7、XP、IOS、Linux等主流操作系统。
    • 使用微信JDK实现微信接口签名验证
      要使用微信的接口必须在绑定的域名下测试;签名必须先向微信请求到access_token,然后用access_token再去请求jsapi_ticket,最后用jsapi_ticket和相关的参数按照ASCII码...
    • oracle数据库相关操作注意事项
      修改Oracle SGA(共享内存) 很多网站说修改Oracle的内存通过命令 如果你这么做了,那么恭喜你,你的Oracle数据库无法启动了。如果你已经这么做了,恢复Oracle启动的方...
    • oracle数据库相关操作注意事项
      修改Oracle SGA(共享内存) 很多网站说修改Oracle的内存通过命令 如果你这么做了,那么恭喜你,你的Oracle数据库无法启动了。如果你已经这么做了,恢复Oracle启动的方...
    • 使用微信JDK实现微信接口签名验证
      要使用微信的接口必须在绑定的域名下测试;签名必须先向微信请求到access_token,然后用access_token再去请求jsapi_ticket,最后用jsapi_ticket和相关的参数按照ASCII码...
    • ABP开发指南系列教程(2) – 多层架构...
      为了减少复杂性和提高代码的可重用性,采用分层架构是一种被广泛接受的技术。为了实现分层的体系结构,ABP遵循DDD(领域驱动设计)的原则,将工程分为四个层: 展现层(...
    • ABP开发指南系列教程(1) – 入...
      ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。 ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WE...
    • Windows下 JIRA + Agile + Mysql 破解...
      本文讲述了Windows下 JIRA + Agile + Mysql 破解安装示例教程
    • c#类的构造函数继承关系示例剖析
      本文通过示例代码讲解了c#子类的构造函数与父类的关系,子类怎样集成父类的构造函数的。