| /* |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.example.android.appusagestatistics; |
| |
| import android.app.usage.UsageStats; |
| import android.app.usage.UsageStatsManager; |
| import android.content.Intent; |
| import android.content.pm.PackageManager; |
| import android.graphics.drawable.Drawable; |
| import android.os.Bundle; |
| import android.provider.Settings; |
| import android.support.v4.app.Fragment; |
| import android.support.v7.widget.LinearLayoutManager; |
| import android.support.v7.widget.RecyclerView; |
| import android.util.Log; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.AdapterView; |
| import android.widget.ArrayAdapter; |
| import android.widget.Button; |
| import android.widget.Spinner; |
| import android.widget.SpinnerAdapter; |
| import android.widget.Toast; |
| |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| |
| /** |
| * Fragment that demonstrates how to use App Usage Statistics API. |
| */ |
| public class AppUsageStatisticsFragment extends Fragment { |
| |
| private static final String TAG = AppUsageStatisticsFragment.class.getSimpleName(); |
| |
| //VisibleForTesting for variables below |
| UsageStatsManager mUsageStatsManager; |
| UsageListAdapter mUsageListAdapter; |
| RecyclerView mRecyclerView; |
| RecyclerView.LayoutManager mLayoutManager; |
| Button mOpenUsageSettingButton; |
| Spinner mSpinner; |
| |
| /** |
| * Use this factory method to create a new instance of |
| * this fragment using the provided parameters. |
| * |
| * @return A new instance of fragment {@link AppUsageStatisticsFragment}. |
| */ |
| public static AppUsageStatisticsFragment newInstance() { |
| AppUsageStatisticsFragment fragment = new AppUsageStatisticsFragment(); |
| return fragment; |
| } |
| |
| public AppUsageStatisticsFragment() { |
| // Required empty public constructor |
| } |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| mUsageStatsManager = (UsageStatsManager) getActivity() |
| .getSystemService("usagestats"); //Context.USAGE_STATS_SERVICE |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| return inflater.inflate(R.layout.fragment_app_usage_statistics, container, false); |
| } |
| |
| @Override |
| public void onViewCreated(View rootView, Bundle savedInstanceState) { |
| super.onViewCreated(rootView, savedInstanceState); |
| |
| mLayoutManager = new LinearLayoutManager(getActivity()); |
| mUsageListAdapter = new UsageListAdapter(); |
| mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview_app_usage); |
| mRecyclerView.setLayoutManager(mLayoutManager); |
| mRecyclerView.scrollToPosition(0); |
| mRecyclerView.setAdapter(mUsageListAdapter); |
| mOpenUsageSettingButton = (Button) rootView.findViewById(R.id.button_open_usage_setting); |
| mSpinner = (Spinner) rootView.findViewById(R.id.spinner_time_span); |
| SpinnerAdapter spinnerAdapter = ArrayAdapter.createFromResource(getActivity(), |
| R.array.action_list, android.R.layout.simple_spinner_dropdown_item); |
| mSpinner.setAdapter(spinnerAdapter); |
| mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { |
| |
| String[] strings = getResources().getStringArray(R.array.action_list); |
| |
| @Override |
| public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { |
| StatsUsageInterval statsUsageInterval = StatsUsageInterval |
| .getValue(strings[position]); |
| if (statsUsageInterval != null) { |
| List<UsageStats> usageStatsList = |
| getUsageStatistics(statsUsageInterval.mInterval); |
| Collections.sort(usageStatsList, new LastTimeLaunchedComparatorDesc()); |
| updateAppsList(usageStatsList); |
| } |
| } |
| |
| @Override |
| public void onNothingSelected(AdapterView<?> parent) { |
| } |
| }); |
| } |
| |
| /** |
| * Returns the {@link #mRecyclerView} including the time span specified by the |
| * intervalType argument. |
| * |
| * @param intervalType The time interval by which the stats are aggregated. |
| * Corresponding to the value of {@link UsageStatsManager}. |
| * E.g. {@link UsageStatsManager#INTERVAL_DAILY}, {@link |
| * UsageStatsManager#INTERVAL_WEEKLY}, |
| * |
| * @return A list of {@link android.app.usage.UsageStats}. |
| */ |
| public List<UsageStats> getUsageStatistics(int intervalType) { |
| // Get the app statistics since one year ago from the current time. |
| Calendar cal = Calendar.getInstance(); |
| cal.add(Calendar.YEAR, -1); |
| |
| List<UsageStats> queryUsageStats = mUsageStatsManager |
| .queryUsageStats(intervalType, cal.getTimeInMillis(), |
| System.currentTimeMillis()); |
| |
| if (queryUsageStats.size() == 0) { |
| Log.i(TAG, "The user may not allow the access to apps usage. "); |
| Toast.makeText(getActivity(), |
| getString(R.string.explanation_access_to_appusage_is_not_enabled), |
| Toast.LENGTH_LONG).show(); |
| mOpenUsageSettingButton.setVisibility(View.VISIBLE); |
| mOpenUsageSettingButton.setOnClickListener(new View.OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); |
| } |
| }); |
| } |
| return queryUsageStats; |
| } |
| |
| /** |
| * Updates the {@link #mRecyclerView} with the list of {@link UsageStats} passed as an argument. |
| * |
| * @param usageStatsList A list of {@link UsageStats} from which update the |
| * {@link #mRecyclerView}. |
| */ |
| //VisibleForTesting |
| void updateAppsList(List<UsageStats> usageStatsList) { |
| List<CustomUsageStats> customUsageStatsList = new ArrayList<>(); |
| for (int i = 0; i < usageStatsList.size(); i++) { |
| CustomUsageStats customUsageStats = new CustomUsageStats(); |
| customUsageStats.usageStats = usageStatsList.get(i); |
| try { |
| Drawable appIcon = getActivity().getPackageManager() |
| .getApplicationIcon(customUsageStats.usageStats.getPackageName()); |
| customUsageStats.appIcon = appIcon; |
| } catch (PackageManager.NameNotFoundException e) { |
| Log.w(TAG, String.format("App Icon is not found for %s", |
| customUsageStats.usageStats.getPackageName())); |
| customUsageStats.appIcon = getActivity() |
| .getDrawable(R.drawable.ic_default_app_launcher); |
| } |
| customUsageStatsList.add(customUsageStats); |
| } |
| mUsageListAdapter.setCustomUsageStatsList(customUsageStatsList); |
| mUsageListAdapter.notifyDataSetChanged(); |
| mRecyclerView.scrollToPosition(0); |
| } |
| |
| /** |
| * The {@link Comparator} to sort a collection of {@link UsageStats} sorted by the timestamp |
| * last time the app was used in the descendant order. |
| */ |
| private static class LastTimeLaunchedComparatorDesc implements Comparator<UsageStats> { |
| |
| @Override |
| public int compare(UsageStats left, UsageStats right) { |
| return (int) (right.getLastTimeUsed() - left.getLastTimeUsed()); |
| } |
| } |
| |
| /** |
| * Enum represents the intervals for {@link android.app.usage.UsageStatsManager} so that |
| * values for intervals can be found by a String representation. |
| * |
| */ |
| //VisibleForTesting |
| static enum StatsUsageInterval { |
| DAILY("Daily", UsageStatsManager.INTERVAL_DAILY), |
| WEEKLY("Weekly", UsageStatsManager.INTERVAL_WEEKLY), |
| MONTHLY("Monthly", UsageStatsManager.INTERVAL_MONTHLY), |
| YEARLY("Yearly", UsageStatsManager.INTERVAL_YEARLY); |
| |
| private int mInterval; |
| private String mStringRepresentation; |
| |
| StatsUsageInterval(String stringRepresentation, int interval) { |
| mStringRepresentation = stringRepresentation; |
| mInterval = interval; |
| } |
| |
| static StatsUsageInterval getValue(String stringRepresentation) { |
| for (StatsUsageInterval statsUsageInterval : values()) { |
| if (statsUsageInterval.mStringRepresentation.equals(stringRepresentation)) { |
| return statsUsageInterval; |
| } |
| } |
| return null; |
| } |
| } |
| } |