Initial Contribution
This commit is contained in:
331
src/com/android/settings/quicklaunch/BookmarkPicker.java
Normal file
331
src/com/android/settings/quicklaunch/BookmarkPicker.java
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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.android.settings.quicklaunch;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Activity to pick a bookmark that will be returned to the caller.
|
||||
* <p>
|
||||
* Currently, bookmarks are either:
|
||||
* <li> Activities that are in the launcher
|
||||
* <li> Activities that are within an app that is capable of being launched with
|
||||
* the {@link Intent#ACTION_CREATE_SHORTCUT}.
|
||||
*/
|
||||
public class BookmarkPicker extends ListActivity implements SimpleAdapter.ViewBinder {
|
||||
|
||||
private static final String TAG = "BookmarkPicker";
|
||||
|
||||
/** Extra in the returned intent from this activity. */
|
||||
public static final String EXTRA_TITLE = "com.android.settings.quicklaunch.TITLE";
|
||||
|
||||
/** Extra that should be provided, and will be returned. */
|
||||
public static final String EXTRA_SHORTCUT = "com.android.settings.quicklaunch.SHORTCUT";
|
||||
|
||||
/**
|
||||
* The request code for the screen to create a bookmark that is WITHIN an
|
||||
* application. For example, Gmail can return a bookmark for the inbox
|
||||
* folder.
|
||||
*/
|
||||
private static final int REQUEST_CREATE_SHORTCUT = 1;
|
||||
|
||||
/** Intent used to get all the activities that are launch-able */
|
||||
private static Intent sLaunchIntent;
|
||||
/** Intent used to get all the activities that are {@link #REQUEST_CREATE_SHORTCUT}-able */
|
||||
private static Intent sShortcutIntent;
|
||||
|
||||
/**
|
||||
* List of ResolveInfo for activities that we can bookmark (either directly
|
||||
* to the activity, or by launching the activity and it returning a bookmark
|
||||
* WITHIN that application).
|
||||
*/
|
||||
private List<ResolveInfo> mResolveList;
|
||||
|
||||
// List adapter stuff
|
||||
private static final String KEY_TITLE = "TITLE";
|
||||
private static final String KEY_RESOLVE_INFO = "RESOLVE_INFO";
|
||||
private static final String sKeys[] = new String[] { KEY_TITLE, KEY_RESOLVE_INFO };
|
||||
private static final int sResourceIds[] = new int[] { R.id.title, R.id.icon };
|
||||
private SimpleAdapter mMyAdapter;
|
||||
|
||||
/** Display those activities that are launch-able */
|
||||
private static final int DISPLAY_MODE_LAUNCH = 0;
|
||||
/** Display those activities that are able to have bookmarks WITHIN the application */
|
||||
private static final int DISPLAY_MODE_SHORTCUT = 1;
|
||||
private int mDisplayMode = DISPLAY_MODE_LAUNCH;
|
||||
|
||||
private Handler mUiHandler = new Handler();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
updateListAndAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, DISPLAY_MODE_LAUNCH, 0, R.string.quick_launch_display_mode_applications)
|
||||
.setIcon(R.drawable.ic_menu_archive);
|
||||
menu.add(0, DISPLAY_MODE_SHORTCUT, 0, R.string.quick_launch_display_mode_shortcuts)
|
||||
.setIcon(R.drawable.ic_menu_goto);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
menu.findItem(DISPLAY_MODE_LAUNCH).setVisible(mDisplayMode != DISPLAY_MODE_LAUNCH);
|
||||
menu.findItem(DISPLAY_MODE_SHORTCUT).setVisible(mDisplayMode != DISPLAY_MODE_SHORTCUT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
switch (item.getItemId()) {
|
||||
|
||||
case DISPLAY_MODE_LAUNCH:
|
||||
mDisplayMode = DISPLAY_MODE_LAUNCH;
|
||||
break;
|
||||
|
||||
case DISPLAY_MODE_SHORTCUT:
|
||||
mDisplayMode = DISPLAY_MODE_SHORTCUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
updateListAndAdapter();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ensureIntents() {
|
||||
if (sLaunchIntent == null) {
|
||||
sLaunchIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
sShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be called from the UI thread.
|
||||
*/
|
||||
private void updateListAndAdapter() {
|
||||
// Get the activities in a separate thread
|
||||
new Thread("data updater") {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (BookmarkPicker.this) {
|
||||
/*
|
||||
* Don't touch any of the lists that are being used by the
|
||||
* adapter in this thread!
|
||||
*/
|
||||
ArrayList<ResolveInfo> newResolveList = new ArrayList<ResolveInfo>();
|
||||
ArrayList<Map<String, ?>> newAdapterList = new ArrayList<Map<String, ?>>();
|
||||
|
||||
fillResolveList(newResolveList);
|
||||
Collections.sort(newResolveList,
|
||||
new ResolveInfo.DisplayNameComparator(getPackageManager()));
|
||||
|
||||
fillAdapterList(newAdapterList, newResolveList);
|
||||
|
||||
updateAdapterToUseNewLists(newAdapterList, newResolveList);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private void updateAdapterToUseNewLists(final ArrayList<Map<String, ?>> newAdapterList,
|
||||
final ArrayList<ResolveInfo> newResolveList) {
|
||||
// Post this back on the UI thread
|
||||
mUiHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
/*
|
||||
* SimpleAdapter does not support changing the lists after it
|
||||
* has been created. We just create a new instance.
|
||||
*/
|
||||
mMyAdapter = createResolveAdapter(newAdapterList);
|
||||
mResolveList = newResolveList;
|
||||
setListAdapter(mMyAdapter);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all activities matching our current display mode.
|
||||
*
|
||||
* @param list The list to fill.
|
||||
*/
|
||||
private void fillResolveList(List<ResolveInfo> list) {
|
||||
ensureIntents();
|
||||
PackageManager pm = getPackageManager();
|
||||
list.clear();
|
||||
|
||||
if (mDisplayMode == DISPLAY_MODE_LAUNCH) {
|
||||
list.addAll(pm.queryIntentActivities(sLaunchIntent, 0));
|
||||
} else if (mDisplayMode == DISPLAY_MODE_SHORTCUT) {
|
||||
list.addAll(pm.queryIntentActivities(sShortcutIntent, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private SimpleAdapter createResolveAdapter(List<Map<String, ?>> list) {
|
||||
SimpleAdapter adapter = new SimpleAdapter(this, list,
|
||||
R.layout.bookmark_picker_item, sKeys, sResourceIds);
|
||||
adapter.setViewBinder(this);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
private void fillAdapterList(List<Map<String, ?>> list,
|
||||
List<ResolveInfo> resolveList) {
|
||||
list.clear();
|
||||
int resolveListSize = resolveList.size();
|
||||
for (int i = 0; i < resolveListSize; i++) {
|
||||
ResolveInfo info = resolveList.get(i);
|
||||
/*
|
||||
* Simple adapter craziness. For each item, we need to create a map
|
||||
* from a key to its value (the value can be any object--the view
|
||||
* binder will take care of filling the View with a representation
|
||||
* of that object).
|
||||
*/
|
||||
Map<String, Object> map = new TreeMap<String, Object>();
|
||||
map.put(KEY_TITLE, getResolveInfoTitle(info));
|
||||
map.put(KEY_RESOLVE_INFO, info);
|
||||
list.add(map);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the title for a resolve info. */
|
||||
private String getResolveInfoTitle(ResolveInfo info) {
|
||||
CharSequence label = info.loadLabel(getPackageManager());
|
||||
if (label == null) label = info.activityInfo.name;
|
||||
return label != null ? label.toString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
if (position >= mResolveList.size()) return;
|
||||
|
||||
ResolveInfo info = mResolveList.get(position);
|
||||
|
||||
switch (mDisplayMode) {
|
||||
|
||||
case DISPLAY_MODE_LAUNCH:
|
||||
// We can go ahead and return the clicked info's intent
|
||||
Intent intent = getIntentForResolveInfo(info, Intent.ACTION_MAIN);
|
||||
intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
finish(intent, getResolveInfoTitle(info));
|
||||
break;
|
||||
|
||||
case DISPLAY_MODE_SHORTCUT:
|
||||
// Start the shortcut activity so the user can pick the actual intent
|
||||
// (example: Gmail's shortcut activity shows a list of mailboxes)
|
||||
startShortcutActivity(info);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Intent getIntentForResolveInfo(ResolveInfo info, String action) {
|
||||
Intent intent = new Intent(action);
|
||||
ActivityInfo ai = info.activityInfo;
|
||||
intent.setClassName(ai.packageName, ai.name);
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an activity to get a shortcut.
|
||||
* <p>
|
||||
* For example, Gmail has an activity that lists the available labels. It
|
||||
* returns a shortcut intent for going directly to this label.
|
||||
*/
|
||||
private void startShortcutActivity(ResolveInfo info) {
|
||||
Intent intent = getIntentForResolveInfo(info, Intent.ACTION_CREATE_SHORTCUT);
|
||||
startActivityForResult(intent, REQUEST_CREATE_SHORTCUT);
|
||||
|
||||
// Will get a callback to onActivityResult
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (requestCode) {
|
||||
|
||||
case REQUEST_CREATE_SHORTCUT:
|
||||
if (data != null) {
|
||||
finish((Intent) data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT),
|
||||
data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the activity and returns the given data.
|
||||
*/
|
||||
private void finish(Intent intent, String title) {
|
||||
// Give back what was given to us (it will have the shortcut, for example)
|
||||
intent.putExtras(getIntent());
|
||||
// Put our information
|
||||
intent.putExtra(EXTRA_TITLE, title);
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean setViewValue(View view, Object data, String textRepresentation) {
|
||||
if (view.getId() == R.id.icon) {
|
||||
Drawable icon = ((ResolveInfo) data).loadIcon(getPackageManager());
|
||||
if (icon != null) {
|
||||
((ImageView) view).setImageDrawable(icon);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user