一、核心类
Settings/src/com/android/settings/applications/ManageApplications.java
Settings/src/com/android/settings/applications/InstalledAppDetails.java
Settings/src/com/android/settings/AppNotificationSettings.java
frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
二、源码流程
(1):ManageApplications.java类中获取所有app的列表及点击事件
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mApplications != null && mApplications.getCount() > position) {
ApplicationsState.AppEntry entry = mApplications.getAppEntry(position);
mCurrentPkgName = entry.info.packageName;
mCurrentUid = entry.info.uid;
startApplicationDetailsActivity();
}
}
// utility method used to start sub activity
private void startApplicationDetailsActivity() {
switch (mListType) {
case LIST_TYPE_NOTIFICATION:
startAppInfoFragment(AppNotificationSettings.class,
R.string.app_notifications_title);
break;
case LIST_TYPE_DOMAINS_URLS:
startAppInfoFragment(AppLaunchSettings.class, R.string.auto_launch_label);
break;
case LIST_TYPE_USAGE_ACCESS:
startAppInfoFragment(UsageAccessDetails.class, R.string.usage_access);
break;
case LIST_TYPE_STORAGE:
startAppInfoFragment(AppStorageSettings.class, R.string.storage_settings);
break;
case LIST_TYPE_HIGH_POWER:
HighPowerDetail.show(this, mCurrentPkgName, INSTALLED_APP_DETAILS,
mFinishAfterDialog);
break;
case LIST_TYPE_OVERLAY:
startAppInfoFragment(DrawOverlayDetails.class, R.string.overlay_settings);
break;
case LIST_TYPE_WRITE_SETTINGS:
startAppInfoFragment(WriteSettingsDetails.class, R.string.write_system_settings);
break;
// TODO: Figure out if there is a way where we can spin up the profile's settings
// process ahead of time, to avoid a long load of data when user clicks on a managed app.
// Maybe when they load the list of apps that contains managed profile apps.
default:
startAppInfoFragment(InstalledAppDetails.class, R.string.application_info_label);
break;
}
}
private void startAppInfoFragment(Class<?> fragment, int titleRes) {
AppInfoBase.startAppInfoFragment(fragment, titleRes, mCurrentPkgName, mCurrentUid, this,
INSTALLED_APP_DETAILS);
}
(2):跳转对应的app详情页
startAppInfoFragment(InstalledAppDetails.class, R.string.application_info_label);函数会跳转到InstalledAppDetails.java类
private static final String KEY_HEADER = "header_view";//
private static final String KEY_NOTIFICATION = "notification_settings";//通知
private static final String KEY_STORAGE = "storage_settings";//存储
private static final String KEY_PERMISSION = "permission_settings";//权限
private static final String KEY_DATA = "data_settings"; //流量使用
private static final String KEY_LAUNCH = "preferred_settings";//默认打开
private static final String KEY_BATTERY = "battery";//电池
private static final String KEY_MEMORY = "memory";//内存
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference == mStoragePreference) {
startAppInfoFragment(AppStorageSettings.class, mStoragePreference.getTitle());
} else if (preference == mNotificationPreference) {
startAppInfoFragment(AppNotificationSettings.class,
getString(R.string.app_notifications_title));
} else if (preference == mPermissionsPreference) {
startManagePermissionsActivity();
} else if (preference == mLaunchPreference) {
startAppInfoFragment(AppLaunchSettings.class, mLaunchPreference.getTitle());
} else if (preference == mMemoryPreference) {
ProcessStatsBase.launchMemoryDetail((SettingsActivity) getActivity(),
mStatsManager.getMemInfo(), mStats, false);
} else if (preference == mDataPreference) {
startAppInfoFragment(AppDataUsage.class, getString(R.string.app_data_usage));
} else if (preference == mBatteryPreference) {
BatteryEntry entry = new BatteryEntry(getActivity(), null, mUserManager, mSipper);
PowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(),
mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, true, false);
} else {
return false;
}
return true;
}
根据KEY的名称可知对应的条目功能,通知对应的是mNotificationPreference,触发后会跳转到
AppNotificationSettings.java中
(3):AppNotificationSettings中获取通知权限项
该类主要是获取可进行的设置项(比如:全部阻止,显示时不发出提示音,覆盖“勿扰”设置)的当前状态,以及提供选项按钮进行设置。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.app_notification_settings);
mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE);
mPriority =
(RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BYPASS_DND);
mVisibilityOverride =
(RestrictedDropDownPreference) getPreferenceScreen().findPreference(
KEY_VISIBILITY_OVERRIDE);
mBlock = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BLOCK);
mSilent = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_SILENT);
if (mPkgInfo != null) {
mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo);
NotificationManager.Policy policy =
NotificationManager.from(mContext).getNotificationPolicy();
mDndVisualEffectsSuppressed = policy == null ? false : policy.suppressedVisualEffects != 0;
// load settings intent
ArrayMap<String, AppRow> rows = new ArrayMap<String, AppRow>();
rows.put(mAppRow.pkg, mAppRow);
collectConfigActivities(rows);
setupImportancePrefs(mAppRow.systemApp, mAppRow.appImportance, mAppRow.banned);
setupPriorityPref(mAppRow.appBypassDnd);
setupVisOverridePref(mAppRow.appVisOverride);
updateDependents(mAppRow.appImportance);
}
}
在onCreate()进行了初始化,主要代码如下:
mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo);//更加包名信息获取通知权限状态
...
//初始化相应控件的选择事件
setupImportancePrefs(mAppRow.systemApp, mAppRow.appImportance, mAppRow.banned);
//以下就是初始化相应的ui显示
setupPriorityPref(mAppRow.appBypassDnd);
setupVisOverridePref(mAppRow.appVisOverride);
updateDependents(mAppRow.appImportance);
setupImportancePrefs()函数是在NotificationSettingsBase.java类中的:
protected void setupImportancePrefs(boolean isSystemApp, int importance, boolean banned) {
if (mShowSlider) {
setVisible(mBlock, false);
setVisible(mSilent, false);
mImportance.setDisabledByAdmin(mSuspendedAppsAdmin);
mImportance.setMinimumProgress(
isSystemApp ? Ranking.IMPORTANCE_MIN : Ranking.IMPORTANCE_NONE);
mImportance.setMax(Ranking.IMPORTANCE_MAX);
mImportance.setProgress(importance);
mImportance.setAutoOn(importance == Ranking.IMPORTANCE_UNSPECIFIED);
mImportance.setCallback(new ImportanceSeekBarPreference.Callback() {
@Override
public void onImportanceChanged(int progress, boolean fromUser) {
if (fromUser) {
mBackend.setImportance(mPkg, mUid, progress);
}
updateDependents(progress);
}
});
} else {
setVisible(mImportance, false);
if (isSystemApp) {
setVisible(mBlock, false);
/// M: mSilent depends on mBlock, so remove mSilent when remove mBlock
setVisible(mSilent, false);
} else {
boolean blocked = importance == Ranking.IMPORTANCE_NONE || banned;
mBlock.setChecked(blocked);
mBlock.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean blocked = (Boolean) newValue;
final int importance =
blocked ? Ranking.IMPORTANCE_NONE : Ranking.IMPORTANCE_UNSPECIFIED;
Log.d("kaypermission", "onPreferenceChange: blocked:" + blocked + " importance:" + importance);
mBackend.setImportance(mPkgInfo.packageName, mUid, importance);
updateDependents(importance);
return true;
}
});
mSilent.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean silenced = (Boolean) newValue;
final int importance =
silenced ? Ranking.IMPORTANCE_LOW : Ranking.IMPORTANCE_UNSPECIFIED;
mBackend.setImportance(mPkgInfo.packageName, mUid, importance);
updateDependents(importance);
return true;
}
});
updateDependents(banned ? Ranking.IMPORTANCE_NONE : importance);
}
}
}
全部阻止对应的是mBlock.setOnPreferenceChangeListener(),点击触发后会先调用mBackend.setImportance()功能设置并走到AppNotificationSettings.java的updateDependents()更新ui显示
@Override
protected void updateDependents(int importance) {
LockPatternUtils utils = new LockPatternUtils(getActivity());
boolean lockscreenSecure = utils.isSecure(UserHandle.myUserId());
UserInfo parentUser = mUm.getProfileParent(UserHandle.myUserId());
if (parentUser != null){
lockscreenSecure |= utils.isSecure(parentUser.id);
}
if (getPreferenceScreen().findPreference(mBlock.getKey()) != null) {
setVisible(mSilent, checkCanBeVisible(Ranking.IMPORTANCE_MIN, importance));
mSilent.setChecked(importance == Ranking.IMPORTANCE_LOW);
}
setVisible(mPriority, checkCanBeVisible(Ranking.IMPORTANCE_DEFAULT, importance)
&& !mDndVisualEffectsSuppressed);
setVisible(mVisibilityOverride,
checkCanBeVisible(Ranking.IMPORTANCE_MIN, importance) && lockscreenSecure);
}
三:小结
做个测试,在SystemUI中阻止某个app的默认开启的通知权限,功能有实现。
一:首先拷贝NotificationBackend.java的类到指定位置
二:使用如下函数进行设置
private void setNotificationPermission(String packageName){
PackageManager pm = mContext.getPackageManager();
if (packageName != null) {
try {
PackageInfo info = pm.getPackageInfo(packageName, 0);
if(info != null){
NotificationBackend mBackend = new NotificationBackend();
NotificationBackend.AppRow mAppRow = mBackend.loadAppRow(mContext, pm, info);
int importance = mBackend.getImportance(packageName, mAppRow.uid);
if(importance != 0 ){
mBackend.setImportance(packageName, mAppRow.uid, 0);
}
}
} catch (PackageManager.NameNotFoundException e) {
}
}
}