androidandroid-tvusagestatsmanager

AndroidTV: UsageStatsManager not returning details for apps results after Reboot


I am working on a Android TV app (system app) where i am trying to use UsageStatsManager to get recently used app list.
By following approach ,

UsageStatsManager usm = getUsageStatsManager(context);
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.YEAR, -1)
final List<UsageStats> usageStatsList = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, startTime, endTime);

Above approach gives right usage data, but after a device reboot it wont give previously used app usage data, until that app has been opened again after reboot .

But same code works fine (after reboot) in an android Phone .

I also tried this sample App from Github in Android TV which also fails to give details after reboot in Android TV (but works in Mobile , both OS version 8) .

Any reason why it's failing to get App usage data for Android TV ?

TIA


Solution

  • @Nainal here is a workaround.

    As we had experienced that after a device power cycle , Android Tv box won’t return the usage stats of installed application. Here is a workaround I followed .

    Here is the code :

    private void SortByRecentlyUsed(final List<ResolveInfo> info, final Context context){
    
        /*load LastTimeUsedMap from pref*/
        lastTimeUsedMap = loadLastTimeUsedMap(context);
    
        UsageStatsManager usm = getUsageStatsManager(context);
        Calendar calendar = Calendar.getInstance();
        long endTime = calendar.getTimeInMillis();
        calendar.add(Calendar.MONTH, -1);
        long startTime = calendar.getTimeInMillis();
    
        final List<UsageStats> usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_BEST, startTime, endTime);
    
        /*Update AppRecentTimeUsedMap with latest data from UsageStatsManager*/
        updateAppRecentTimeUsedMap(usageStatsList,info);
    
        class RecentUseComparator implements Comparator<ResolveInfo> {
            @Override
            public int compare(ResolveInfo lhs, ResolveInfo rhs) {
                String lhsPackageName=lhs.activityInfo.applicationInfo.packageName;
                String rhsPackageName=rhs.activityInfo.applicationInfo.packageName;
                long lhsUsedTime = getLastUsedTime(lhsPackageName);
                long rhsUsedTime = getLastUsedTime(rhsPackageName);
                return (lhsUsedTime > rhsUsedTime) ? -1 : (lhsUsedTime == rhsUsedTime) ? 0 : 1;
            }
    
            private long getLastUsedTime(String packageDetails) {
                long appRecentUsedtime = -1;
                if (appRecentTimeUsedMap.containsKey(packageDetails)) {
                    appRecentUsedtime = appRecentTimeUsedMap.get(packageDetails);
                    }
                return appRecentUsedtime;
            }
        }
        RecentUseComparator mRecentComp = new RecentUseComparator();
        Collections.sort(info, mRecentComp);
        /*Save the updated  LastTimeUsedMap in pref*/
        saveLastTimeUsedMap(lastTimeUsedMap, context);
    
    }
    
    private void updateAppRecentTimeUsedMap(List<UsageStats> usageStatsList,List<ResolveInfo> info){
    
        String packageName=null;
        if (usageStatsList != null) {
            for (ResolveInfo Rinfo : info) {
                packageName = Rinfo.activityInfo.applicationInfo.packageName;
                boolean added = false;
                for (UsageStats usageStats : usageStatsList) {
                    if (packageName.equalsIgnoreCase(usageStats.getPackageName())) {
                        appRecentTimeUsedMap.put(usageStats.getPackageName(), usageStats.getLastTimeUsed());
                        updateLastTimeUsedMap(usageStats.getPackageName(), usageStats.getLastTimeUsed());
                        added=true;
                    }
                }
                if (!added && lastTimeUsedMap.containsKey(packageName)) {
                    appRecentTimeUsedMap.put(packageName, lastTimeUsedMap.get(packageName));
                }
            }
    
        }
    
    }
    
    private void updateLastTimeUsedMap(String packageName,Long timeStamp){
        lastTimeUsedMap.put(packageName, timeStamp);
    }
    
    /**
     * Return Map containing Package name and recent used time from preference
     *
     * @param context
     * @return Map<String,Long>
     */
    private Map<String,Long> loadLastTimeUsedMap(Context context){
        Map<String,Long> outputMap = new HashMap<String,Long>();
        SharedPreferences pSharedPref = context.getSharedPreferences(LAST_TIME_USED_PREFS, Context.MODE_PRIVATE);
        try{
            if (pSharedPref != null){
                String jsonString = pSharedPref.getString(LAST_TIME_USED_MAP, (new JSONObject()).toString());
                JSONObject jsonObject = new JSONObject(jsonString);
                Iterator<String> keysItr = jsonObject.keys();
                while(keysItr.hasNext()) {
                    String key = keysItr.next();
                    Long value = jsonObject.getLong(key);
                    outputMap.put(key, value);
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return outputMap;
    }
    /**
     * Save the updated map containing Package name and recent used time in preference
     *
     * @param inputMap
     * @param context
     */
    private void saveLastTimeUsedMap(Map<String,Long> inputMap, Context context){
        final SharedPreferences sharedPreferences = context.getSharedPreferences(LAST_TIME_USED_PREFS,Context.MODE_PRIVATE);
        if (sharedPreferences != null){
            JSONObject jsonObject = new JSONObject(inputMap);
            String jsonString = jsonObject.toString();
            final SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.remove(LAST_TIME_USED_MAP).commit();
            editor.putString(LAST_TIME_USED_MAP, jsonString);
            editor.commit();
        }
    }