Android 使用記錄訪問權限

  • 本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家發(fā)布

什么是使用記錄訪問權限呢委乌?這是在Android5.0(Api level 21)新添加的,通過該權限我們可以查看設備上其它應用使用情況的統計信息等诺舔。

如何使用該權限呢玉锌?
首先在manifest中添加:

<uses-permission
        android:name="android.permission.PACKAGE_USAGE_STATS"
        tools:ignore="ProtectedPermissions" />

由于該權限默認只授予系統應用技羔,所以添加了ignore屬性蚀同。
然后通過如下代碼進而手動打開權限:

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivityForResult(intent);

當然只要我們在manifest中進行了權限配置,也可以通過設置->安全->有權查看使用情況的應用來打開權限:


到此我們的應用就擁有了該權限读跷。那么有了這個權限到底能做什么呢梗搅?繼續(xù)往下看......

前段時間和同事聊到了一個叫我要當學霸的app,里邊有個學習監(jiān)督的功能效览,就需要使用記錄訪問權限无切,當打開權限后,除了自己和桌面外丐枉,其它app都不能正常使用哆键,點擊其它app時會直接退到后臺并彈出一個提示頁面。不妨我們來模擬下這個功能瘦锹。
在這之前我們首先看一個類UsageStatsManager

public final class UsageStatsManager {
    public static final int INTERVAL_BEST = 4; //根據提供的開始籍嘹、結束時間決定時間間隔
    public static final int INTERVAL_DAILY = 0; //以天為時間間隔(最長7天)
    public static final int INTERVAL_MONTHLY = 2; //以月為時間間隔(最長6個月)
    public static final int INTERVAL_WEEKLY = 1; //以周為時間間隔(最長4個星期)
    public static final int INTERVAL_YEARLY = 3; //以年為時間間隔(最長2年)

    UsageStatsManager() {
        throw new RuntimeException("Stub!");
    }

    public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) {
        throw new RuntimeException("Stub!");
    }

    public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime, long endTime) {
        throw new RuntimeException("Stub!");
    }

    public UsageEvents queryEvents(long beginTime, long endTime) {
        throw new RuntimeException("Stub!");
    }

    public Map<String, UsageStats> queryAndAggregateUsageStats(long beginTime, long endTime) {
        throw new RuntimeException("Stub!");
    }

    public boolean isAppInactive(String packageName) {
        throw new RuntimeException("Stub!");
    }
}

可以看到該類提供了五種時間間隔類型,這里我們比較關注queryUsageStats()方法弯院,通過該方法我們可以得到一段時間內 其它應用的使用情況辱士。
我們實現思路是這樣的,通過UsageStatsManager類獲得2秒內手機app的使用數據抽兆,找到時間最近的一個识补,如果不是我們自己的app或桌面則模擬home鍵點擊,同時彈出一個提示頁面辫红,具體的代碼如下:

private void getTopApp() {
        UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);//usagestats
        long time = System.currentTimeMillis();
        List<UsageStats> usageStatsList = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, time - 2000, time);

        if (usageStatsList != null && !usageStatsList.isEmpty()) {
            SortedMap<Long, UsageStats> usageStatsMap = new TreeMap<>();
            for (UsageStats usageStats : usageStatsList) {
                usageStatsMap.put(usageStats.getLastTimeUsed(), usageStats);
            }
            if (!usageStatsMap.isEmpty()) {
                String topPackageName = usageStatsMap.get(usageStatsMap.lastKey()).getPackageName();

                if (getLauncherPackageName(mContext).equals(topPackageName) || "com.othershe.test".equals(topPackageName)) {
                    return;
                }

                Log.e("TopPackage Name", topPackageName);

                //模擬home鍵點擊
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addCategory(Intent.CATEGORY_HOME);
                startActivity(intent);

                //啟動提示頁面
                Intent intent1 = new Intent(mContext, TipActivity.class);
                intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent1);
            }
        }
    }

因為時間周期是2秒凭涂,所以這里我們采用INTERVAL_BEST作為時間間隔。其中的UsageStats對象對應一個查詢到的app數據贴妻,主要包含以下信息:


getTopApp()是我們的核心方法切油,當然我們需要開啟一個服務,然后在服務中每隔500毫秒執(zhí)行一次上邊的方法名惩,這樣就能起到不斷檢測的作用:

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        mTimer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                getTopApp();
            }
        };

        mTimer.schedule(task, 1000, 500);
        return super.onStartCommand(intent, flags, startId);
    }

打開權限澎胡、啟動服務,可以看到實際的運行效果如下娩鹉,基本符合我們的預期攻谁。



類似的道理,我們也可以判斷摸個app是否在前臺運行弯予。

上邊我們使用了**INTERVAL_BEST **時間間隔類型戚宦,還可以使用其它4中,例如使用INTERVAL_YEARLY:

private void getHistoryApps() {
        Calendar calendar = Calendar.getInstance();
        long endTime = calendar.getTimeInMillis();
        calendar.add(Calendar.YEAR, -1);
        long startTime = calendar.getTimeInMillis();

        UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
        List<UsageStats> usageStatsList = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, startTime, endTime);

        if (usageStatsList != null && !usageStatsList.isEmpty()) {
            HashSet<String> set = new HashSet<>();
            for (UsageStats usageStats : usageStatsList) {
                set.add(usageStats.getPackageName());
            }

            if (!set.isEmpty()) {
                Log.e("size", set.size() + "");
            }
        }
    }

上邊的代碼我們最終獲得了過去一年手機上使用過的app的包名集合(其中包括系統級別的):

拿到這些包名可以做什么呢锈嫩?
其實對于網賺類型的應用有這樣一種業(yè)務場景受楼,就是用戶通過下載app來做任務進而賺取收益垦搬,但是如果當前設備通過其它網賺應用已經下載過某個app,然后卸載了艳汽,再通過你的網賺應用下載猴贰。如果你不知道用戶之前安裝過該app,就需要給用戶結算相應的收益河狐,但是你的上游渠道是不會給你結算的米绕,因為這屬于同一設備上的重復下載,這樣對公司而言就是虧損的馋艺。

有了歷史包名信息义郑,我們就可以判斷用戶在一定的時間周期內是否安裝過對應的app,進而采取相應的策略丈钙,這樣可以在一定程度降低損失。當然有個前提交汤,你要友好的引導用戶開啟權限雏赦。

先到這里吧,更多的用法還有待進一步探究芙扎。

demo下載

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末星岗,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子戒洼,更是在濱河造成了極大的恐慌俏橘,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圈浇,死亡現場離奇詭異寥掐,居然都是意外死亡,警方通過查閱死者的電腦和手機磷蜀,發(fā)現死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門召耘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人褐隆,你說我怎么就攤上這事污它。” “怎么了庶弃?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵衫贬,是天一觀的道長。 經常有香客問我歇攻,道長固惯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任掉伏,我火速辦了婚禮缝呕,結果婚禮上澳窑,老公的妹妹穿的比我還像新娘。我一直安慰自己供常,他們只是感情好摊聋,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著栈暇,像睡著了一般麻裁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上源祈,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天煎源,我揣著相機與錄音,去河邊找鬼香缺。 笑死手销,一個胖子當著我的面吹牛,可吹牛的內容都是我干的图张。 我是一名探鬼主播锋拖,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祸轮!你這毒婦竟也來了兽埃?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤适袜,失蹤者是張志新(化名)和其女友劉穎柄错,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體苦酱,經...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡售貌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了躏啰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趁矾。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖给僵,靈堂內的尸體忽然破棺而出毫捣,到底是詐尸還是另有隱情,我是刑警寧澤帝际,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布蔓同,位于F島的核電站,受9級特大地震影響蹲诀,放射性物質發(fā)生泄漏斑粱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一脯爪、第九天 我趴在偏房一處隱蔽的房頂上張望则北。 院中可真熱鬧矿微,春花似錦、人聲如沸尚揣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽快骗。三九已至娜庇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間方篮,已是汗流浹背名秀。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留藕溅,地道東北人匕得。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像巾表,于是被迫代替她去往敵國和親耗跛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內容

  • 作者簡介 原創(chuàng)微信公眾號郭霖 WeChat ID: guolin_blog 大家早上好攒发,新的一周開始啦! 本篇是O...
    木木00閱讀 4,687評論 1 5
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,290評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理晋南,服務發(fā)現惠猿,斷路器,智...
    卡卡羅2017閱讀 134,702評論 18 139
  • 發(fā)現 關注 消息 iOS 第三方庫负间、插件偶妖、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,120評論 4 61
  • 這個世界有人喜歡旅行,當然也會有人不喜歡政溃。 我是喜歡的趾访,至少到目前為止是這樣的,所以我老是希望自己一有空就在路上董虱。...
    清風伏筆閱讀 455評論 0 4