2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.android.settingslib.drawer;
18 import android.annotation.LayoutRes;
19 import android.annotation.Nullable;
20 import android.app.Activity;
21 import android.content.ActivityNotFoundException;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.pm.PackageManager;
28 import android.content.res.TypedArray;
29 import android.os.AsyncTask;
30 import android.os.Bundle;
31 import android.provider.Settings;
32 import android.support.v4.widget.DrawerLayout;
33 import android.util.ArraySet;
34 import android.util.Log;
35 import android.util.Pair;
36 import android.view.Gravity;
37 import android.view.LayoutInflater;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.view.ViewGroup;
41 import android.view.Window;
42 import android.view.WindowManager.LayoutParams;
43 import android.widget.AdapterView;
44 import android.widget.ListView;
45 import android.widget.Toolbar;
46 import com.android.settingslib.R;
47 import com.android.settingslib.applications.InterestingConfigChanges;
49 import java.util.ArrayList;
50 import java.util.HashMap;
51 import java.util.List;
53 public class SettingsDrawerActivity extends Activity {
55 protected static final boolean DEBUG_TIMING = false;
56 private static final String TAG = "SettingsDrawerActivity";
58 public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
60 private static List<DashboardCategory> sDashboardCategories;
61 private static HashMap<Pair<String, String>, Tile> sTileCache;
62 // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
64 private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>();
65 private static InterestingConfigChanges sConfigTracker;
67 private final PackageReceiver mPackageReceiver = new PackageReceiver();
68 private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
70 private SettingsDrawerAdapter mDrawerAdapter;
71 private DrawerLayout mDrawerLayout;
72 private boolean mShowingMenu;
75 protected void onCreate(@Nullable Bundle savedInstanceState) {
76 super.onCreate(savedInstanceState);
78 long startTime = System.currentTimeMillis();
80 TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
81 if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
82 getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
83 getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
84 requestWindowFeature(Window.FEATURE_NO_TITLE);
86 super.setContentView(R.layout.settings_with_drawer);
87 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
88 if (mDrawerLayout == null) {
91 Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
92 if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
93 toolbar.setVisibility(View.GONE);
94 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
98 getDashboardCategories();
99 setActionBar(toolbar);
100 mDrawerAdapter = new SettingsDrawerAdapter(this);
101 ListView listView = (ListView) findViewById(R.id.left_drawer);
102 listView.setAdapter(mDrawerAdapter);
103 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
104 public void onItemClick(android.widget.AdapterView<?> parent, View view, int position,
106 onTileClicked(mDrawerAdapter.getTile(position));
109 if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
114 public boolean onOptionsItemSelected(MenuItem item) {
115 if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
116 && mDrawerAdapter.getCount() != 0) {
120 return super.onOptionsItemSelected(item);
124 protected void onResume() {
127 if (mDrawerLayout != null) {
128 final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
129 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
130 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
131 filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
132 filter.addDataScheme("package");
133 registerReceiver(mPackageReceiver, filter);
135 new CategoriesUpdater().execute();
137 if (getIntent() != null && getIntent().getBooleanExtra(EXTRA_SHOW_MENU, false)) {
143 protected void onPause() {
144 if (mDrawerLayout != null) {
145 unregisterReceiver(mPackageReceiver);
151 public void addCategoryListener(CategoryListener listener) {
152 mCategoryListeners.add(listener);
155 public void remCategoryListener(CategoryListener listener) {
156 mCategoryListeners.remove(listener);
159 public void setIsDrawerPresent(boolean isPresent) {
161 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
164 if (mDrawerLayout != null) {
165 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
166 mDrawerLayout = null;
171 public void openDrawer() {
172 if (mDrawerLayout != null) {
173 mDrawerLayout.openDrawer(Gravity.START);
177 public void closeDrawer() {
178 if (mDrawerLayout != null) {
179 mDrawerLayout.closeDrawers();
184 public void setContentView(@LayoutRes int layoutResID) {
185 final ViewGroup parent = (ViewGroup) findViewById(R.id.content_frame);
186 if (parent != null) {
187 parent.removeAllViews();
189 LayoutInflater.from(this).inflate(layoutResID, parent);
193 public void setContentView(View view) {
194 ((ViewGroup) findViewById(R.id.content_frame)).addView(view);
198 public void setContentView(View view, ViewGroup.LayoutParams params) {
199 ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
202 public void updateDrawer() {
203 if (mDrawerLayout == null) {
206 // TODO: Do this in the background with some loading.
207 mDrawerAdapter.updateCategories();
208 if (mDrawerAdapter.getCount() != 0) {
209 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
211 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
215 public void showMenuIcon() {
217 getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
218 getActionBar().setDisplayHomeAsUpEnabled(true);
221 public List<DashboardCategory> getDashboardCategories() {
222 if (sDashboardCategories == null) {
223 sTileCache = new HashMap<>();
224 sConfigTracker = new InterestingConfigChanges();
225 // Apply initial current config.
226 sConfigTracker.applyNewConfig(getResources());
227 sDashboardCategories = TileUtils.getCategories(this, sTileCache);
229 return sDashboardCategories;
232 protected void onCategoriesChanged() {
234 final int N = mCategoryListeners.size();
235 for (int i = 0; i < N; i++) {
236 mCategoryListeners.get(i).onCategoriesChanged();
240 public boolean openTile(Tile tile) {
243 startActivity(new Intent(Settings.ACTION_SETTINGS).addFlags(
244 Intent.FLAG_ACTIVITY_CLEAR_TASK));
248 int numUserHandles = tile.userHandle.size();
249 if (numUserHandles > 1) {
250 ProfileSelectDialog.show(getFragmentManager(), tile);
252 } else if (numUserHandles == 1) {
253 // Show menu on top level items.
254 tile.intent.putExtra(EXTRA_SHOW_MENU, true);
255 tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
256 startActivityAsUser(tile.intent, tile.userHandle.get(0));
258 // Show menu on top level items.
259 tile.intent.putExtra(EXTRA_SHOW_MENU, true);
260 tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
261 startActivity(tile.intent);
263 } catch (ActivityNotFoundException e) {
264 Log.w(TAG, "Couldn't find tile " + tile.intent, e);
269 protected void onTileClicked(Tile tile) {
270 if (openTile(tile)) {
275 public void onProfileTileOpen() {
279 public void setTileEnabled(ComponentName component, boolean enabled) {
280 PackageManager pm = getPackageManager();
281 int state = pm.getComponentEnabledSetting(component);
282 boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
283 if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
285 sTileBlacklist.remove(component);
287 sTileBlacklist.add(component);
289 pm.setComponentEnabledSetting(component, enabled
290 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
291 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
292 PackageManager.DONT_KILL_APP);
293 new CategoriesUpdater().execute();
297 public interface CategoryListener {
298 void onCategoriesChanged();
301 private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
303 protected List<DashboardCategory> doInBackground(Void... params) {
304 if (sConfigTracker.applyNewConfig(getResources())) {
307 return TileUtils.getCategories(SettingsDrawerActivity.this, sTileCache);
311 protected void onPreExecute() {
312 if (sConfigTracker == null || sTileCache == null) {
313 getDashboardCategories();
318 protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
319 for (int i = 0; i < dashboardCategories.size(); i++) {
320 DashboardCategory category = dashboardCategories.get(i);
321 for (int j = 0; j < category.tiles.size(); j++) {
322 Tile tile = category.tiles.get(j);
323 if (sTileBlacklist.contains(tile.intent.getComponent())) {
324 category.tiles.remove(j--);
328 sDashboardCategories = dashboardCategories;
329 onCategoriesChanged();
333 private class PackageReceiver extends BroadcastReceiver {
335 public void onReceive(Context context, Intent intent) {
336 new CategoriesUpdater().execute();