关于手机-Android版本-基带版本,连续点击六次进入工厂模式 :
首先这个preference是在vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java
继承的是BasePreferenceController 这个是在MtkSettings里的文件,有些是继承AbstractPreferenceController,这个是frameworks下的,但都差不多的,里面有个关于preference点击事件的方法handlePreferenceTreeClick,这个就是返回true就是已经处理过了
记得导包
import android.util.Log;
import android.content.Intent;
import android.text.TextUtils;
import android.widget.Toast;
import androidx.preference.Preference;
import android.os.SystemClock;
所需的全局变量
private Toast mDevHitToast = null;
private int count = 6;
final static int COUNTS = 6;
final static long DURATION_All = 2000;
final static long DURATION_EVERY = 350;
long[] mHits = new long[COUNTS];
关键是重载复写这个方法
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
android.util.Log.i("yantao","base version Click");
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return false;
}
onClickToFactory();
return true;
主要是我写的这个方法
public void onClickToFactory(){
System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1);
mHits[mHits.length - 1] = SystemClock.uptimeMillis();
if (count > 1) {
if (mDevHitToast != null) {
mDevHitToast.cancel();
}
mDevHitToast = Toast.makeText(mContext,
mContext.getResources().getQuantityString(
R.plurals.show_remain_count, count - 1,count - 1),
Toast.LENGTH_SHORT);
mDevHitToast.show();
if (mHits[mHits.length - 2] >= (SystemClock.uptimeMillis() - DURATION_EVERY)) {
count--;
if (mDevHitToast != null) {
mDevHitToast.cancel();
}
mDevHitToast = Toast.makeText(mContext,
mContext.getResources().getQuantityString(
R.plurals.show_remain_count, count,count),
Toast.LENGTH_SHORT);
mDevHitToast.show();
Log.i("yantao", "count=" + count);
return;
}
}
if (mHits[0] >= (SystemClock.uptimeMillis() - DURATION_All)) {
count = 6;
mHits = new long[COUNTS];
mDevHitToast.cancel();
Intent intent = new Intent();
intent.setClassName("com.freeme.factory", "com.freeme.factory.FactoryTest");
mContext.startActivity(intent);
}
else {
count = 6;
}
}
里面的toast是参照默认版本号点五次进入开发者模式的toast,BuildNumberPreferenceController
里面的字符串也参照版本号的稍微改下vendor/mediatek/proprietary/packages/apps/MtkSettings/res/values-zh-rCN/strings.xml
vendor/mediatek/proprietary/packages/apps/MtkSettings/res/values/strings.xml
<plurals name="show_remain_count">
<item quantity="one">You are now <xliff:g id="step_count">%1$d</xliff:g> step away from entering FactoryTest .</item>
<item quantity="other">You are now <xliff:g id="step_count">%1$d</xliff:g> step away from entering FactoryTest .</item>
</plurals>
中文里面提醒用户是连续点击五次,注意这个overlay需要写全resource,因为是动态字符串,<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">,
里面关键的toast调用字符串的mContext.getResources().getQuantityString(
R.plurals.show_remain_count, count,count),,这个getQuantityString,和xml里的plurals标签是相辅相成的,根据数字的不同自动选择不同的字符串显示,特别是单复数。特别是不同国家的语言对应不同的单复数。One是单数,other是复数。
在使用getQuantityString()方法时,如果字符串包含数字格式化串,则需要传递2个deleteCount参数。例如:对于字符串“%d sélectionné”,第一个deleteCount参数选择合适的复数字符串,第二个count参数插入占位符%d中。如果复数字符串资源不包含格式化信息,就不需要给getQuantityString()传递第三个参数(我们这个字符串包含了,所以需要加)
意思就是如果other后面没有规定字符串,那么默认没有复数,那么就可以不传第三个参数。
System.arraycopy方法里面四个参数,
数组1:int[] arr = { 1, 2, 3, 4, 5 };
数组2:int[] arr2 = { 5, 6,7, 8, 9 };
运行:System.arraycopy(arr, 1, arr2, 0, 3);
得到:
int[] arr2 = { 2, 3, 4, 8, 9 };
过程分析:
先看第1、2、5个参数,得出要从arr中从下标为1的数组中拿出三个数值:2,3,4
然后看第3、4个参数,知道要在arr2中从下标为0开始放入数据,放入的个数也是第五个参加决定的这里是3个
所有最后的结果就是:2,3,4(加入的) + 8,9(原来的)
System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1);就是mHits这个array数组的1下标的元素开始拿出mHits.length – 1个元素,copy覆盖到mHits的0下标开始
这里执行六次大概可以是 ,每一次传入相应的数字,
//0,0,0,0,0,1 // 0,0,0,0,1,2 //0,0,0,1,2,3 //0.0.1.2.3.4 //0.1.2.3.4.5 //1.2.3.4.5.6
最后的mHits[0]只有在最后一次才有值,而这个值就是刚开始那一下传入的值
res/xml/my_device_info.xml,是关于手机点进去之后的,虽然也有基带版本,但是这个不显示的,
真正的xml文件是这个res/xml/firmware_version.xml
找到这个preference ,
android:key="base_band"
android:title="@string/baseband_version"
preference有个属性settings:enableCopying="true" 可复制,还有个属性android:selectable="false",这个就是不可选择,就是无法点击,把这句删了,就可以进行点击操作了。
1、System.currentTimeMillis()获取的是系统的时间,可以使用SystemClock.setCurrentTimeMillis(long millis)进行设置。如果使用System.currentTimeMillis()来获取当前时间进行计时,应该考虑监听ACTION_TIME_TICK, ACTION_TIME_CHANGED 和 ACTION_TIMEZONE_CHANGED这些广播ACTION,如果系统时间发生了改变,可以通过监听广播来获取。
2、SystemClock.uptimeMillis()表示系统开机到当前的时间总数,单位是毫秒,但是,当系统进入深度睡眠(CPU休眠、屏幕休眠、设备等待外部输入)时间就会停止,但是不会受到时钟缩放、空闲或者其他节能机制的影响。所以两次时间之差就是相隔时间,比如1000就是1秒
自定义版本动态隐藏某应用:
点五次的逻辑如上,自定义版本在
./src/com/mediatek/settings/deviceinfo/CustomizeBuildVersionPreferenceController.java
动态消除
//下面的是执行和逻辑和所需的对象,放到对应的位置就行
PackageManager packageManager = mContext.getPackageManager();
if (enableState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
enableState =PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
} else {
enableState =PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
}
packageManager.setComponentEnabledSetting(componentName,enableState,0);
private int enableState;
componentName=new ComponentName("com.android.dialer","com.android.dialer.main.impl.MainActivity");
整合一个方法
public void checkThenToast(int count){
if(count > 1){
if(enableState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED){
mDevHitToast = Toast.makeText(mContext,
mContext.getResources().getQuantityString(
R.plurals.remains_disable, count-1,count-1),
Toast.LENGTH_SHORT);
mDevHitToast.show();
}else {
mDevHitToast = Toast.makeText(mContext,
mContext.getResources().getQuantityString(
R.plurals.remains_show, count-1,count-1),
Toast.LENGTH_SHORT);
mDevHitToast.show();
}
}
}
谷歌商店 play store的对应的activity机器上看不到,因为进去是登录界面
包名是这个com.android.vending","com.android.vending.AssetBrowserActivity