Home | History | Annotate | Download | only in development
      1 /*
      2  * Copyright (C) 2007 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.android.development;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.ListActivity;
     21 import android.content.Context;
     22 import android.content.pm.IPackageDeleteObserver;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.content.BroadcastReceiver;
     26 import android.content.pm.PackageInfo;
     27 import android.content.pm.PackageManager;
     28 import android.net.Uri;
     29 import android.os.Bundle;
     30 import android.os.RemoteException;
     31 import android.os.Handler;
     32 import android.view.Menu;
     33 import android.view.MenuItem;
     34 import android.view.View;
     35 import android.widget.ImageView;
     36 import android.widget.ListView;
     37 import android.widget.TextView;
     38 
     39 import java.text.Collator;
     40 import java.util.ArrayList;
     41 import java.util.Collections;
     42 import java.util.Comparator;
     43 import java.util.List;
     44 
     45 public class PackageBrowser extends ListActivity {
     46     static class MyPackageInfo {
     47         PackageInfo info;
     48         String label;
     49     }
     50 
     51     private PackageListAdapter mAdapter;
     52     private List<MyPackageInfo> mPackageInfoList = new ArrayList<MyPackageInfo>();
     53     private Handler mHandler;
     54     private BroadcastReceiver mRegisteredReceiver;
     55 
     56     public class PackageListAdapter extends ArrayAdapter<MyPackageInfo> {
     57 
     58         public PackageListAdapter(Context context) {
     59             super(context, R.layout.package_list_item);
     60             List<PackageInfo> pkgs = context.getPackageManager().getInstalledPackages(0);
     61             for (int i=0; i<pkgs.size(); i++) {
     62                 MyPackageInfo info = new MyPackageInfo();
     63                 info.info = pkgs.get(i);
     64                 info.label = info.info.applicationInfo.loadLabel(getPackageManager()).toString();
     65                 mPackageInfoList.add(info);
     66             }
     67             if (mPackageInfoList != null) {
     68                 Collections.sort(mPackageInfoList, sDisplayNameComparator);
     69             }
     70             setSource(mPackageInfoList);
     71         }
     72 
     73         @Override
     74         public void bindView(View view, MyPackageInfo info) {
     75             ImageView icon = (ImageView)view.findViewById(R.id.icon);
     76             TextView name = (TextView)view.findViewById(R.id.name);
     77             TextView description = (TextView)view.findViewById(R.id.description);
     78             icon.setImageDrawable(info.info.applicationInfo.loadIcon(getPackageManager()));
     79             name.setText(info.label);
     80             description.setText(info.info.packageName);
     81         }
     82     }
     83 
     84     /**
     85      * Receives notifications when applications are added/removed.
     86      */
     87     private class ApplicationsIntentReceiver extends BroadcastReceiver {
     88         @Override
     89         public void onReceive(Context context, Intent intent) {
     90             // todo: this is a bit brute force.  We should probably get the action and package name
     91             //       from the intent and just add to or delete from the mPackageInfoList
     92             setupAdapter();
     93         }
     94     }
     95 
     96     private final static Comparator<MyPackageInfo> sDisplayNameComparator
     97             = new Comparator<MyPackageInfo>() {
     98         public final int
     99         compare(MyPackageInfo a, MyPackageInfo b) {
    100             return collator.compare(a.label, b.label);
    101         }
    102 
    103         private final Collator   collator = Collator.getInstance();
    104     };
    105 
    106     @Override
    107     protected void onCreate(Bundle icicle) {
    108         super.onCreate(icicle);
    109         setupAdapter();
    110         mHandler= new Handler();
    111         registerIntentReceivers();
    112     }
    113 
    114     @Override
    115     protected void onDestroy() {
    116         super.onDestroy();
    117         if (mRegisteredReceiver != null) {
    118             unregisterReceiver(mRegisteredReceiver);
    119         }
    120     }
    121 
    122     private void setupAdapter() {
    123         mAdapter = new PackageListAdapter(this);
    124         setListAdapter(mAdapter);
    125     }
    126 
    127     @Override
    128     public boolean onCreateOptionsMenu(Menu menu) {
    129         menu.add(0, 0, 0, "Delete package").setOnMenuItemClickListener(
    130                 new MenuItem.OnMenuItemClickListener() {
    131             public boolean onMenuItemClick(MenuItem item) {
    132                 deletePackage();
    133                 return true;
    134             }
    135         });
    136         return true;
    137     }
    138 
    139     private void deletePackage() {
    140         final int curSelection = getSelectedItemPosition();
    141         if (curSelection >= 0) {
    142             // todo: verification dialog for package deletion
    143             final MyPackageInfo packageInfo = mAdapter.itemForPosition(curSelection);
    144             if (packageInfo != null) {
    145                 getPackageManager().deletePackage(packageInfo.info.packageName,
    146                                                   new IPackageDeleteObserver.Stub() {
    147                     public void packageDeleted(String packageName, int returnCode)
    148                             throws RemoteException {
    149                         if (returnCode == PackageManager.DELETE_SUCCEEDED) {
    150                             mPackageInfoList.remove(curSelection);
    151                             mHandler.post(new Runnable() {
    152                                     public void run() {
    153                                         mAdapter.notifyDataSetChanged();
    154                                     }
    155                                 });
    156 
    157                             // todo: verification dialog for data directory
    158                             final String dataPath = packageInfo.info.applicationInfo.dataDir;
    159                             // todo: delete the data directory
    160                         } else {
    161                             mHandler.post(new Runnable() {
    162                                     public void run() {
    163                                         new AlertDialog.Builder(PackageBrowser.this)
    164                                             .setTitle("Oops")
    165                                             .setMessage("Could not delete package." +
    166                                                 "  Maybe it is in /system/app rather than /data/app?")
    167                                             .show();
    168                                     }
    169                                 });
    170 
    171                         }
    172                     }
    173                 },
    174                                                   0);
    175             }
    176         }
    177     }
    178 
    179     private void registerIntentReceivers() {
    180         IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
    181         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
    182         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
    183         filter.addDataScheme("package");
    184         mRegisteredReceiver = new ApplicationsIntentReceiver();
    185         registerReceiver(mRegisteredReceiver, filter);
    186     }
    187 
    188     @Override
    189     protected void onListItemClick(ListView l, View v, int position, long id) {
    190         MyPackageInfo info =
    191             mAdapter.itemForPosition(position);
    192         if (info != null) {
    193             Intent intent = new Intent(
    194                 null, Uri.fromParts("package", info.info.packageName, null));
    195             intent.setClass(this, PackageSummary.class);
    196             startActivity(intent);
    197         }
    198     }
    199 }
    200