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