Home | History | Annotate | Download | only in appusagestatistics
      1 /*
      2 * Copyright 2014 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 *     http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 package com.example.android.appusagestatistics;
     18 
     19 import android.app.usage.UsageStats;
     20 import android.app.usage.UsageStatsManager;
     21 import android.content.Intent;
     22 import android.content.pm.PackageManager;
     23 import android.graphics.drawable.Drawable;
     24 import android.os.Bundle;
     25 import android.provider.Settings;
     26 import android.support.v4.app.Fragment;
     27 import android.support.v7.widget.LinearLayoutManager;
     28 import android.support.v7.widget.RecyclerView;
     29 import android.util.Log;
     30 import android.view.LayoutInflater;
     31 import android.view.View;
     32 import android.view.ViewGroup;
     33 import android.widget.AdapterView;
     34 import android.widget.ArrayAdapter;
     35 import android.widget.Button;
     36 import android.widget.Spinner;
     37 import android.widget.SpinnerAdapter;
     38 import android.widget.Toast;
     39 
     40 import java.util.ArrayList;
     41 import java.util.Calendar;
     42 import java.util.Collections;
     43 import java.util.Comparator;
     44 import java.util.List;
     45 
     46 /**
     47  * Fragment that demonstrates how to use App Usage Statistics API.
     48  */
     49 public class AppUsageStatisticsFragment extends Fragment {
     50 
     51     private static final String TAG = AppUsageStatisticsFragment.class.getSimpleName();
     52 
     53     //VisibleForTesting for variables below
     54     UsageStatsManager mUsageStatsManager;
     55     UsageListAdapter mUsageListAdapter;
     56     RecyclerView mRecyclerView;
     57     RecyclerView.LayoutManager mLayoutManager;
     58     Button mOpenUsageSettingButton;
     59     Spinner mSpinner;
     60 
     61     /**
     62      * Use this factory method to create a new instance of
     63      * this fragment using the provided parameters.
     64      *
     65      * @return A new instance of fragment {@link AppUsageStatisticsFragment}.
     66      */
     67     public static AppUsageStatisticsFragment newInstance() {
     68         AppUsageStatisticsFragment fragment = new AppUsageStatisticsFragment();
     69         return fragment;
     70     }
     71 
     72     public AppUsageStatisticsFragment() {
     73         // Required empty public constructor
     74     }
     75 
     76     @Override
     77     public void onCreate(Bundle savedInstanceState) {
     78         super.onCreate(savedInstanceState);
     79 
     80         mUsageStatsManager = (UsageStatsManager) getActivity()
     81                 .getSystemService("usagestats"); //Context.USAGE_STATS_SERVICE
     82     }
     83 
     84     @Override
     85     public View onCreateView(LayoutInflater inflater, ViewGroup container,
     86             Bundle savedInstanceState) {
     87         return inflater.inflate(R.layout.fragment_app_usage_statistics, container, false);
     88     }
     89 
     90     @Override
     91     public void onViewCreated(View rootView, Bundle savedInstanceState) {
     92         super.onViewCreated(rootView, savedInstanceState);
     93 
     94         mLayoutManager = new LinearLayoutManager(getActivity());
     95         mUsageListAdapter = new UsageListAdapter();
     96         mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview_app_usage);
     97         mRecyclerView.setLayoutManager(mLayoutManager);
     98         mRecyclerView.scrollToPosition(0);
     99         mRecyclerView.setAdapter(mUsageListAdapter);
    100         mOpenUsageSettingButton = (Button) rootView.findViewById(R.id.button_open_usage_setting);
    101         mSpinner = (Spinner) rootView.findViewById(R.id.spinner_time_span);
    102         SpinnerAdapter spinnerAdapter = ArrayAdapter.createFromResource(getActivity(),
    103                 R.array.action_list, android.R.layout.simple_spinner_dropdown_item);
    104         mSpinner.setAdapter(spinnerAdapter);
    105         mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    106 
    107             String[] strings = getResources().getStringArray(R.array.action_list);
    108 
    109             @Override
    110             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    111                 StatsUsageInterval statsUsageInterval = StatsUsageInterval
    112                         .getValue(strings[position]);
    113                 if (statsUsageInterval != null) {
    114                     List<UsageStats> usageStatsList =
    115                             getUsageStatistics(statsUsageInterval.mInterval);
    116                     Collections.sort(usageStatsList, new LastTimeLaunchedComparatorDesc());
    117                     updateAppsList(usageStatsList);
    118                 }
    119             }
    120 
    121             @Override
    122             public void onNothingSelected(AdapterView<?> parent) {
    123             }
    124         });
    125     }
    126 
    127     /**
    128      * Returns the {@link #mRecyclerView} including the time span specified by the
    129      * intervalType argument.
    130      *
    131      * @param intervalType The time interval by which the stats are aggregated.
    132      *                     Corresponding to the value of {@link UsageStatsManager}.
    133      *                     E.g. {@link UsageStatsManager#INTERVAL_DAILY}, {@link
    134      *                     UsageStatsManager#INTERVAL_WEEKLY},
    135      *
    136      * @return A list of {@link android.app.usage.UsageStats}.
    137      */
    138     public List<UsageStats> getUsageStatistics(int intervalType) {
    139         // Get the app statistics since one year ago from the current time.
    140         Calendar cal = Calendar.getInstance();
    141         cal.add(Calendar.YEAR, -1);
    142 
    143         List<UsageStats> queryUsageStats = mUsageStatsManager
    144                 .queryUsageStats(intervalType, cal.getTimeInMillis(),
    145                         System.currentTimeMillis());
    146 
    147         if (queryUsageStats.size() == 0) {
    148             Log.i(TAG, "The user may not allow the access to apps usage. ");
    149             Toast.makeText(getActivity(),
    150                     getString(R.string.explanation_access_to_appusage_is_not_enabled),
    151                     Toast.LENGTH_LONG).show();
    152             mOpenUsageSettingButton.setVisibility(View.VISIBLE);
    153             mOpenUsageSettingButton.setOnClickListener(new View.OnClickListener() {
    154                 @Override
    155                 public void onClick(View v) {
    156                     startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
    157                 }
    158             });
    159         }
    160         return queryUsageStats;
    161     }
    162 
    163     /**
    164      * Updates the {@link #mRecyclerView} with the list of {@link UsageStats} passed as an argument.
    165      *
    166      * @param usageStatsList A list of {@link UsageStats} from which update the
    167      *                       {@link #mRecyclerView}.
    168      */
    169     //VisibleForTesting
    170     void updateAppsList(List<UsageStats> usageStatsList) {
    171         List<CustomUsageStats> customUsageStatsList = new ArrayList<>();
    172         for (int i = 0; i < usageStatsList.size(); i++) {
    173             CustomUsageStats customUsageStats = new CustomUsageStats();
    174             customUsageStats.usageStats = usageStatsList.get(i);
    175             try {
    176                 Drawable appIcon = getActivity().getPackageManager()
    177                         .getApplicationIcon(customUsageStats.usageStats.getPackageName());
    178                 customUsageStats.appIcon = appIcon;
    179             } catch (PackageManager.NameNotFoundException e) {
    180                 Log.w(TAG, String.format("App Icon is not found for %s",
    181                         customUsageStats.usageStats.getPackageName()));
    182                 customUsageStats.appIcon = getActivity()
    183                         .getDrawable(R.drawable.ic_default_app_launcher);
    184             }
    185             customUsageStatsList.add(customUsageStats);
    186         }
    187         mUsageListAdapter.setCustomUsageStatsList(customUsageStatsList);
    188         mUsageListAdapter.notifyDataSetChanged();
    189         mRecyclerView.scrollToPosition(0);
    190     }
    191 
    192     /**
    193      * The {@link Comparator} to sort a collection of {@link UsageStats} sorted by the timestamp
    194      * last time the app was used in the descendant order.
    195      */
    196     private static class LastTimeLaunchedComparatorDesc implements Comparator<UsageStats> {
    197 
    198         @Override
    199         public int compare(UsageStats left, UsageStats right) {
    200             return (int) (right.getLastTimeUsed() - left.getLastTimeUsed());
    201         }
    202     }
    203 
    204     /**
    205      * Enum represents the intervals for {@link android.app.usage.UsageStatsManager} so that
    206      * values for intervals can be found by a String representation.
    207      *
    208      */
    209     //VisibleForTesting
    210     static enum StatsUsageInterval {
    211         DAILY("Daily", UsageStatsManager.INTERVAL_DAILY),
    212         WEEKLY("Weekly", UsageStatsManager.INTERVAL_WEEKLY),
    213         MONTHLY("Monthly", UsageStatsManager.INTERVAL_MONTHLY),
    214         YEARLY("Yearly", UsageStatsManager.INTERVAL_YEARLY);
    215 
    216         private int mInterval;
    217         private String mStringRepresentation;
    218 
    219         StatsUsageInterval(String stringRepresentation, int interval) {
    220             mStringRepresentation = stringRepresentation;
    221             mInterval = interval;
    222         }
    223 
    224         static StatsUsageInterval getValue(String stringRepresentation) {
    225             for (StatsUsageInterval statsUsageInterval : values()) {
    226                 if (statsUsageInterval.mStringRepresentation.equals(stringRepresentation)) {
    227                     return statsUsageInterval;
    228                 }
    229             }
    230             return null;
    231         }
    232     }
    233 }
    234