我的GitHub | 我的博客 | 我的微信 | 我的郵箱 |
---|---|---|---|
baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
目錄
UsageStatsManager 使用總結
Provides access to device usage history
and statistics. Usage data is aggregated into 匯總成 time intervals 時間間隔: days, weeks, months, and years.
A request for data in the middle of a time interval 間隔 will include that interval.
NOTE: Most methods on this API require the permission
android.permission.PACKAGE_USAGE_STATS
. However, declaring 聲明 the permission implies 暗示 intention 意圖 to use the API and the user of the device still needs to grant permission through theSettings
application. Methods which only return the information for thecalling package
do not require this permission. E.g.getAppStandbyBucket()
andqueryEventsForSelf()
.
應用使用統計信息
查詢應用使用統計信息,包括:應用的前台使用時長,應用首次啟動的時間,應用啟動次數,應用最近一次使用的時間等
queryUsageStats
List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime)
Gets application usage stats
for the given time range, aggregated by the specified interval.
The returned list will contain one or more UsageStats
objects for each package, with usage data that covers
at least the given time range 至少覆蓋給定的時間范圍.
Note: The begin and end times of the time range may be
expanded
to the nearest whole interval period.
queryAndAggregateUsageStats
Map<String, UsageStats> queryAndAggregateUsageStats(long beginTime, long endTime)
A convenience method that queries for all stats in the given range, merges the resulting data, and keys it by package name
.
其實就是逐個遍歷 queryUsageStats 返回的結果,按照包名進行整合,得出多條記錄的合並結果后再封裝起來。
UsageStats
Contains usage statistics
for an app package for a specific time range.
常用方法:
- long getFirstTimeStamp():Get the
beginning
of the time range this UsageStats represents, measured in milliseconds since the epoch紀元. 獲取此UsageStats表示的時間范圍的開始。 - long getLastTimeStamp():Get the
end
of the time range this UsageStats represents, ... - long getLastTimeUsed():Get the last time this package's
activity was used
, ... - long getTotalTimeInForeground():Get the total time this package
spent
in the foreground, ...
API 29 新增方法:
- long getLastTimeVisible():Get the last time this package's
activity is visible
in the UI, ... - long getLastTimeForegroundServiceUsed():Get the last time this package's
foreground service was used
, ... - long getTotalTimeVisible():Get the total time this package's activity is
visible
in the UI, ... - long getTotalTimeForegroundServiceUsed():Get the total time this package's
foreground services are started
, ...
時間間隔類型
- UsageStatsManager.INTERVAL_DAILY :天存儲級別的數據
- UsageStatsManager.INTERVAL_WEEKLY :星期存儲級別的數據
- UsageStatsManager.INTERVAL_MONTHLY :月存儲級別的數據
- UsageStatsManager.INTERVAL_YEARLY :年存儲級別的數據
- UsageStatsManager.INTERVAL_BEST :根據給定時間范圍選取最佳時間間隔類型
測試
測試代碼
private void testUsageStats(@NonNull Context context) {
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000 * 60 * 60 * 24 * 3; //最近3天
UsageStatsManager manager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
List<UsageStats> usageStatsList = manager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, beginTime, endTime);
for (UsageStats usageStats : usageStatsList) {
printUsageStatsInfo(usageStats);
}
System.out.println("--------------------------------------------------------------------------");
Map<String, UsageStats> map = manager.queryAndAggregateUsageStats(beginTime, endTime);
for (Map.Entry<String, UsageStats> entry : map.entrySet()) {
printUsageStatsInfo(entry.getValue());
}
}
private void printUsageStatsInfo(UsageStats usageStats) {
DateFormat format = new SimpleDateFormat("yyyy.MM.dd_HH:mm:ss", Locale.getDefault());
String packageName = usageStats.getPackageName();
String beginningTime = format.format(new Date(usageStats.getFirstTimeStamp()));
String endTime = format.format(new Date(usageStats.getLastTimeStamp()));
String lastUsedTime = format.format(new Date(usageStats.getLastTimeUsed())); //上次使用時間
long foregroundTime = usageStats.getTotalTimeInForeground() / 1000; //前台總共運行的時間
int appLaunchCount = 0; //應用被拉起啟動次數
int launchCount = 0;//應用前台啟動次數(包括自己啟動其他activity)
try {
appLaunchCount = (int) usageStats.getClass().getDeclaredMethod("getAppLaunchCount").invoke(usageStats);
launchCount = usageStats.getClass().getDeclaredField("mLaunchCount").getInt(usageStats);
} catch (Exception e) {
e.printStackTrace();
}
if (packageName.equals("com.tencent.mm") || packageName.equals("com.xiaomi.smarthome") || packageName.equals("com.eg.android.AlipayGphone")) {
Log.i("bqt", "| " + packageName + " | " + beginningTime + " | " + endTime + " | " + lastUsedTime + " | " + foregroundTime + " | " + appLaunchCount + " | " + launchCount + " |");
}
}
測試結果一
使用 UsageStatsManager.INTERVAL_BEST 的結果
表一:queryUsageStats
| packageName | beginningTime | endTime | lastUsedTime | 前台時長 | 拉起次數 | 切換次數 |
| :------------: | :------------: |
| com.tencent.mm | 2020.11.16_12:46:02 | 2020.11.20_00:13:56 | 2020.11.20_00:13:56 | 9890 | 96 | 68 |
| com.eg.android.AlipayGphone | 2020.11.16_12:46:02 | 2020.11.20_00:12:13 | 2020.11.18_13:06:54 | 27 | 3 | 0 |
表二:queryAndAggregateUsageStats
| packageName | beginningTime | endTime | lastUsedTime | 前台時長 | 拉起次數 | 切換次數 |
| :------------: | :------------: |
| com.tencent.mm | 2020.11.16_12:46:02 | 2020.11.20_00:13:56 | 2020.11.20_00:13:56 | 9890 | 96 | 68 |
| com.eg.android.AlipayGphone | 2020.11.16_12:46:02 | 2020.11.20_00:12:13 | 2020.11.18_13:06:54 | 27 | 3 | 0 |
使用 UsageStatsManager.INTERVAL_DAILY 的結果
表一:queryUsageStats
| packageName | beginningTime | endTime | lastUsedTime | 前台時長 | 拉起次數 | 切換次數 |
| :------------: | :------------: |
| com.tencent.mm | 2020.11.16_12:46:02 | 2020.11.17_12:46:02 | 2020.11.17_12:17:00 | 2930 | 33 | 0 |
| com.eg.android.AlipayGphone | 2020.11.16_12:46:02 | 2020.11.17_12:46:02 | 1970.01.01_07:59:57 | 0 | 0 | 0 |
| com.tencent.mm | 2020.11.17_12:46:38 | 2020.11.18_12:46:38 | 2020.11.18_12:46:33 | 2575 | 25 | 0 |
| com.eg.android.AlipayGphone | 2020.11.17_12:46:38 | 2020.11.18_12:46:38 | 2020.11.17_22:01:34 | 7 | 2 | 0 |
| com.tencent.mm | 2020.11.18_12:46:48 | 2020.11.19_12:46:48 | 2020.11.19_12:46:48 | 2113 | 21 | 0 |
| com.eg.android.AlipayGphone | 2020.11.18_12:46:48 | 2020.11.19_12:46:48 | 2020.11.18_13:06:54 | 19 | 1 | 0 |
| com.tencent.mm | 2020.11.19_12:46:55 | 2020.11.20_00:13:56 | 2020.11.20_00:13:56 | 2270 | 17 | 68 |
表二:queryAndAggregateUsageStats
| packageName | beginningTime | endTime | lastUsedTime | 前台時長 | 拉起次數 | 切換次數 |
| :------------: | :------------: |
| com.tencent.mm | 2020.11.16_12:46:02 | 2020.11.20_00:13:56 | 2020.11.20_00:13:56 | 9890 | 96 | 68 |
| com.eg.android.AlipayGphone | 2020.11.16_12:46:02 | 2020.11.20_00:12:13 | 2020.11.18_13:06:54 | 27 | 3 | 0 |
測試結果二
表一:queryUsageStats
| packageName | beginningTime | endTime | lastUsedTime | 前台時長 | 拉起次數 | 切換次數 |
| :------------: | :------------: |
| com.tencent.mm | 2020.11.08_12:35:24 | 2020.11.09_12:35:24 | 2020.11.09_12:05:16 | 2000 | 19 | 0 |
| com.eg.android.AlipayGphone | 2020.11.08_12:35:24 | 2020.11.09_12:35:24 | 2020.11.09_11:43:58 | 17 | 4 | 0 |
| com.tencent.mm | 2020.11.09_12:36:01 | 2020.11.10_12:36:01 | 2020.11.10_10:12:31 | 3119 | 39 | 0 |
| com.xiaomi.smarthome | 2020.11.09_12:36:01 | 2020.11.10_12:36:01 | 2020.11.10_12:36:01 | 489 | 4 | 0 |
| com.eg.android.AlipayGphone | 2020.11.09_12:36:01 | 2020.11.10_12:36:01 | 2020.11.10_09:09:22 | 115 | 12 | 0 |
| com.tencent.mm | 2020.11.10_12:36:03 | 2020.11.11_12:36:03 | 2020.11.11_11:24:53 | 5374 | 65 | 0 |
| com.xiaomi.smarthome | 2020.11.10_12:36:03 | 2020.11.11_12:36:03 | 2020.11.10_21:46:02 | 5109 | 13 | 0 |
| com.eg.android.AlipayGphone | 2020.11.10_12:36:03 | 2020.11.11_12:36:03 | 2020.11.10_18:15:47 | 583 | 2 | 0 |
| com.tencent.mm | 2020.11.11_12:37:05 | 2020.11.12_01:16:07 | 2020.11.11_23:00:43 | 1009 | 24 | 81 |
| com.xiaomi.smarthome | 2020.11.11_12:37:05 | 2020.11.12_01:22:28 | 2020.11.12_01:22:28 | 53 | 4 | 23 |
| com.eg.android.AlipayGphone | 2020.11.11_12:37:05 | 2020.11.12_01:16:07 | 2020.11.11_22:29:44 | 9 | 2 | 4 |
表二:queryAndAggregateUsageStats
| packageName | beginningTime | endTime | lastUsedTime | 前台時長 | 拉起次數 | 切換次數 |
| :------------: | :------------: |
| com.tencent.mm | 2020.11.08_12:35:24 | 2020.11.12_01:16:07 | 2020.11.11_23:00:43 | 11503 | 147 | 81 |
| com.xiaomi.smarthome | 2020.11.09_12:36:01 | 2020.11.12_01:22:28 | 2020.11.12_01:22:28 | 5652 | 21 | 23 |
| com.eg.android.AlipayGphone | 2020.11.08_12:35:24 | 2020.11.12_01:16:07 | 2020.11.11_22:29:44 | 725 | 20 | 4 |
設備狀態事件統計
事件包括:鎖屏事件、切換前台事件、切換到后台事件、屏幕交互狀態事件、屏幕非交互狀態事件等
queryEventStats
List<EventStats> queryEventStats(int intervalType, long beginTime, long endTime) //API 28添加
Gets aggregated 匯總 event stats for the given time range
, aggregated by the specified interval.
The returned list will contain a EventStats object for each event type that is being aggregated and has data for an interval that is a subset of the time range given.
返回的列表將為每個正在匯總的事件類型包含一個EventStats對象,並具有間隔時間的數據,該間隔是給定時間范圍的子集。
EventStats
Contains usage statistics for an event type for a specific time range.
常用方法:
- void add(EventStats right):Add the statistics from the right EventStats to the left. The event type for both UsageStats objects must be the same. 系統服務調用的方法
- int getCount():Return the number of times that this event occurred over the interval.
- int getEventType():Return the type of event this is usage for. May be one of the event constants in
UsageEvents.Event
. - long getFirstTimeStamp():Get the beginning of the time range this EventStats represents, measured in milliseconds since the epoch.
- long getLastEventTime():Get the last time this event triggered, measured in milliseconds since the epoch.
- long getLastTimeStamp():Get the end of the time range this EventStats represents, measured in milliseconds since the epoch.
- long getTotalTime():Get the total time this event was active, measured in milliseconds.
涉及到的四種事件
- UsageEvents.Event.SCREEN_INTERACTIVE = 15:交互狀態。An event type denoting 表示 that the screen has gone in to an interactive 交互 state (turned on for full user interaction, not ambient display 環境顯示 or other non-interactive state). 表示屏幕已進入交互狀態的事件類型(為完全用戶交互而打開,而不是環境顯示或其他非交互狀態)
- UsageEvents.Event.SCREEN_NON_INTERACTIVE = 16:非交互狀態。An event type denoting that the screen has gone in to a non-interactive state (completely turned off or turned on only in a non-interactive state like ambient display). 表示屏幕已進入非交互狀態的事件類型(完全關閉或僅在非交互狀態(如環境顯示)中完全打開)。
- UsageEvents.Event.KEYGUARD_SHOWN = 17:鎖屏。An event type denoting that the screen's keyguard 鍵盤鎖 has been shown, whether or not the screen is off.指示屏幕的鍵盤鎖已經顯示,無論屏幕是否關閉。
- UsageEvents.Event.KEYGUARD_HIDDEN = 18:解鎖。An event type denoting that the screen's keyguard has been hidden. This typically happens when the user unlocks their phone after turning it on. 表示屏幕的鍵盤鎖已隱藏。 當用戶在打開手機后解鎖手機時,通常會發生這種情況。
測試代碼
private void testEventStats(@NonNull Context context) {
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000 * 60 * 60 * 24 * 3; //最近3天
UsageStatsManager manager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
List<EventStats> usageStatsList = manager.queryEventStats(UsageStatsManager.INTERVAL_BEST, beginTime, endTime);
for (EventStats eventStats : usageStatsList) {
printEventStatsInfo(eventStats);
}
}
private void printEventStatsInfo(EventStats eventStats) {
DateFormat format = new SimpleDateFormat("yyyy.MM.dd_HH:mm:ss", Locale.getDefault());
int count = eventStats.getCount();
int eventType = eventStats.getEventType();
String beginningTime = format.format(new Date(eventStats.getFirstTimeStamp()));
String endTime = format.format(new Date(eventStats.getLastTimeStamp()));
String lastEventTime = format.format(new Date(eventStats.getLastEventTime()));
long totalTime = eventStats.getTotalTime() / 1000;
Log.i("bqt", "| " + count + " | " + eventType + " | " + beginningTime + " | " + endTime + " | " + lastEventTime + " | " + totalTime + " | ");
}
測試結果
| count | eventType | beginningTime | endTime | lastEventTime | totalTime |
| :------------: | :------------: |
| 323 | 15 | 2020.11.16_12:46:02 | 2020.11.20_01:06:12 | 2020.11.20_00:59:34 | 112197 |
| 322 | 16 | 2020.11.16_12:46:02 | 2020.11.20_01:06:12 | 2020.11.20_00:35:25 | 185469 |
| 173 | 17 | 2020.11.16_12:46:02 | 2020.11.20_01:06:12 | 2020.11.20_00:35:25 | 191812 |
| 174 | 18 | 2020.11.16_12:46:02 | 2020.11.20_01:06:12 | 2020.11.20_00:59:34 | 105847 |
應用事件詳細信息
事件包括:切換到前台、切換到后台、時間切換(比如一天的開始結束)、Configuration改變等
queryEvents
UsageEvents queryEvents(long beginTime, long endTime)
UsageEvents queryEventsForSelf(long beginTime, long endTime) //僅返回調用包的事件信息,不需要權限
Query for events in the given time range. Events are only kept by the system for a few days.
UsageEvents
A result returned from UsageStatsManager.queryEvents(long, long)
from which to read UsageEvents.Event
objects.
- public boolean getNextEvent (UsageEvents.Event eventOut):Retrieve the next
UsageEvents.Event
from the collection and put the resulting data into eventOut. - public boolean hasNextEvent ():Returns whether or not there are more events to read using
getNextEvent(UsageEvents.Event)
.
UsageEvents.Event
An event representing a state change for a component.
通用方法:
- String getPackageName():The package name of the source of this event.
- int getEventType():The event type.
- long getTimeStamp():The time at which this event occurred, measured in milliseconds since the epoch.
- String getClassName():The class name of the source of this event. This may be
null
for certain events.
特殊方法:
- int getAppStandbyBucket():Returns the standby bucket of the app, if the event is of type
STANDBY_BUCKET_CHANGED
, otherwise returns0
. - Configuration getConfiguration():Returns a Configuration for this event if the event is of type
CONFIGURATION_CHANGE
, otherwise it returnsnull
. - String getShortcutId():Returns the ID of a ShortcutInfo for this event if the event is of type
SHORTCUT_INVOCATION
, otherwise it returnsnull
.
常見的幾種事件類型
- NONE = 0;
- MOVE_TO_FOREGROUND = 1; //前台,同 ACTIVITY_RESUMED(API 29新增)
- MOVE_TO_BACKGROUND = 2; //后台,同 ACTIVITY_PAUSED(API 29新增)
- ACTIVITY_STOPPED = 23; //不可見(API 29新增)
- END_OF_DAY = 3;
- CONTINUE_PREVIOUS_DAY = 4;
- CONFIGURATION_CHANGE = 5;
- SYSTEM_INTERACTION = 6;
- USER_INTERACTION = 7;
- SHORTCUT_INVOCATION = 8;
- DEVICE_SHUTDOWN = 26;
- DEVICE_STARTUP = 27;
StandbyBucket
測試代碼
private void testEvent(@NonNull Context context) {
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000 * 60 * 60 * 3; //最近3小時
UsageStatsManager manager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
UsageEvents usageEvents = manager.queryEventsForSelf(beginTime, endTime);
UsageEvents.Event eventOut;
while (usageEvents.hasNextEvent()) {
eventOut = new UsageEvents.Event();
usageEvents.getNextEvent(eventOut);
printEventInfo(eventOut);
}
}
private void printEventInfo(UsageEvents.Event event) {
DateFormat format = new SimpleDateFormat("yyyy.MM.dd_HH:mm:ss", Locale.getDefault());
String packageName = event.getPackageName();
String className = event.getClassName();
int eventType = event.getEventType();
int standbyBucket = event.getAppStandbyBucket();
String shortcutId = event.getShortcutId();
String time = format.format(new Date(event.getTimeStamp()));
Log.i("bqt", "| " + packageName + " | " + className + " | " + eventType + " | " + standbyBucket + " | " + shortcutId + " | " + time + " |");
}
測試結果
| packageName | className | eventType | standbyBucket | shortcutId | time |
| :------------: | :------------: |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_00:13:56 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_00:13:56 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_00:13:56 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_00:15:03 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 23 | 0 | null | 2020.11.20_00:15:04 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_00:15:26 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_00:15:28 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 23 | 0 | null | 2020.11.20_00:15:29 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_00:16:06 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_00:16:08 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 23 | 0 | null | 2020.11.20_00:16:08 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_00:16:13 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_00:24:42 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_00:24:42 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_00:35:25 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 23 | 0 | null | 2020.11.20_00:35:25 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_00:59:34 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 23 | 0 | null | 2020.11.20_01:06:09 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_01:06:11 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_01:06:11 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_01:06:12 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_01:15:50 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 23 | 0 | null | 2020.11.20_01:15:50 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_01:35:39 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_01:35:39 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_01:35:39 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_01:36:22 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_01:36:22 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 2 | 0 | null | 2020.11.20_01:37:08 |
| com.bqt.test.x | com.bqt.test.x.MainActivity | 1 | 0 | null | 2020.11.20_01:37:08 |
其他方法
List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime, long endTime)
Gets the hardware configurations the device was in for the given time range, aggregated by the specified interval. The results are ordered as in queryUsageStats(int, long, long)
.
配置信息包括:orientation、uimode、mcc、mnc、navigation、locale、keyboard等
int getAppStandbyBucket()
Returns the current standby bucket of the calling app. The system determines the standby state of the app based on app usage patterns. Standby buckets determine how much an app will be restricted from running background tasks such as jobs and alarms.
boolean isAppInactive(String packageName)
Returns whether the specified app is currently considered inactive
. This will be true
if the app hasn't been used directly or indirectly for a period of time defined by the system. This could be of the order of several hours or days.
Apps are not considered inactive when the device is charging.
獲取指定的應用程序當前是否為非活動狀態。無論我怎么測試,返回值都是false
!
如何獲取該權限
1、在manifest文件中聲明該權限
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
只有在清單文件中聲明了此權限,才能繼續后面的操作
2、跳到系統setting應用中打開相應開關,准許應用獲取數據
//public static final String ACTION_USAGE_ACCESS_SETTINGS = "android.settings.USAGE_ACCESS_SETTINGS";
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
3、判斷是否具有此權限
常規的判斷權限方式無法獲取到准確的 UsageStatsManager 權限是否被賦予,以下方法經驗證有效
@TargetApi(Build.VERSION_CODES.M)
public static boolean isGrantedUsagePremission(@NonNull Context context) {
boolean granted;
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName());
if (mode == AppOpsManager.MODE_DEFAULT) {
granted = (context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) == PackageManager.PERMISSION_GRANTED);
} else {
granted = (mode == AppOpsManager.MODE_ALLOWED);
}
return granted;
}
2020-04-23