Android_原生设置入口问题

问题引入

某沃学习机上面,出现几次系统的动画时长缩放被设置为0,导致应用动画异常。

某沃学习机Android版本:10。

transition_animation_scale 0.5
window_animation_scale 0.5
animator_duration_scale 1.0

实际上,这个是开发者选项中才能调整的参数,而且这个设置的入口在定制版系统上屏蔽掉了,不介入第三方应用或者开发工具不会直接打开,所以可能的原因有:

  1. 通过开发工具或者第三方应用进入了开发者选项,手动调整参数。
  2. 第三方应用修改了动画时长缩放配置;

针对第一种可能:网上下载了一个Open Settings(shortcut to settings)APK。尝试在某度学习机和某沃学习机上打开,发现,某度进入了厂家定制的设置中,而某沃却轻松地进入了Android的原生设置程序中。

实际上学习机这类产品是不想把原生设置的机会让度给普通用户的,所以,某沃的学习机进不去实属没有周全考虑系统安全性。

经自己模拟开发第三方应用设置参数,排除了第三方应用直接设置的可能,见下文。

Android Settings中System/Global/Secure

https://blog.csdn.net/qq_37580586/article/details/122327215

来电铃声、锁屏时间、日期格式等等这些属性的设置通常有Settings为入口,通过SettingsProvider来进行。SettingsProvider也是所有系统设置的管理者。

在Android 5.0版本之前,SettingsProvider中系统设置是存储在settings.db数据库中;但是在Android 6.0之后,SettingsProvider中系统设置改为由xml存储在data分区。

为何要从settings.db改为xml存储?

  1. 这次修改主要涉及到global, secure, system三个表。改为了settings_global.xmlsettings_secure.xmlsettings_system.xml,对应/frameworks/base/core/java/android/provider/Settings.java中的三个内部类:Global、Secure、System。其实还有两个xml,settings_config.xmlsettings_ssaid.xml
    1. Global:所有的偏好设置对系统的所有用户公开,第三方APP只读;
    2. System:包含各种各样的用户偏好系统设置,第三方APP只读;
    3. Secure:安全性的用户偏好系统设置,第三方APP只读。
  2. 实现方式从之前的数据库,改为异步性能更加优良的xml。
  3. 这次修改主要是基于性能的考量(写入一条耗时从400ms降低为10ms),同时也能够使得保存数据的过程更加可信。
  4. 实际上,使保存数据过程更加可信这一条并不是问题的关键,写入失败的情况非常罕见,而且上层应用修改SettingsProvider设置都是通过SettingsProvider来实现的。所以当上层APP下次再次启动的时候,并不知道数据写入失败。
  5. 从db改为xml以及相应逻辑,可以有效的防止某些恶意APP监听某些设置选项,进而频繁的进行操作。
  6. 每个用户都有自己的一份SettingsProvider设置xml文档。通常位于/data/system/users/userid/
  7. 控制APP针对SettingsProvider的写入,即合法性判断
  8. 控制SettingsProvider的大小(数据量大小,占用内存大小)

其实主要原因就是因为性能、安全两个原因。

与SystemProperties对比

settings_global.xmlsettings_secure.xmlsettings_system.xml,对应/frameworks/base/core/java/android/provider/Settings.java中的三个内部类。

它们三个都继承了NameValueTable,而NameValueTable都继承了BaseColumns。查看/frameworks/base/core/java/android/provider/BaseColumns.java可以看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package android.provider;
public interface BaseColumns {
/**
* The unique ID for a row.
* <P>Type: INTEGER (long)</P>
*/
public static final String _ID = "_id";

/**
* The count of rows in a directory.
* <P>Type: INTEGER</P>
*/
public static final String _COUNT = "_count";
}

Settings中不论是Global、System还是Secure的数据都由键值对组成的。

SettingsProvider有点类似Android的properties系统(Android属性系统):SystemProperties。但是SettingsProvider和SystemProperties有以下不同点:

  1. 数据保存方式不同:SystemProperties的数据保存属性文件中(/system/build.prop等),开机后会被加载到system properties store;SettingsProvider的数据保存在文件/data/system/users/0/settings_***.xml和数据库settings.db中;
  2. 作用范围不同:SystemProperties可以实现跨进程、跨层次调用,即底层的c/c++可以调用,java层也可以调用;SettingsProvider只能能在java层(APP)使用;
  3. 公开程度不同:SystemProperties有部分功能上层第三方APP可以使用(对于加了@hide标记的第三方APP仅可读,不可修改);SettingsProvider上层第三方APP不可以使用;

Settings的修改方式

adb shell

通过adb shell进行修改,格式为:

1
2
3
adb shell settings get [global/system/secure] [key]
adb shell settings put [global/system/secure] [key] [value]
adb shell settings list [global/system/secure]
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
PS C:\Users\ThinkPad> adb shell
tb8788p1_64_wifi:/ # settings put global transition_animation_scale 0.5
tb8788p1_64_wifi:/ # settings get global transition_animation_scale
0.5
tb8788p1_64_wifi:/ # settings list system
accelerometer_rotation=0
alarm_alert=content://media/internal/audio/media/35?title=Cesium&canonical=1
alarm_alert_set=1
background_power_saving_enable=1
dim_screen=1
display_paper_mode_activated=0
display_paper_mode_texture=255
dtmf_tone=1
dtmf_tone_type=0
end_button_behavior=2
ethernet_state=1
gsensor_change_all_process=0
haptic_feedback_enabled=0
hearing_aid=0
hide_rotation_lock_toggle_for_accessibility=0
import_remove_running=false
isEthernetOpen=0
is_ambient_sensor_adjust=1
is_gravity_sensor_adjust=1
is_light_sensor_adjust=1
is_proximity_sensor_adjust=1
lockscreen_sounds_enabled=0
machine_serial_number=62210304000055
mode_ringer_streams_affected=166
mute_streams_affected=111
notification_light_pulse=1
notification_sound=content://media/internal/audio/media/56?title=Pixie%20Dust&canonical=1
notification_sound_set=1
notification_vibration_intensity=0
pointer_speed=0
radio.data.stall.recovery.action=0
ring_vibration_intensity=0
ringtone=content://media/internal/audio/media/177?title=Flutey%20Phone&canonical=1
ringtone_set=1
screen_brightness=204
screen_brightness_for_vr=86
screen_brightness_mode=0
screen_off_timeout=600000
s..wo_close_voice_call=1
show_password=0
sound_effects_enabled=1
stu_fingerprint=.........
system_s..wo_sensor_value_report=1
system_user_login_state=1
time_12_24=24
tty_mode=0
user_rotation=0
vibrate_when_ringing=0
voice_trigger_active_command_id=1
voice_wakeup_mode=1
volume_alarm=5
volume_bluetooth_sco=5
volume_music=5
volume_music_speaker=1
volume_music_usb_headset=2
volume_notification=5
volume_ring=5
volume_system=5
volume_voice=3
website_control_state=0

应用修改

1
2
3
4
// 示例
import android.provider.Settings;//需要通过提供器中的settings类修改
Settings.Global.putString(mContext.getContentResolver(), "audio_test_result", value);//修改
Settings.Global.getString(mContext.getContentResolver(), "audio_test_result");//查询
1
2
3
4
5
6
7
8
9
10
11
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/change_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ChangeAppArgs">
</Button>
</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import android.provider.Settings;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.change_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Settings.Global.putString(getContentResolver(), "animator_duration_scale", "1.0");
String ads = Settings.Global.getString(getContentResolver(), "animator_duration_scale");
Log.d("MainActivity", "animator_duration_scale: " + ads);
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.appchangeargtest">
<!-- error: This Permission is only granted to system apps -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppChangeArgTest">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

提示:error: This Permission is only granted to system apps。说明第三方App肯定是无法修改这个动画缩放的,而是系统应用才有权修改,因此也排除了三方应用直接修改动画时长缩放参数。

推测如何找到原生设置入口

通过Intent来测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intenttosetting">
<application ...>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
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
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">

<Button
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SETTINGS">
</Button>
<Button
android:id="@+id/develop_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="APPLICATION_DEVELOPMENT_SETTINGS">
</Button>
<Button
android:id="@+id/accessibility_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ACCESSIBILITY_SETTINGS">
</Button>
<Button
android:id="@+id/device_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="DEVICE_INFO">
</Button>
<Button
android:id="@+id/top_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="top_settings">
</Button>

<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="packageName" />

<EditText
android:id="@+id/editText2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="className" />

<Button
android:id="@+id/package_class"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="package_class" />

<EditText
android:id="@+id/editText3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="actionName" />

<Button
android:id="@+id/action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ACTION" />
</LinearLayout>
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
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b1 = (Button) findViewById(R.id.settings);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("android.settings.SETTINGS");
startActivity(intent);
}
});
Button b2 = (Button) findViewById(R.id.develop_settings);
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS");
startActivity(intent);
}
});
Button b3 = (Button) findViewById(R.id.accessibility_settings);
b3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("android.settings.ACCESSIBILITY_SETTINGS");
startActivity(intent);
}
});
Button b4 = (Button) findViewById(R.id.device_info);
b4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("android.settings.DEVICE_INFO_SETTINGS");
startActivity(intent);
}
});
Button b5 = (Button) findViewById(R.id.top_settings);
b5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setClassName("com.android.settings", "com.android.settings.SubSettings");
startActivity(intent);
}
});
Button b_package_class = (Button) findViewById(R.id.package_class);
b_package_class.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EditText t1 = (EditText) findViewById(R.id.editText);
EditText t2 = (EditText) findViewById(R.id.editText2);
Intent intent = new Intent();
intent.setClassName(t1.getText().toString(), t2.getText().toString());
startActivity(intent);
}
});
Button b_action = (Button) findViewById(R.id.action);
b_action.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EditText t3 = (EditText) findViewById(R.id.editText3);
Intent intent = new Intent(t3.getText().toString());
startActivity(intent);
}
});
}
}

情况如下:

intent 某沃 某度
android.settings.SETTINGS 直接进原生设置。 进厂家设置。
com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS 提示请先启用开发者选项。如果处于开发者模式,则直接进。 提示请先启用开发者选项。如果处于开发者模式,则直接进。
android.settings.ACCESSIBILITY_SETTINGS 直接进无障碍设置。 直接进无障碍设置。
android.settings.DEVICE_INFO_SETTINGS 直接进关于本机信息,下拉菜单点击若干次版本号,可以进入开发者模式。 直接进关于本机信息,下拉菜单点击若干次版本号,可以进入开发者模式。
com.android.settings, com.android.settings.SubSettings 崩溃,日志报错,permission denial, id = 1000。疑似是此操作只有系统应用才可操作。 直接进原生设置顶层界面!
某一子设置项目的左上角返回按键流向 可以返回到设置顶层界面 经过处理,统一返回到桌面,即不可返回到设置顶层界面。

由以上实验,推测,某沃用户可以通过各种第三方应用先转到原生设置下点按版本号进入开发者模式,后进入开发者选项调整动画时长缩放。

由此,为了避免用户进入原生设置进行配置,造成不可预测的异常现象,需要定制一个设置程序,屏蔽掉原生设置的活动入口。有以下几个方向:

  1. 把原来action指向的原生设置程序指向厂家定制设置程序。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 以下信息来自.../vendor/mediatek/proprietary/packages/apps/MtkSettings/AndroidManifest.xml
    <activity android:name=".homepage.SettingsHomepageActivity"
    android:label="@string/settings_label_launcher"
    android:theme="@style/Theme.Settings.Home"
    android:launchMode="singleTask">
    <intent-filter android:priority="1">
    <action android:name="android.settings.SETTINGS" />
    <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
    android:value="true" />
    </activity>

拦截进入开发者模式

进入版本号界面后,快速连续点按版本号,会显示信息:“现在只需再执行n步操作即可进入开发者模式”。以此为入口,检索这个字符串的代号。

1
2
3
4
~/myProject/DT15/alps/vendor/mediatek/proprietary/packages/apps/MtkSettings/src$ rg "步操作即可进入开发者模式" ..
../res/values-zh-rCN/strings.xml
26: <item quantity="other">现在只需再执行 <xliff:g id="STEP_COUNT_1">%1$d</xliff:g> 步操作即可进入开发者模式。</item>
27: <item quantity="one">现在只需再执行 <xliff:g id="STEP_COUNT_0">%1$d</xliff:g> 步操作即可进入开发者模式。</item>

可以看到,这个信息的字符串在.../res/values-zh-rCN/strings.xml中定义。

1
2
3
4
25     <plurals name="show_dev_countdown" formatted="false" msgid="7201398282729229649">
26 <item quantity="other">现在只需再执行 <xliff:g id="STEP_COUNT_1">%1$d</xliff:g> 步操作即可进入开发者模式。</item>
27 <item quantity="one">现在只需再执行 <xliff:g id="STEP_COUNT_0">%1$d</xliff:g> 步操作即可进入开发者模式。</item>
28 </plurals>

这个字符串的name为show_dev_countdown,顺藤摸瓜。

1
2
3
~/myProject/DT15/alps/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com$ rg show_dev_countdown
android/settings/deviceinfo/BuildNumberPreferenceController.java
196: R.plurals.show_dev_countdown, mDevHitCountdown,

可以看到,输出此字符串的代码文件只有一个,BuildNumberPreferenceController.java,拦截进入开发者模式的解决之道则聚焦在了此文件上。

原生设置入口跳转

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
public class SettingsHomepageActivity extends FragmentActivity {
private static final String TAG = SettingsHomepageActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String password = getIntent().getStringExtra("password");
if(password != null && password.equals(".........")) {
Log.w(TAG, "Origin Action");
setContentView(R.layout.settings_homepage_container);
final View root = findViewById(R.id.settings_homepage_container);
root.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

setHomepageContainerPaddingTop();

final Toolbar toolbar = findViewById(R.id.search_action_bar);
FeatureFactory.getFactory(this).getSearchFeatureProvider()
.initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);

final ImageView avatarView = findViewById(R.id.account_avatar);
final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
getLifecycle().addObserver(avatarViewMixin);

if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
// Only allow contextual feature on high ram devices.
showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
}
showFragment(new TopLevelSettings(), R.id.main_content);
((FrameLayout) findViewById(R.id.main_content))
.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
} else {
Log.w(TAG, "s..wo's Action");
Intent intent = new Intent();
intent.setClassName("com.s..wo.eclass.settings", "com.s..wo.eclass.settings.SettingsActivity");
startActivity(intent);
finish();
}
}
// ...
}

版本信息入口屏蔽

目的是隐藏设置主页面最下面的“关于平板电脑”子项目。

在源码目录中检索“关于平板电脑”一词。发现此属性名为"about_settings"

1
2
3
<string name="about_settings" product="tablet" msgid="593457295516533765">"关于平板电脑"</string>
<string name="about_settings" product="default" msgid="1743378368185371685">"关于手机"</string>
<string name="about_settings" product="device" msgid="6717640957897546887">"关于设备"</string>

在源码目录中检索“about_settings”一词。发现在AndroidManifest.xml中被引用

1
2
vendor/mediatek/proprietary/packages/apps/MtkSettings/AndroidManifest.xml
1009: android:label="@string/about_settings"

AndroidManifest.xml中涉及关于设备信息的完整部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<activity android:name=".Settings$MyDeviceInfoActivity"
android:label="@string/about_settings"
android:icon="@drawable/ic_homepage_about">
<intent-filter android:priority="1">
<action android:name="android.settings.DEVICE_INFO_SETTINGS" />
<action android:name="android.settings.DEVICE_NAME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="71">
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>

说明,屏蔽版本信息入口后,依然可以通过“adb shell am start -a android.settings.DEVICE_INFO_SETTINGS”进入版本信息界面。

接着检索android.settings.DEVICE_INFO_SETTINGS

1
2
3
4
5
frameworks/base/core/java/android/provider/Settings.java

@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_DEVICE_INFO_SETTINGS =
"android.settings.DEVICE_INFO_SETTINGS";

检索ACTION_DEVICE_INFO_SETTINGS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
frameworks/base/core/java/android/provider/Settings.java
1177: public static final String ACTION_DEVICE_INFO_SETTINGS =

development/apps/BuildWidget/src/com/android/buildwidget/BuildWidget.java
69: new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS),

frameworks/base/core/tests/coretests/src/android/provider/SettingsProviderTest.java
339: assertCanBeHandled(new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS));

cts/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
73: new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS),

cts/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
125: Settings.ACTION_DEVICE_INFO_SETTINGS,
127: Settings.ACTION_DEVICE_INFO_SETTINGS,

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/uitests/src/com/android/settings/ui/AboutPhoneSettingsTests.java
76: launchAboutPhoneSettings(Settings.ACTION_DEVICE_INFO_SETTINGS);
1
vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/core/gateway/SettingsGateway.java

应用信息打开按钮屏蔽

全局搜索“打开”。

  1. mtk_strings.xml: vendor/mediatek/proprietary/packages/apps/Mms/res/values-zh-rCN
  2. strings.xml: vendor/mediatek/proprietary/frameworks/base/res/res/values-zh-rCN
1
<string name="launch_instant_app" msgid="391581144859010499">"打开"</string>

全局搜索“强行停止”

  1. strings.xml: vendor/mediatek/proprietary/frameworks/apps/MtkSettings/res/values-zh-rCN
    1. 649958863744041872
    2. 7435006169872876756

修改的文件

DT15/alps/vendor/mediatek/proprietary/packages/apps/MtkSettings

进入android.settings.SETTINGS时会判断调用者或校验extra参数;进入设备信息页面时会判断调用者;去除应用信息页面中“打开”的按钮;

1
2
3
4
5
[feature][SettingsEntryBlock] Intercept the entry of AOSP config

[what] 1. when intent to AOSP settings page, it will judge the caller or verify extra parameters; 2. when intent to the AOSP device info page, it will judge the caller; 3. remove the "Open" button in the ASOP app info page;
[why] avoid user mistakenly or deliberately configure parameters to cause exceptions
[how] modify intent logic; hide entries

AppButtonsPreferenceController.java

src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@@ -169,9 +169,10 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
if (isAvailable()) {
mButtonsPref = ((ActionButtonsPreference) screen.findPreference(
KEY_ACTION_BUTTONS))
- .setButton1Text(R.string.launch_instant_app)
- .setButton1Icon(R.drawable.ic_settings_open)
- .setButton1OnClickListener(v -> launchApplication())
+ //.setButton1Text(R.string.launch_instant_app)
+ //.setButton1Icon(R.drawable.ic_settings_open)
+ //.setButton1OnClickListener(v -> launchApplication())
+ .setButton1Visible(false)
.setButton2Text(R.string.uninstall_text)
.setButton2Icon(R.drawable.ic_settings_delete)
.setButton2OnClickListener(new UninstallAndDisableButtonListener())

SettingsGateway.java【去除版本号入口】

src/com/android/settings/core/gateway/SettingsGateway.java

1
2
3
4
5
6
7
8
9
@@ -190,7 +190,7 @@ public class SettingsGateway {
UserDictionaryList.class.getName(),
UserDictionarySettings.class.getName(),
DisplaySettings.class.getName(),
- MyDeviceInfoFragment.class.getName(),
+ //MyDeviceInfoFragment.class.getName(),
ModuleLicensesDashboard.class.getName(),
ManageApplications.class.getName(),
FirmwareVersionSettings.class.getName(),

SettingsHomepageActivity.java

src/com/android/settings/homepage/SettingsHomepageActivity.java

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
import android.util.Log;

@@ -37,33 +39,42 @@ import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
import com.android.settings.overlay.FeatureFactory;

public class SettingsHomepageActivity extends FragmentActivity {
-
+ private static final String TAG = SettingsHomepageActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- setContentView(R.layout.settings_homepage_container);
- final View root = findViewById(R.id.settings_homepage_container);
- root.setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-
- setHomepageContainerPaddingTop();
-
- final Toolbar toolbar = findViewById(R.id.search_action_bar);
- FeatureFactory.getFactory(this).getSearchFeatureProvider()
- .initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
-
- final ImageView avatarView = findViewById(R.id.account_avatar);
- final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
- getLifecycle().addObserver(avatarViewMixin);
-
- if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
- // Only allow contextual feature on high ram devices.
- showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
+ String password = getIntent().getStringExtra("password");
+ if(password != null && password.equals(".........")) {
+ Log.w(TAG, "Origin Action");
+ setContentView(R.layout.settings_homepage_container);
+ final View root = findViewById(R.id.settings_homepage_container);
+ root.setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+
+ setHomepageContainerPaddingTop();
+
+ final Toolbar toolbar = findViewById(R.id.search_action_bar);
+ FeatureFactory.getFactory(this).getSearchFeatureProvider()
+ .initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
+
+ final ImageView avatarView = findViewById(R.id.account_avatar);
+ final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
+ getLifecycle().addObserver(avatarViewMixin);
+
+ if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
+ // Only allow contextual feature on high ram devices.
+ showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
+ }
+ showFragment(new TopLevelSettings(), R.id.main_content);
+ ((FrameLayout) findViewById(R.id.main_content))
+ .getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
+ } else {
+ Log.w(TAG, "s..wo's Action");
+ Intent intent = new Intent();
+ intent.setClassName("com.s..wo.eclass.settings", "com.s..wo.eclass.settings.SettingsActivity");
+ startActivity(intent);
+ finish();
}
- showFragment(new TopLevelSettings(), R.id.main_content);
- ((FrameLayout) findViewById(R.id.main_content))
- .getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
}

MyDeviceInfoFragment.java

com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import android.widget.Toast;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if("android-app://com.android.settings".equals(this.getActivity().getReferrer().toString()))
{
use(ImeiInfoPreferenceController.class).setHost(this /* parent */);
use(DeviceNamePreferenceController.class).setHost(this /* parent */);
mBuildNumberPreferenceController = use(BuildNumberPreferenceController.class);
mBuildNumberPreferenceController.setHost(this /* parent */);
} else {
Toast.makeText(context, R.string.cannot_into_device_info, Toast.LENGTH_SHORT).show();
finish();
}
}

strings.xml

vendor/mediatek/proprietary/packages/apps/MtkSettings/res/values/strings.xml

1
<string name="cannot_into_device_info">Only debuggers can access the Device-Info Page</string>

vendor/mediatek/proprietary/packages/apps/MtkSettings/res/values-zh-rCN/strings.xml

1
<string name="cannot_into_device_info" msgid="2196318436963951285">非调试者无法进入版本信息页面</string>

编译冲突

vendor/mediatek/proprietary/packages/apps/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java

日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
development/apps/Fallback/AndroidManifest.xml
55: <action android:name="android.settings.SETTINGS" />

vendor/mediatek/proprietary/packages/apps/MtkSettings/AndroidManifest.xml
160: <action android:name="android.settings.SETTINGS" />

frameworks/base/core/java/android/provider/Settings.java
122: public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

cts/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
633: executeShellCommand("am start -a android.settings.SETTINGS");

development/samples/MultiWindow/src/com/example/android/multiwindow/LaunchingAdjacentActivity.java
53: Intent intent = new Intent("android.settings.SETTINGS");

vendor/mediatek/proprietary/operator/packages/apps/Browser/OP07/src/com/mediatek/op07/browser/OP07NetworkStateHandlerExt.java
158: Intent intent = new Intent("android.settings.SETTINGS");
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
frameworks/base/api/current.txt
38705: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

development/apps/Fallback/AndroidManifest.xml
55: <action android:name="android.settings.SETTINGS" />

prebuilts/sdk/5/public/api/android.txt
11335: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/7/public/api/android.txt
11389: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/2/public/api/android.txt
7654: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/6/public/api/android.txt
11342: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/12/public/api/android.txt
15925: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/10/public/api/android.txt
13613: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/22/public/api/android.txt
25214: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/22/system/api/android.txt
26813: field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/25/public/api/android.txt
32341: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/25/system/api/android.txt
35173: field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/8/public/api/android.txt
12573: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/11/public/api/android.txt
15541: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/17/public/api/android.txt
18754: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/20/public/api/android.txt
21186: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/28/public/api/android.txt
36463: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/15/public/api/android.txt
17382: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/21/public/api/android.txt
25141: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/14/public/api/android.txt
17255: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/3/public/api/android.txt
8708: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/1/public/api/android.txt
7650: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/13/public/api/android.txt
16020: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/19/public/api/android.txt
21028: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/18/public/api/android.txt
19874: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/4/public/api/android.txt
9945: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/27/public/api/android.txt
34744: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/24/public/api/android.txt
32236: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/27/system/api/android.txt
37925: field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/23/public/api/android.txt
26448: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/24/system/api/android.txt
35019: field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/23/system/api/android.txt
28511: field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/29/public/api/android.txt
38674: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/9/public/api/android.txt
13384: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/16/public/api/android.txt
18326: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/26/public/api/android.txt
34646: field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

prebuilts/sdk/26/system/api/android.txt
37772: field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";

frameworks/opt/setupwizard/tools/docs/android-22.txt
25229: field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";

vendor/mediatek/proprietary/packages/apps/MtkSettings/AndroidManifest.xml
160: <action android:name="android.settings.SETTINGS" />

external/autotest/client/common_lib/cros/arc.py
657: output = adb_shell('am start -W -a android.settings.SETTINGS')

frameworks/base/core/java/android/provider/Settings.java
122: public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

out/target/common/obj/APPS/MtkSettings_intermediates/manifest/AndroidManifest.xml.fixed
141: <action android:name="android.settings.SETTINGS"/>

out/target/common/obj/APPS/MtkSettings_intermediates/manifest/AndroidManifest.xml
168: <action android:name="android.settings.SETTINGS" />

cts/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
633: executeShellCommand("am start -a android.settings.SETTINGS");

development/samples/MultiWindow/src/com/example/android/multiwindow/LaunchingAdjacentActivity.java
53: Intent intent = new Intent("android.settings.SETTINGS");

vendor/mediatek/proprietary/operator/packages/apps/Browser/OP07/src/com/mediatek/op07/browser/OP07NetworkStateHandlerExt.java
158: Intent intent = new Intent("android.settings.SETTINGS");

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
xurui@ubuntu:~/myProject/DT15/alps$
rg 'package com.android.settings;' . -j56
./external/flatbuffers/.gitignore: line 114: error parsing glob '.corpus**': invalid use of **; must be one path component
./external/flatbuffers/.gitignore: line 115: error parsing glob '.seed**': invalid use of **; must be one path component
out/target/common/R/com/android/settings/Manifest.java
8:package com.android.settings;

out/target/common/R/com/android/settings/R.java
8:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ProgressCategoryBase.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/CustomListPreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SummaryPreference.java
15:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/DateTimeSettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/LinkifyUtils.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/CancellablePreference.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/TestingSettingsBroadcastReceiver.java
1:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/EncryptionInterstitial.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/AccessiblePreferenceCategory.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SettingsDumpService.java
15:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ProgressCategory.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/DisplaySettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/BrightnessPreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/TestingSettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/BandMode.java
1:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/HelpTrampoline.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SetFullBackupPassword.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/MasterClearConfirm.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SettingsLicenseActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/MonitoringCertInfoActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/AirplaneModeEnabler.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ResetNetworkConfirm.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ResetNetwork.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/TrustedCredentialsDialogBuilder.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ActivityPicker.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/IccLockSettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/FallbackHome.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SetupWizardUtils.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ManualDisplayActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/RingtonePreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/DialogCreatable.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/RestrictedCheckBox.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SetupRedactionInterstitial.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/RadioInfo.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/MasterClear.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/CryptKeeper.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/RegulatoryInfoDisplayActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SelfAvailablePreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/AirplaneModeVoiceActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/Utils.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/RestrictedSettingsFragment.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/TetherSettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/DefaultRingtonePreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SetupEncryptionInterstitial.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/UsageStatsActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/AppWidgetLoader.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/TouchBlockingFrameLayout.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/RestrictedRadioButton.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SubSettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/EditPinPreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/Settings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/UserCredentialsSettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SeekBarDialogPreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SettingsInitialize.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/PointerSpeedPreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SettingsActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/BugreportPreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/AllowBindAppWidgetActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/CheckableLinearLayout.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/CryptKeeperConfirm.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ButtonBarHandler.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SettingsPreferenceFragment.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/SettingsTutorialDialogWrapperActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/RestrictedListPreference.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/RemoteBugreportActivity.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/LegalSettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/TrustedCredentialsSettings.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/AppWidgetPickActivity.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ProxySelector.java
17:package com.android.settings;

out/target/common/obj/APPS/MtkSettings_intermediates/srcjars/com/android/settings/Manifest.java
8:package com.android.settings;

out/target/common/obj/APPS/MtkSettings_intermediates/srcjars/com/android/settings/R.java
8:package com.android.settings;

out/target/common/obj/APPS/MtkSettings_intermediates/aapt2/com/android/settings/Manifest.java
8:package com.android.settings;

out/target/common/obj/APPS/MtkSettings_intermediates/aapt2/com/android/settings/R.java
8:package com.android.settings;

out/target/common/obj/JAVA_LIBRARIES/settings-logtags_intermediates/logtags/src/com/android/settings/EventLogTags.java
5:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/HelpTrampolineTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/TetherSettingsTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/unit/src/com/android/settings/UserCredentialsTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/unit/src/com/android/settings/UtilsTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/RestrictedSettingsFragmentTest.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/unit/src/com/android/settings/RegulatoryInfoDisplayActivityTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/SettingsDumpServiceTest.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/RestrictedListPreferenceTest.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/UtilsTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/SettingsActivityTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/TestUtils.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/LegalSettingsTest.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/ResetNetworkConfirmTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/SettingsPreferenceFragmentTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/RegulatoryInfoDisplayActivityTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/SettingsDialogFragmentTest.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/MasterClearConfirmTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/DisplaySettingsTest.java
1:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/ResetNetworkTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/SummaryPreferenceTest.java
16:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/SettingsInitializeTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/MasterClearTest.java
17:package com.android.settings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/unit/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java
1:package com.android.settings;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
xurui@ubuntu:~/myProject/DT15/alps$
rg 'com.s..wo.eclass.settings' . -j56
./external/flatbuffers/.gitignore: line 114: error parsing glob '.corpus**': invalid use of **; must be one path component
./external/flatbuffers/.gitignore: line 115: error parsing glob '.seed**': invalid use of **; must be one path component
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
624: "com.s..wo.eclass.settings",

vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/custom/UtilsAc.java
37: new ComponentName("com.s..wo.eclass.settings", "com.s..wo.eclass.settings.SettingsActivity"));
49: new ComponentName("com.s..wo.eclass.settings", "com.s..wo.eclass.settings.SettingsActivity"));
61: new ComponentName("com.s..wo.eclass.settings", "com.s..wo.eclass.settings.SettingsActivity"));
88: new ComponentName("com.s..wo.eclass.settings", "com.s..wo.eclass.settings.SettingsActivity"));
98: new ComponentName("com.s..wo.eclass.settings", "com.s..wo.eclass.settings.SettingsActivity"));
161: intent.setClassName("com.s..wo.eclass.settings", "com.s..wo.eclass.settings.SettingsActivity");

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
out/target/common/obj/APPS/MtkSettings_intermediates/proguard_dictionary
21825:com.android.settings.SubSettings -> com.android.settings.SubSettings:

out/target/common/obj/APPS/MtkSettings_intermediates/manifest/AndroidManifest.xml
216: android:name="com.android.settings.SubSettings"

vendor/mediatek/proprietary/hardware/power/config/mt6739/app_list/power_app_cfg.xml
25: <Activity name="com.android.settings.SubSettings">

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/location/LocationSlice.java
38:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/core/SubSettingLauncher.java
31:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/core/SettingsBaseActivity.java
42:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
37:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/panel/NfcPanel.java
25:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/search/SearchResultTrampoline.java
27:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/panel/WifiPanel.java
25:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/slices/SliceBuilderUtils.java
47:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/notification/ZenModeSliceBuilder.java
38:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/wifi/slice/WifiSlice.java
49:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
51:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
37:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
49:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
45:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
34:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
37:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
37:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
34:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
45:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
39:import com.android.settings.SubSettings;

vendor/mediatek/proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
52:import com.android.settings.SubSettings;

Android_多线程和异步编程

服务

服务是Android中实现程序后台运行的解决方案,适合不需要和用户交互而且长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。另外,也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。

Android多线程编程

当我们需要执行一些耗时操作,比如说发起一条网络请求时,考虑到网速等其他原因,服务器未必会立刻响应我们的请求,如果不将这类操作放在子线程里去运行,就会导致主线程被阻塞住,从而影响用户对软件的正常使用。

线程的基本用法

继承Thread

Android多线程编程其实并不比Java多线程编程特殊,基本都是使用相同的语法。比如说,定义一个线程只需要新建一个类继承自Thread,然后重写父类的run方法,并在里面编写耗时逻辑即可,如下所示:

1
2
3
4
5
6
class MyThread extends Thread {
@Override
public void fun() {
// 处理具体的逻辑
}
}

那么该如何启动这个线程呢?其实很简单,只需要new出MyThread的实例,然后调用它的start方法,这样run方法中的代码就会在子线程当中运行了,如下所示:

1
new MyThread().start();

实现接口Runnable

当然,使用继承的方式耦合性有点高,更多的时候我们都会选择使用实现Runnable接口的方式来定义一个线程,如下所示:

1
2
3
4
5
6
class MyThread implements Runnable {
@Override
public void run() {
// 处理具体的逻辑
}
}

如果使用了这种写法,启动线程的方法也需要进行相应的改变,如下所示:

1
2
MyThread myThread = new MyThread();
new Thread(myThread).start();

可以看到,Thread的构造函数接收一个Runnable参数,而我们new出的MyThread正是一个实现了Runnable接口的对象,所以可以直接将它传人到Thread的构造函数里。接着调用Thread的start方法,run方法中的代码就会在子线程当中运行了。

匿名类

如果你不想专门再定义一个类去实现Runnable接口,也可以使用匿名类的方式,这种写法更为常见。如下所示:

1
2
3
4
5
6
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
}
}).start();

以上几种线程的使用方式在Java中创建和启动线程也是使用同样的方式。了解线程的基本用法后,下面我们来看一下Android多线程编程与Java多线程编程不同的地方。

子线程中更新UI

和许多其他的GUI库一样,Android的UI也是线程不安全的。也就是说,如果想要更新应用程序里的UI元素,则必须在主线程中进行,否则就会出现异常。眼见为实,通过一个具体的例子来验证一下。新建一个AndroidThreadTest项目,然后修改activity_main.xml中的代码,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/change_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Change Text">
</Button>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello world"
android:textSize="20sp">
</TextView>
</RelativeLayout>

布局文件中定义了两个控件,TextView用于在屏幕的正中央显示一个Hello world字符串,Button用于改变TextView中显示的内容,我们希望在点击Button后可以把TextView中显示的字符串改成Nice to meet you。

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

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
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
Button changeText = (Button) findViewById(R.id.change_text);
changeText.setOnCLickListener(this);
}
@Override
public void onCLick(View v) {
switch(v.getId()) {
case R.id.change_text:
new Thread(new Runnable() {
@Override
public void run(){
text.setText("Nice to meet you");
}
}).start();
break;
default:
break;
}
}
}

可以看到,我们在Change Text按钮的点击事件里面开启了一个子线程,然后在子线程中调用TextView的setText方法将显示的字符串改成Nice to meet you。代码的逻辑非常简单,只不过我们是在子线程中更新UI的。现在运行一下程序并点击Change Text按钮,程序果然崩溃。

logcat错误日志:

1
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

安卓异步消息处理机制

由此证实了Android确实是不允许在子线程中进行UI操作的。但是有些时候必须在子线程里去执行一些耗时任务,然后根据任务的执行结果来更新相应的UI控件。对于这种情况,Android提供了一套异步消息处理机制,完美地解决了在子线程中进行UI操作的问题。

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

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
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int UPDATE_TEXT = 1;
private TextView text;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
// 可以在这里进行UI操作
text.setText("Nice to meet you");
break;
default:
break;
}
}
};
...
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.change_text:
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message); // 将Message对象发送出去
}
}).start();
break;
default:
break;
}
}
}

这里我们先是定义了一个整型常量UPDATE_TEXT,用于表示更新TextView这个动作。然后新增一个Handler对象,并重写父类的handleMessage方法,在这里对具体的Message进行处理。如果发现Message的what字段的值等于UPDATE_TEXT,就将TextView显示的内容改成Nice to meet you。

下面再来看一下Change Text按钮的点击事件中的代码。可以看到,这次我们并没有在子线程里直接进行UI操作,而是创建了一个Message( android.os.Message)对象,并将它的what字段的值指定为UPDATE_TEXT,然后调用Handler的sendMessage方法将这条Message发送出去。很快,Handler就会收到这条Message,并在handleMessage方法中对它进行处理。注意此时handleMessage方法中的代码就是在主线程当中运行的了,所以我们可以放心地在这里进行UI操作。接下来对Message携带的what字段的值进行判断,如果等于UPDATE_TEXT,就将TextView显示的内容改成Nice to meet you。

这样就已经掌握了Android异步消息处理的基本用法,使用这种机制就可以出色地解决掉在子线程中更新UI的问题(其实本质上是子线程发消息给主线程,主线程更新UI)。下面我们就来分析一下Android异步消息处理机制到底是如何工作的。

原理

Android中的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue和Looper。

  1. Message
  2. Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。上一小节中我们使用到了Message的what字段,除此之外还可以使用arg1和arg2字段来携带一些整型数据,使用obj字段携带一个Object对象。
  3. Handler
  4. Handler顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用Handler的sendMessage方法,而发出的消息经过一系列地辗转处理后,最终会传递到Handler的handleMessage方法中。
  5. MessageQueue
  6. MessageQueue是消息队列的意思,它主要用于存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象。
  7. Looper
  8. Looper是每个线程中的MessageQueue的管家,调用Looper的Loop方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将它取出,并传递到Handler的handleMessage方法中。每个线程中也只会有一个Looper对象。

了解了Message、Handler、MessageOueue以及Looper的基本概念后,我们再来把异步消息处理的整个流程梳理一遍。首先需要在主线程当中创建一个Handler对象,并重写handLeMessage方法。然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去。之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理消息,最后分发回Handler的handleMessage方法中。由于Handler是在主线程中创建的,所以此时handleMessage方法中的代码也会在主线程中运行,于是我们在这里就可以安心地进行UI操作了。整个异步消息处理机制的流程如图所示。

image-20220817202437951

使用AsyncTask

不过为了更加方便我们在子线程中对UI进行操作,Android还提供了另外一些好用的工具,比如AsyncTask。借助AsyncTask,即使你对异步消息处理机制完全不了解,也可以十分简单地从子线程切换到主线程。当然,AsyncTask背后的实现原理也是基于异步消息处理机制的,只是Android帮我们做了很好的封装而已。首先来看一下AsyncTask的基本用法,由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它。在继承时我们可以为AsyncTask类指定3个泛型参数,这3个参数的用途如下。

  1. Params。在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
  2. Progress。后台任务执行时、如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
  3. Result。当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

因此,一个最简单的自定义AsyncTask就可以写成如下方式:

1
2
3
class DownloadTask extends AsyncTask<Void, Integer, Boolean> {
...
}

这里我们把AsyncTask的第一个泛型参数指定为Void,表示在执行AsyncTask的时候不需要传入参数给后台任务。第二个泛型参数指定为Integer,表示使用整型数据来作为进度显示单位。第三个泛型参数指定为Boolean,则表示使用布尔型数据来反馈执行结果。

当然,目前我们自定义的DownloadTask还是一个空任务,并不能进行任何实际的操作,我们还需要去重写AsyncTask中的几个方法才能完成对任务的定制。经常需要去重写的方法有以下4个。

  1. onPreExecute()
    1. 这个方法会在后台任务开始执行之前调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
  2. doInBackground(Params...)
    1. 这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果返回,如果AsyncTask的第三个泛型参数指定的是Void就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。
  3. onProgressUpdate(Progress...)
    1. 当在后台任务中调用了publishProgress(Progress...)方法后,onProgressUpdate(Progress...)方法就会很快被调用,该方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
  4. onPostExecute(Result)
    1. 当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些 U操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。

因此,一个比较完整的自定义AsyncTask就可以写成如下方式:

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
class DownloadTask extends AsyncTask<Void, Integer, Boolean> {
@Override
protected void onPreExecute() {
progressDialog.show(); // 显示进度对话框
}
@Override
protected Boolean doInBackground(Void... params) {
try {
while (true) {
int downloadPercent = doDownload();
publishProgress(downloadPercent);
if(downloadPercent >= 100) {
break;
}
}
} catch (Exception e) {
return false;
}
return true;
}
@Override
protected void onProgressUpdate(Integer... values) {
// 在这里更新下载进度
progressDialog.setMessage("Download " + values[0] + "%");
}
@Override
protected void onPostExecute(Boolean result) {
progressDialog.dismiss(); // 关闭进度对话框
// 在这里提示下载结果
if (result) {
Toast.makeText(context, "Download succeeded", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Download failed", Toast.LENGTH_SHORT).show();
}
}
}

在这个DownloadTask中,我们在doInBackground方法里去执行具体的下载任务。这个方法里的代码都是在子线程中运行的,因而不会影响到主线程的运行。注意这里虚构了一个doDownload方法,这个方法用于计算当前的下载进度并返回,我们假设这个方法已经存在了在得到了当前的下载进度后,下面就该考虑如何把它显示到界面上了,由于doInBackground方法是在子线程中运行的,在这里肯定不能进行UI操作,所以我们可以调用publishProgress方法并将当前的下载进度传进来,这样onProgressUpdate方法就会很快被调用,在这里就可以进行UI操作了。

当下载完成后,doInBackground方法会返回一个布尔型变量,这样onPostExecute方法就会很快被调用,这个方法也是在主线程中运行的。然后在这里我们会根据下载的结果来弹出相应的Toast提示,从而完成整个DownloadTask任务。

简单来说,使用AsyncTask的诀窍就是,在doInBackground方法中执行具体的耗时任务。在onProgressUpdate方法中进行UI操作,在onPostExecute方法中执行一些任务的收尾工作。

如果想要启动这个任务,只需编写以下代码即可:

1
new DownLoadTask().execute();

以上就是AsyncTask的基本用法,我们并不需要去考虑什么异步消息处理机制,也不需要专门使用一个Handler来发送和接收消息。只需要调用一下publishProgress方法,就可以轻松地从子线程切换到UI线程了。