前言
本文只是一个总结性的文章,方便我以后使用的时候查找。我做完FTPLog上传demo之后,我就想如果直接安装在launcher中显示出来的话,那如果有心怀不轨的人一直点击上传,那我服务器不炸了?!不行,得藏起来,机器出问题的时候再告诉客户怎么上传,so直接在系统中加入一个暗门,再做一个密码输入的功能,不就OK了~话不多说,直接搞起!(基于MTK源代码实现)
添加思路
- 将demo移植到系统私有配置目录,局编通过。
- 在系统设置->关于设备的列表信息中,使用机器型号item作为暗门,连续点击8次进入FTP上传应用。
正文
移植demo到系统源码
系统中编译一个简单的工程其实不难,首先我们先在源代码中新建一个工程,简单的目录级别如下:
然后再贴上写完的demo的工程目录级别:
对比一下,除了没有Android.mk文件,其他都可以直接搬过去就ok了,对应搬的目录级别(从AS搬到系统工程目录):libs ->libs res->res src的话只留AS目录中src-main-java这个层次级别的就可以;
当然有一点要说明下,如今AS工程版本号是在build文件中,要知道我们java工程初始的时候版本号是在manifest.xml文件中的,所以在系统源码中定义版本号需定义到manifest文件中:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.topwise.compress"
android:sharedUserId="android.uid.system"
android:versionCode="1"
android:versionName="1.0.0">
刚才说了,Android.mk文件还没有呢,其实这个才是重点,系统源码的编译大部分都是需要make文件支撑的,so先贴上再讲解:
ifeq ($(strip $(UPLOAD_USDKLOG)), yes)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_STATIC_JAVA_LIBRARIES := libftp
#需要引入V4包
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
LOCAL_PACKAGE_NAME := USDKLogUpload
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libftp:libs/commons-net-3.3.jar
include $(BUILD_MULTI_PREBUILT)
endif
关于mk文件的详细讲解,后续我会出一篇详细文章供大家参考,在这里我只说下几个比较关键的定义:
//此判断是编译条件,定义了宏UPLOAD_USDKLOG=yes才可编译进去此apk
//UPLOAD_USDKLOG=yes 定义在项目的proj.cfg文件中
ifeq ($(strip $(UPLOAD_USDKLOG)), yes)
//模块编译所需版本要求 optional:指该模块在所有版本下都编译
LOCAL_MODULE_TAGS := optional
//编译代码文件
//all-subdir-java-files 指当前根目录下所有java文件都参与编译
LOCAL_SRC_FILES := $(call all-subdir-java-files)
//引入静态java库 注意别名libftp一致
LOCAL_STATIC_JAVA_LIBRARIES := libftp
//引入FTP三方支持库
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libftp:libs/commons-net-3.3.jar
include $(BUILD_MULTI_PREBUILT)
//编译生成的apk名称
LOCAL_PACKAGE_NAME := USDKLogUpload
//设置签名方式 platform:系统签名,即编译生成apk为系统apk
LOCAL_CERTIFICATE := platform
其中LOCAL_CERTIFICATE这个字段我为什么要设置为系统apk呢?主要是想免去动态申请权限带来的不便,因为本身这个应用也没有多大,所以放到系统应用池中是ok的(system/app目录是有存储大小限制的,没有特殊需求此字段可不填,默认为普通应用)。
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/../../../../prebuilts/sdk/current/support/v7/appcompat/res
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
--extra-packages android.support.v7.appcompat
好了,第一阶段基本完成,到这局部编译就可以通过了!
设置暗门入口
首先我们找到设置中关于设备里处理点击事件的类–packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java,处理点击事件的部分代码如下(方法内有进入开发者模式的相关代码,这里只贴了我写的一部分):
@Override
public boolean onPreferenceTreeClick(Preference preference) {
/.......
.......
.......
/
if (preference.getKey().equals(KEY_DEVICE_MODEL)) {
if (mModelHitCountdown-- == 0) {
mModelHitCountdown = TAPS_TO_BE_A_DEVELOPER;
List<PackageInfo> packageInfos = getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
for (PackageInfo info : packageInfos) {
if (info.applicationInfo.packageName.equals("com.topwise.compress")) {
Log.i("testxk", "start activity log upload");
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName("com.topwise.compress", "com.topwise.compress.MainActivity");
startActivity(intent);
break;
}
}
}
}
}
这里onPreferenceTreeClick方法是设备信息列表中的点击事件处理方法,这个是使用Preference的布局结构中的复写方法,android中许多的UI都是使用Preference布局,咳咳,扯远了~通过preference.getKey()方法获取点击的item,这里已经把型号属性添加到preference中了,添加方法如下:
//添加显示item
setStringSummary(KEY_DEVICE_MODEL, Build.MODEL);
//添加点击使能 false为无点击事件
findPreference(KEY_DEVICE_MODEL).setEnabled(true);
这个其实在onCreate方法中已经添加好了,之后的逻辑很简单了,判断点击次数,同时判断是否已经安装了我们的demo,如果已经安装,那就跳转到我们的FTP上传日志的应用。
OK了,到这里基本上就可以编译一个带Log上传功能的OS版本了;有什么需要纠正的,欢迎大佬批评指正!!!
后记
后续会推出基础篇和实践篇两款类型文章供各位同学交流学习,感觉写写文章也能找回当年在学校奋笔疾书的ganjio啊~~