PackageBrowser.java revision 52d4c30ca52320ec92d1d1ddc8db3f07f69c4f98
152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project/* 252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * 452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * you may not use this file except in compliance with the License. 652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * You may obtain a copy of the License at 752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * 852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * 1052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * See the License for the specific language governing permissions and 1452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * limitations under the License. 1552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project */ 1652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 1752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectpackage com.android.development; 1852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 1952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.app.AlertDialog; 2052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.app.ListActivity; 2152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.content.Context; 2252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.content.pm.IPackageDeleteObserver; 2352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.content.Intent; 2452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.content.IntentFilter; 2552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.content.BroadcastReceiver; 2652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.content.pm.PackageInfo; 2752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.net.Uri; 2852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.os.Bundle; 2952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.os.RemoteException; 3052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.os.Handler; 3152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.view.Menu; 3252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.view.MenuItem; 3352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.view.View; 3452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.widget.ListView; 3552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.widget.TextView; 3652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 3752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport java.text.Collator; 3852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport java.util.Collections; 3952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport java.util.Comparator; 4052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport java.util.List; 4152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 4252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectpublic class PackageBrowser extends ListActivity 4352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project{ 4452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private PackageListAdapter mAdapter; 4552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private List<PackageInfo> mPackageInfoList = null; 4652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private Handler mHandler; 4752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 4852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public class PackageListAdapter extends ArrayAdapter<PackageInfo> 4952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project { 5052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 5152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public PackageListAdapter(Context context) 5252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project { 5352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project super(context, android.R.layout.simple_list_item_1); 5452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project mPackageInfoList = context.getPackageManager().getInstalledPackages(0); 5552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project if (mPackageInfoList != null) { 5652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project Collections.sort(mPackageInfoList, sDisplayNameComparator); 5752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 5852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project setSource(mPackageInfoList); 5952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 6052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 6152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project @Override 6252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public void bindView(View view, PackageInfo info) 6352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project { 6452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project TextView text = (TextView)view.findViewById(android.R.id.text1); 6552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project text.setText(info.packageName); 6652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 6752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 6852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 6952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project /** 7052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * Receives notifications when applications are added/removed. 7152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project */ 7252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private class ApplicationsIntentReceiver extends BroadcastReceiver { 7352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project @Override 7452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public void onReceive(Context context, Intent intent) { 7552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project // todo: this is a bit brute force. We should probably get the action and package name 7652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project // from the intent and just add to or delete from the mPackageInfoList 7752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project setupAdapter(); 7852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 7952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 8052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 8152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private final static Comparator sDisplayNameComparator = new Comparator() { 8252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public final int 8352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project compare(Object a, Object b) 8452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project { 8552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project CharSequence sa = ((PackageInfo) a).packageName; 8652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project CharSequence sb = ((PackageInfo) b).packageName; 8752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project return collator.compare(sa, sb); 8852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 8952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 9052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private final Collator collator = Collator.getInstance(); 9152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project }; 9252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 9352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project @Override 9452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project protected void onCreate(Bundle icicle) { 9552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project super.onCreate(icicle); 9652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project setupAdapter(); 9752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project mHandler= new Handler(); 9852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project registerIntentReceivers(); 9952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 10052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 10152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private void setupAdapter() { 10252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project mAdapter = new PackageListAdapter(this); 10352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project setListAdapter(mAdapter); 10452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 10552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 10652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project @Override 10752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public boolean onCreateOptionsMenu(Menu menu) { 10852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project menu.add(0, 0, 0, "Delete package").setOnMenuItemClickListener( 10952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project new MenuItem.OnMenuItemClickListener() { 11052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public boolean onMenuItemClick(MenuItem item) { 11152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project deletePackage(); 11252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project return true; 11352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 11452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project }); 11552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project return true; 11652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 11752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 11852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private void deletePackage() { 11952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project final int curSelection = getSelectedItemPosition(); 12052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project if (curSelection >= 0) { 12152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project // todo: verification dialog for package deletion 12252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project final PackageInfo packageInfo = mAdapter.itemForPosition(curSelection); 12352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project if (packageInfo != null) { 12452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project getPackageManager().deletePackage(packageInfo.packageName, 12552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project new IPackageDeleteObserver.Stub() { 12652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public void packageDeleted(boolean succeeded) throws RemoteException { 12752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project if (succeeded) { 12852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project mPackageInfoList.remove(curSelection); 12952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project mHandler.post(new Runnable() { 13052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public void run() { 13152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project mAdapter.notifyDataSetChanged(); 13252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 13352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project }); 13452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 13552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project // todo: verification dialog for data directory 13652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project final String dataPath = packageInfo.applicationInfo.dataDir; 13752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project // todo: delete the data directory 13852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } else { 13952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project mHandler.post(new Runnable() { 14052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project public void run() { 14152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project new AlertDialog.Builder(PackageBrowser.this) 14252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project .setTitle("Oops") 14352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project .setMessage("Could not delete package." + 14452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project " Maybe it is in /system/app rather than /data/app?") 14552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project .show(); 14652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 14752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project }); 14852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 14952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 15052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 15152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project }, 15252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 0); 15352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 15452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 15552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 15652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 15752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project private void registerIntentReceivers() { 15852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); 15952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 16052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 16152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project filter.addDataScheme("package"); 16252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project registerReceiver(new ApplicationsIntentReceiver(), filter); 16352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 16452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project 16552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project @Override 16652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project protected void onListItemClick(ListView l, View v, int position, long id) 16752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project { 16852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project PackageInfo info = 16952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project mAdapter.itemForPosition(position); 17052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project if (info != null) { 17152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project Intent intent = new Intent( 17252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project null, Uri.fromParts("package", info.packageName, null)); 17352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project intent.setClass(this, PackageSummary.class); 17452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project startActivity(intent); 17552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 17652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project } 17752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project} 178