package com.ghostsq.commander.adapters;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import com.ghostsq.commander.Commander;
import com.ghostsq.commander.R;
import com.ghostsq.commander.TextViewer;
import com.ghostsq.commander.adapters.CommanderAdapter;
import com.ghostsq.commander.adapters.CommanderAdapterBase;
import com.ghostsq.commander.utils.MnfUtils;
import com.ghostsq.commander.utils.Utils;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ContextMenu;
import android.widget.AdapterView;
public class AppsAdapter extends CommanderAdapterBase {
private final static String TAG = "AppsAdapter";
public static final String DEFAULT_LOC = "apps:";
public static final int LAUNCH_CMD = 9176, MANAGE_CMD = 7161, CREATE_APP_SHORTCUT = 3123;
// Java compiler creates a thunk function to access to the private owner class member from a subclass
// to avoid that all the member accessible from the subclasses are public
public final PackageManager pm = ctx.getPackageManager();
public PackageInfo[] pkgInfos = null;
private final String MANIFEST = "Manifest", ACTIVITIES = "Activities", PROVIDERS = "Providers", SERVICES = "Services";
private String MANAGE = "Manage", SHORTCUTS = "Shortcuts";
private Item[] compItems = null;
private ActivityInfo[] actInfos = null;
private ProviderInfo[] prvInfos = null;
private ServiceInfo[] srvInfos = null;
private ResolveInfo[] resInfos = null;
private IntentFilter[] intFilters = null;
private MnfUtils manUtl = null;
private Uri uri;
public AppsAdapter( Context ctx_ ) {
super( ctx_, DETAILED_MODE | NARROW_MODE | SHOW_ATTR );
parentLink = PLS;
MANAGE = s( R.string.manage );
SHORTCUTS = s( R.string.shortcuts );
}
@Override
public int getType() {
return CA.APPS;
}
@Override
public int setMode( int mask, int val ) {
if( ( mask & ( MODE_WIDTH /*| MODE_DETAILS | MODE_ATTR*/ ) ) == 0 )
super.setMode( mask, val );
return mode;
}
class ListEngine extends Engine {
private PackageInfo[] items_tmp;
public String pass_back_on_done;
ListEngine( Handler h, String pass_back_on_done_ ) {
super.setHandler( h );
pass_back_on_done = pass_back_on_done_;
}
public PackageInfo[] getItems() {
return items_tmp;
}
@Override
public void run() {
try {
Init( null );
List<PackageInfo> all_packages = pm.getInstalledPackages( 0 );
items_tmp = new PackageInfo[all_packages.size()];
all_packages.toArray( items_tmp );
Arrays.sort( items_tmp, new PackageInfoComparator( mode & MODE_SORTING, (mode & MODE_CASE) != 0, ascending ) );
sendProgress( null, Commander.OPERATION_COMPLETED, pass_back_on_done );
}
catch( Exception e ) {
sendProgress( "Fail", Commander.OPERATION_FAILED, pass_back_on_done );
}
catch( OutOfMemoryError err ) {
sendProgress( "Out Of Memory", Commander.OPERATION_FAILED, pass_back_on_done );
}
finally {
super.run();
}
}
}
@Override
protected void onReadComplete() {
if( reader instanceof ListEngine ) {
ListEngine list_engine = (ListEngine)reader;
pkgInfos = list_engine.getItems();
reSort();
numItems = pkgInfos != null ? pkgInfos.length+1 : 1;
notifyDataSetChanged();
}
}
@Override
public String toString() {
return uri.toString();
}
/*
* CommanderAdapter implementation
*/
@Override
public Uri getUri() {
return uri;
}
@Override
public void setUri( Uri uri_ ) {
uri = uri_;
}
@Override
public boolean readSource( Uri tmp_uri, String pbod ) {
try {
dirty = true;
numItems = 1;
compItems = null;
pkgInfos = null;
actInfos = null;
prvInfos = null;
srvInfos = null;
resInfos = null;
intFilters = null;
super.setMode( ATTR_ONLY, 0 );
if( reader != null ) {
if( reader.reqStop() ) { // that's not good.
Thread.sleep( 500 ); // will it end itself?
if( reader.isAlive() ) {
Log.e( TAG, "Busy!" );
return false;
}
}
}
if( tmp_uri != null )
uri = tmp_uri;
String a = uri.getAuthority();
if( a == null || a.length() == 0 ) { // enumerate the applications
manUtl = null;
notify( Commander.OPERATION_STARTED );
reader = new ListEngine( readerHandler, pbod );
reader.start();
return true;
}
String path = uri.getPath();
if( path == null || path.length() <= 1 ) {
ArrayList<Item> ial = new ArrayList<Item>();
numItems = 1;
Item manage_item = new Item( MANAGE );
manage_item.setIcon( pm.getApplicationIcon( "com.android.settings" ) );
manage_item.icon_id = R.drawable.and;
ial.add( manage_item );
Item manifest_item = new Item( MANIFEST );
manifest_item.icon_id = R.drawable.xml;
ial.add( manifest_item );
PackageInfo pi = pm.getPackageInfo( a, PackageManager.GET_ACTIVITIES |
PackageManager.GET_PROVIDERS |
PackageManager.GET_SERVICES );
if( pi.activities != null && pi.activities.length > 0 ) {
Item activities_item = new Item( ACTIVITIES );
activities_item.dir = true;
activities_item.size = pi.activities.length;
ial.add( activities_item );
}
if( pi.providers != null && pi.providers.length > 0 ) {
Item providers_item = new Item( PROVIDERS );
providers_item.dir = true;
providers_item.size = pi.providers.length;
ial.add( providers_item );
}
if( pi.services != null && pi.services.length > 0 ) {
Item services_item = new Item( SERVICES );
services_item.dir = true;
services_item.size = pi.services.length;
ial.add( services_item );
}
Item shortcuts_item = new Item( SHORTCUTS );
shortcuts_item.dir = true;
ial.add( shortcuts_item );
// all items were created
compItems = new Item[ial.size()];
ial.toArray( compItems );
numItems = compItems.length + 1;
notify( pbod );
return true;
}
else { // the URI path contains something
super.setMode( 0, ATTR_ONLY );
List<String> ps = uri.getPathSegments();
if( ps != null && ps.size() >= 1 ) {
if( SHORTCUTS.equals( ps.get( 0 ) ) ) {
Intent[] ins = new Intent[2];
ins[0] = new Intent( Intent.ACTION_CREATE_SHORTCUT );
ins[1] = new Intent( Intent.ACTION_MAIN );
resInfos = getResolvers( ins, a );
if( resInfos != null )
numItems = resInfos.length + 1;
} else
if( ps.size() >= 2 && ACTIVITIES.equals( ps.get( 0 ) ) ) {
if( manUtl == null )
manUtl = new MnfUtils( pm, a );
intFilters = manUtl.getIntentFilters( ps.get( 1 ) );
if( intFilters != null )
numItems = intFilters.length + 1;
} else {
PackageInfo pi = pm.getPackageInfo( a, PackageManager.GET_ACTIVITIES |
PackageManager.GET_PROVIDERS |
PackageManager.GET_SERVICES );
if( ACTIVITIES.equals( ps.get( 0 ) ) ) {
actInfos = pi.activities != null ? pi.activities : new ActivityInfo[0];
reSort();
numItems = actInfos.length + 1;
} else if( PROVIDERS.equals( ps.get( 0 ) ) ) {
prvInfos = pi.providers != null ? pi.providers : new ProviderInfo[0];
numItems = prvInfos.length + 1;
} else if( SERVICES.equals( ps.get( 0 ) ) ) {
srvInfos = pi.services != null ? pi.services : new ServiceInfo[0];
numItems = srvInfos.length + 1;
}
}
notify( pbod );
return true;
}
}
}
catch( Exception e ) {
Log.e( TAG, uri != null ? uri.toString() : null, e );
notify( uri != null ? s( R.string.failed ) + s( R.string.pkg_name ) + ":\n" + uri.getAuthority() :
s( R.string.fail ), pbod );
return false;
}
finally {
notifyDataSetChanged();
}
notify( s( R.string.fail ), pbod );
return false;
}
@Override
protected void reSort() {
if( pkgInfos != null ) {
PackageInfoComparator comp = new PackageInfoComparator( mode & MODE_SORTING, (mode & MODE_CASE) != 0, ascending );
Arrays.sort( pkgInfos, comp );
}
else if( actInfos != null ) {
ActivityInfoComparator comp = new ActivityInfoComparator( mode & MODE_SORTING, (mode & MODE_CASE) != 0, ascending );
Arrays.sort( actInfos, comp );
}
else if( prvInfos != null ) {
}
else {
}
}
private final ResolveInfo[] getResolvers( Intent[] ins, String package_name ) {
try {
final int fl = PackageManager.GET_INTENT_FILTERS | PackageManager.GET_RESOLVED_FILTER;
List<ResolveInfo> tmp_list = new ArrayList<ResolveInfo>();
for( Intent in : ins ) {
List<ResolveInfo> resolves = pm.queryIntentActivities( in, fl );
for( ResolveInfo res : resolves ) {
if( package_name.equals( res.activityInfo.applicationInfo.packageName ) )
tmp_list.add( res );
}
}
if( tmp_list.size() > 0 ) {
ResolveInfo[] ret = new ResolveInfo[tmp_list.size()];
return tmp_list.toArray( ret );
}
} catch( Exception e ) {
Log.e( TAG, "For: " + package_name, e );
}
return null;
}
private static <T> ArrayList<T> bitsToItems( SparseBooleanArray cis, T[] items ) {
try {
if( items == null ) return null;
ArrayList<T> al = new ArrayList<T>();
for( int i = 0; i < cis.size(); i++ ) {
if( cis.valueAt( i ) ) {
int k = cis.keyAt( i );
if( k > 0 )
al.add( items[ k - 1 ] );
}
}
return al;
} catch( Exception e ) {
Log.e( TAG, "bitsToNames()'s Exception: " + e );
}
return null;
}
private String[] flagsStrs = {
"SYSTEM",
"DEBUGGABLE",
"HAS_CODE",
"PERSISTENT",
"FACTORY_TEST",
"ALLOW_TASK_REPARENTING",
"ALLOW_CLEAR_USER_DATA",
"UPDATED_SYSTEM_APP",
"TEST_ONLY",
"SUPPORTS_SMALL_SCREENS",
"SUPPORTS_NORMAL_SCREENS",
"SUPPORTS_LARGE_SCREENS",
"RESIZEABLE_FOR_SCREENS",
"SUPPORTS_SCREEN_DENSITIES",
"VM_SAFE_MODE",
"ALLOW_BACKUP",
"KILL_AFTER_RESTORE",
"RESTORE_ANY_VERSION",
"EXTERNAL_STORAGE",
"SUPPORTS_XLARGE_SCREENS",
"NEVER_ENCRYPT",
"FORWARD_LOCK",
"CANT_SAVE_STATE"
};
private final String getGroupName( int gid ) {
switch( gid ) {
case 0: return "root"; /* traditional unix root user */
case 1000: return "system"; /* system server */
case 1001: return "radio"; /* telephony subsystem, RIL */
case 1002: return "bluetooth"; /* bluetooth subsystem */
case 1003: return "graphics"; /* graphics devices */
case 1004: return "input"; /* input devices */
case 1005: return "audio"; /* audio devices */
case 1006: return "camera"; /* camera devices */
case 1007: return "log"; /* log devices */
case 1008: return "compass"; /* compass device */
case 1009: return "mount"; /* mountd socket */
case 1010: return "wifi"; /* wifi subsystem */
case 1011: return "adb"; /* android debug bridge (adbd) */
case 1012: return "install"; /* group for installing packages */
case 1013: return "media"; /* mediaserver process */
case 1014: return "dhcp"; /* dhcp client */
case 1015: return "sdcard_rw"; /* external storage write access */
case 1016: return "vpn"; /* vpn system */
case 1017: return "keystore"; /* keystore subsystem */
case 1018: return "usb"; /* USB devices */
case 1019: return "drm"; /* DRM server */
case 1020: return "available"; /* available for use */
case 1021: return "gps"; /* GPS daemon */
case 1023: return "media_rw"; /* internal media storage write access */
case 1024: return "mtp"; /* MTP USB driver access */
case 1025: return "nfc"; /* nfc subsystem */
case 1026: return "drmrpc"; /* group for drm rpc */
case 2000: return "shell"; /* adb and debug shell user */
case 2001: return "cache"; /* cache access */
case 2002: return "diag"; /* access to diagnostic resources */
case 3001: return "net_bt_admin"; /* bluetooth: create any socket */
case 3002: return "net_bt"; /* bluetooth: create sco, rfcomm or l2cap sockets */
case 3003: return "inet"; /* can create AF_INET and AF_INET6 sockets */
case 3004: return "net_raw"; /* can create raw INET sockets */
case 3005: return "net_admin";
case 9998: return "misc"; /* access to misc storage */
case 9999: return "nobody";
default: return gid >= 10000 ? "app_" + ( gid - 10000 ) : "?";
}
}
@Override
public void reqItemsSize( SparseBooleanArray cis ) {
ArrayList<PackageInfo> pl = null;
if( pkgInfos == null ) {
pl = new ArrayList<PackageInfo>( 1 );
try {
pl.add( pm.getPackageInfo( uri.getAuthority(), 0 ) );
} catch( Exception e ) {
Log.e( TAG, uri.getAuthority(), e );
}
}
else
pl = bitsToItems( cis, pkgInfos );
if( pl == null || pl.size() == 0 ) {
notErr();
return;
}
final String cs = ": ";
StringBuffer sb = new StringBuffer( 1024 );
for( int i = 0; i < pl.size(); i++ ) {
try {
PackageInfo pi = pm.getPackageInfo( pl.get( i ).packageName, PackageManager.GET_GIDS |
PackageManager.GET_PERMISSIONS ); // PackageManager.GET_SIGNATURES
if( pi == null )
continue;
String v = null;
int vc = 0;
String size = null;
String date = null;
String flags = null;
String gids = null;
try {
v = pi.versionName;
vc = pi.versionCode;
if( pi.gids != null && pi.gids.length > 0 ) {
StringBuffer gsb = new StringBuffer( 128 );
for( int gi = 0; gi < pi.gids.length; gi++ ) {
if( gi > 0 )
gsb.append( ", " );
int g = pi.gids[gi];
gsb.append( g ).append( "(" ).append( getGroupName( g ) ).append( ")" );
}
gids = gsb.toString();
}
} catch( Exception e ) {}
sb.append( s( R.string.pkg_name ) ).append( cs ).append( pi.packageName );
if( v != null )
sb.append( "\n" ).append( s( R.string.version ) ).append( cs ).append( v );
if( vc > 0 )
sb.append( "\n" ).append( s( R.string.version_code ) ).append( cs ).append( vc );
ApplicationInfo ai = pi.applicationInfo;
if( ai != null ) {
File asdf = new File( ai.sourceDir );
date = getLocalDateTimeStr( new Date( asdf.lastModified() ) );
size = Utils.getHumanSize( asdf.length() );
StringBuffer fsb = new StringBuffer( 512 );
int ff = ai.flags;
for( int fi = 0; fi < flagsStrs.length; fi++ ) {
if( ( ( 1<<fi ) & ff ) != 0 ) {
if( fsb.length() > 0 )
fsb.append( " | " );
fsb.append( flagsStrs[fi] );
}
}
fsb.append( " (" ).append( Integer.toHexString( ff ) ).append( ")" );
flags = fsb.toString();
sb.append( "\n" ).append( s( R.string.target_sdk ) ).append( cs ).append( ai.targetSdkVersion );
sb.append( "\n" ).append( "UID" ).append( cs ).append( ai.uid );
if( gids != null )
sb.append( "\n" ).append( "GIDs" ).append( cs ).append( gids );
sb.append( "\n" ).append( s( R.string.location ) ).append( cs ).append( ai.sourceDir );
if( date != null )
sb.append( "\n" ).append( s( R.string.inst_date ) ).append( cs ).append( date );
if( size != null )
sb.append( "\n" ).append( s( R.string.pkg_size ) ).append( cs ).append( size );
sb.append( "\n" ).append( s( R.string.process ) ).append( cs ).append( ai.processName );
if( ai.className != null )
sb.append( "\n" ).append( s( R.string.app_class ) ).append( cs ).append( ai.className );
if( ai.taskAffinity != null )
sb.append( "\n" ).append( s( R.string.affinity ) ).append( cs ).append( ai.taskAffinity );
}
StringBuffer psb = new StringBuffer( 512 );
if( pi.requestedPermissions != null ) {
for( int rpi = 0; rpi < pi.requestedPermissions.length; rpi++ ) {
if( rpi > 0 )
psb.append( ", " );
String p = pi.requestedPermissions[rpi];
if( p.startsWith( "android.permission." ) )
p = p.substring( 19 );
psb.append( p );
}
}
if( pi.permissions != null ) {
psb.append( "\nDeclared:\n" );
for( int dpi = 0; dpi < pi.permissions.length; dpi++ ) {
if( dpi > 0 )
psb.append( ", " );
psb.append( pi.permissions[dpi].toString() );
}
}
if( psb.length() > 0 )
sb.append( "\n" ).append( s( R.string.permissions ) ).append( cs ).append( psb.toString() );
if( flags != null )
sb.append( "\n\n" ).append( s( R.string.flags ) ).append( cs ).append( flags );
sb.append( "\n" );
if( pi.signatures != null ) {
sb.append( "\nSignatures:\n" );
for( int si = 0; si < pi.signatures.length; si++ ) {
if( si > 0 )
sb.append( ", " );
sb.append( pi.signatures[si].toCharsString() );
}
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
notify( sb.toString(), Commander.OPERATION_COMPLETED, Commander.OPERATION_REPORT_IMPORTANT );
}
class CopyFromEngine extends Engine
{
private ArrayList<PackageInfo> pl;
CopyFromEngine( ArrayList<PackageInfo> list_, Engines.IReciever recipient_ ) {
super( recipient_ );
pl = list_;
}
@Override
public void run() {
String tmp_path = Utils.mbAddSl( createTempDir() );
for( int i = 0; i < pl.size(); i++ ) {
ApplicationInfo ai = pl.get( i ).applicationInfo;
if( ai != null ) {
try {
FileInputStream fis = new FileInputStream( ai.sourceDir );
String tmp_n = tmp_path + ai.packageName + ".apk";
FileOutputStream fos = new FileOutputStream( tmp_n );
Utils.copyBytes( fis, fos );
} catch( Exception e ) {
Log.e( TAG, "tmp apk creation", e );
}
}
}
sendReceiveReq( new File( tmp_path ) );
return;
}
}
@Override
public boolean copyItems( SparseBooleanArray cis, CommanderAdapter to, boolean move ) {
if( pkgInfos != null ) {
ArrayList<PackageInfo> pl = bitsToItems( cis, pkgInfos );
if( pl == null || pl.size() == 0 ) {
notify( s( R.string.copy_err ), Commander.OPERATION_FAILED );
return false;
}
notify( Commander.OPERATION_STARTED );
commander.startEngine( new CopyFromEngine( pl, to.getReceiver() ) );
return true;
}
if( compItems != null ) {
ArrayList<Item> il = bitsToItems( cis, compItems );
if( il != null ) {
for( int i = 0; i < il.size(); i++ ) {
if( MANIFEST.equals( il.get( i ).name ) ) {
try {
ApplicationInfo ai = pm.getApplicationInfo( uri.getAuthority(), 0 );
if( manUtl == null )
manUtl = new MnfUtils( pm, ai.packageName );
String m = manUtl.extractManifest();
if( m != null && m.length() > 0 ) {
String tmp_fn = ai.packageName + ".xml";
FileOutputStream fos = ctx.openFileOutput( tmp_fn, Context.MODE_WORLD_WRITEABLE|Context.MODE_WORLD_READABLE);
if( fos != null ) {
OutputStreamWriter osw = new OutputStreamWriter( fos );
osw.write( m );
osw.close();
String[] paths = new String[1];
paths[0] = ctx.getFileStreamPath( tmp_fn ).getAbsolutePath();
boolean ok = to.receiveItems( paths, MODE_COPY );
if( !ok ) notify( Commander.OPERATION_FAILED );
return ok;
}
}
} catch( Exception e ) {
e.printStackTrace();
}
}
}
}
}
return notErr();
}
@Override
public boolean createFile( String fileURI ) {
return notErr();
}
@Override
public void createFolder( String new_name ) {
notErr();
}
@Override
public boolean deleteItems( SparseBooleanArray cis ) {
if( pkgInfos == null ) return notErr();
ArrayList<PackageInfo> al = bitsToItems( cis, pkgInfos );
if( al == null ) return false;
for( int i = 0; i < al.size(); i++ ) {
Intent in = new Intent( Intent.ACTION_DELETE, Uri.parse( "package:" + al.get( i ).packageName ) );
commander.issue( in, 0 );
}
return true;
}
@Override
public boolean receiveItems( String[] full_names, int move_mode ) {
return notErr();
}
@Override
public boolean renameItem( int position, String newName, boolean c ) {
return notErr();
}
@Override
public void populateContextMenu( ContextMenu menu, AdapterView.AdapterContextMenuInfo acmi, int num ) {
try {
if( acmi.position > 0 ) {
if( pkgInfos != null ) {
ApplicationInfo ai = pkgInfos[acmi.position-1].applicationInfo;
if( ai != null ) {
String name = ai.loadLabel( pm ).toString();
menu.add( 0, LAUNCH_CMD, 0, ctx.getString( R.string.launch ) + " \"" + name + "\"" );
}
menu.add( 0, MANAGE_CMD, 0, MANAGE );
menu.add( 0, Commander.SEND_TO, 0, R.string.send_to );
}
else if( resInfos != null ) {
ResolveInfo ri = resInfos[acmi.position-1];
if( ri.filter != null && ri.filter.matchAction( Intent.ACTION_MAIN ) )
menu.add( 0, CREATE_APP_SHORTCUT, 0, ctx.getString( R.string.shortcut ) );
}
}
} catch( Exception e ) {
Log.e( TAG, null, e );
}
super.populateContextMenu( menu, acmi, num );
}
@Override
public void doIt( int command_id, SparseBooleanArray cis ) {
try {
if( pkgInfos != null ) {
ArrayList<PackageInfo> pl = bitsToItems( cis, pkgInfos );
if( pl == null || pl.size() == 0 ) return;
ApplicationInfo ai = pl.get(0).applicationInfo;
if( ai == null ) return;
if( MANAGE_CMD == command_id ) {
managePackage( ai.packageName );
return;
}
if( LAUNCH_CMD == command_id ) {
Intent in = pm.getLaunchIntentForPackage( ai.packageName );
commander.issue( in, 0 );
return;
}
}
else if( resInfos != null ) {
if( CREATE_APP_SHORTCUT == command_id ) {
ArrayList<ResolveInfo> rl = bitsToItems( cis, resInfos );
if( rl == null || rl.size() == 0 ) return;
for( int i = 0; i < rl.size(); i++ ) {
ActivityInfo ai = rl.get( i ).activityInfo;
if( ai != null ) {
Bitmap ico = null;
Drawable drawable = ai.loadIcon( pm );
if( drawable instanceof BitmapDrawable ) {
BitmapDrawable bd = (BitmapDrawable)drawable;
ico = bd.getBitmap();
}
createDesktopShortcut( new ComponentName( ai.applicationInfo.packageName, ai.name ),
ai.loadLabel( pm ).toString(), ico );
}
}
return;
}
}
} catch( Exception e ) {
Log.e( TAG, "Can't do the command " + command_id, e );
}
}
@Override
public void openItem( int position ) {
try {
if( pkgInfos != null ) {
if( position == 0 ) {
commander.Navigate( Uri.parse( HomeAdapter.DEFAULT_LOC ), null, null );
}
else if( position <= pkgInfos.length ) {
PackageInfo pi = pkgInfos[position - 1];
commander.Navigate( uri.buildUpon().authority( pi.packageName ).build(), null, null );
}
} else if( actInfos != null ) {
if( position == 0 ) {
commander.Navigate( uri.buildUpon().path( null ).build(), null, ACTIVITIES );
}
else if( position <= actInfos.length ) {
ActivityInfo act = actInfos[position-1];
if( act.exported )
commander.Navigate( uri.buildUpon().appendPath( act.name ).build(), null, null );
else
commander.showInfo( s( R.string.not_exported ) );
}
} else if( prvInfos != null || srvInfos != null ) {
if( position == 0 ) {
commander.Navigate( uri.buildUpon().path( null ).build(), null, PROVIDERS );
}
else if( position <= prvInfos.length ) {
// ???
}
} else if( resInfos != null ) {
if( position == 0 ) {
List<String> paths = uri.getPathSegments();
if( paths == null )
commander.Navigate( uri.buildUpon().path( null ).build(), null, null );
String p = paths.size() > 1 ? paths.get( paths.size()-2 ) : null;
String n = paths.get( paths.size()-1 );
commander.Navigate( uri.buildUpon().path( p ).build(), null, n );
}
else if( position <= resInfos.length ) {
ResolveInfo ri = resInfos[position - 1];
ActivityInfo ai = ri.activityInfo;
if( ri.filter.hasAction( Intent.ACTION_CREATE_SHORTCUT ) ) {
Intent in = new Intent( Intent.ACTION_CREATE_SHORTCUT );
in.setComponent( new ComponentName( ai.packageName, ai.name ) );
commander.issue( in, R.id.create_shortcut );
}
else if( ri.filter.hasAction( Intent.ACTION_MAIN ) ) {
Intent in = new Intent(Intent.ACTION_MAIN );
in.setComponent( new ComponentName( ai.packageName, ai.name ) );
commander.issue( in, 0 );
/*
Bitmap ico = null;
Drawable drawable = ai.loadIcon( pm );
if( drawable instanceof BitmapDrawable ) {
BitmapDrawable bd = (BitmapDrawable)drawable;
ico = bd.getBitmap();
}
createDesktopShortcut( new ComponentName( ai.packageName, ai.name ),
ai.loadLabel( pm ).toString(), ico );
*/
}
}
} else
if( intFilters != null ) {
if( position == 0 ) {
List<String> paths = uri.getPathSegments();
if( paths == null )
commander.Navigate( uri.buildUpon().path( null ).build(), null, null );
String p = paths.size() > 1 ? paths.get( paths.size()-2 ) : null;
String n = paths.get( paths.size()-1 );
commander.Navigate( uri.buildUpon().path( p ).build(), null, n );
}
else {
// ???
}
} else {
if( position == 0 ) {
commander.Navigate( Uri.parse( DEFAULT_LOC ), null, uri.getAuthority() );
return;
}
String name = getItemName( position, false );
if( MANAGE.equals( name ) ) {
managePackage( uri.getAuthority() );
}
else if( MANIFEST.equals( name ) ) {
String a = uri.getAuthority();
ApplicationInfo ai = pm.getApplicationInfo( a, 0 );
if( manUtl == null )
manUtl = new MnfUtils( pm, a );
String m = manUtl.extractManifest();
if( m != null ) {
Intent in = new Intent( ctx, TextViewer.class );
in.setData( Uri.parse( TextViewer.STRURI ) );
in.putExtra( TextViewer.STRKEY, m );
commander.issue( in, 0 );
}
}
else
commander.Navigate( uri.buildUpon().path( name ).build(), null, null );
}
} catch( Exception e ) {
Log.e( TAG, uri.toString() + " " + position, e );
}
}
private final void managePackage( String p ) {
try {
Intent in = new Intent( Intent.ACTION_VIEW );
in.setClassName( "com.android.settings", "com.android.settings.InstalledAppDetails" );
in.putExtra( "com.android.settings.ApplicationPkgName", p );
in.putExtra( "pkg", p );
List<ResolveInfo> acts = pm.queryIntentActivities( in, 0 );
if( acts.size( ) > 0 )
commander.issue( in, 0 );
else {
in = new Intent( "android.settings.APPLICATION_DETAILS_SETTINGS", Uri.fromParts( "package", p, null ) );
acts = pm.queryIntentActivities( in, 0 );
if( acts.size( ) > 0 )
commander.issue( in, 0 );
else {
Log.e( TAG, "Failed to resolve activity for InstalledAppDetails" );
}
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
@Override
public String getItemName( int position, boolean full ) {
if( position < 0 )
return null;
if( position == 0 )
return parentLink;
try {
int idx = position - 1;
if( pkgInfos != null ) {
return position <= pkgInfos.length ? pkgInfos[idx].packageName : null;
}
if( compItems != null ) {
return position <= compItems.length ? compItems[idx].name : null;
}
if( actInfos != null ) {
return position <= actInfos.length ? actInfos[idx].name : null;
}
if( prvInfos != null ) {
return position <= prvInfos.length ? prvInfos[idx].toString() : null;
}
if( srvInfos != null ) {
return position <= srvInfos.length ? srvInfos[idx].toString() : null;
}
if( resInfos != null ) {
return position <= resInfos.length ? resInfos[idx].toString() : null;
}
if( intFilters != null ) {
return position <= intFilters.length ? intFilters[idx].toString() : null;
}
}
catch( Exception e ) {
Log.e( TAG, "pos=" + position, e );
}
return null;
}
@Override
public Object getItem( int position ) {
Item item = new Item();
if( position == 0 ) {
item.name = parentLink;
item.dir = true;
return item;
}
item.name = "???";
if( pkgInfos != null ) {
if( position >= 0 && position <= pkgInfos.length ) {
PackageInfo pi = pkgInfos[position - 1];
ApplicationInfo ai = pi.applicationInfo;
item.dir = false;
item.name = ai != null ? ai.loadLabel( pm ).toString() : pi.packageName;
item.sel = false;
File asdf = new File( ai.sourceDir );
item.date = new Date( asdf.lastModified() );
item.size = asdf.length();
if( ai != null )
item.attr = ai.packageName;
item.setIcon( ai.loadIcon( pm ) );
item.origin = new File( ai.sourceDir );
}
}
else if( actInfos != null ) {
if( position <= actInfos.length ) {
ActivityInfo ai = actInfos[position - 1];
item.name = ai.loadLabel( pm ).toString();
if( !ai.exported )
item.name += " - private";
item.attr = ai.name;
item.setIcon( ai.loadIcon( pm ) );
}
}
else if( prvInfos != null ) {
if( position <= prvInfos.length ) {
ProviderInfo pi = prvInfos[position - 1];
item.name = pi.loadLabel( pm ).toString();
item.attr = pi.name;
item.setIcon( pi.loadIcon( pm ) );
}
}
else if( srvInfos != null ) {
if( position <= srvInfos.length ) {
ServiceInfo si = srvInfos[position - 1];
item.name = si.loadLabel( pm ).toString();
item.attr = si.name;
item.setIcon( si.loadIcon( pm ) );
}
}
else if( resInfos != null ) {
try {
if( position <= resInfos.length ) {
ResolveInfo ri = resInfos[position - 1];
IntentFilter inf = ri.filter;
if( inf != null ) {
ActivityInfo ai = ri.activityInfo;
item.name = ai.loadLabel( pm ).toString();
item.attr = ai.name;
item.setIcon( ai.loadIcon( pm ) );
if( ri.filter.hasAction( Intent.ACTION_CREATE_SHORTCUT ) )
item.name += " - CREATE_SHORTCUT";
if( ri.filter.hasAction( Intent.ACTION_MAIN ) )
item.name += " - MAIN";
}
else {
item.name = ri.loadLabel( pm ).toString();
item.attr = ri.toString();
}
item.setIcon( ri.loadIcon( pm ) );
}
}
catch( Exception e ) {
Log.e( TAG, "pos=" + position, e );
}
}
else if( intFilters != null ) {
if( position <= intFilters.length ) {
IntentFilter inf = intFilters[position - 1];
String action = inf.getAction( 0 );
item.name = action != null ? action : inf.toString();
StringBuilder sb = new StringBuilder( 128 );
int n = inf.countDataTypes();
if( n > 0 ) {
sb.append( "types=" );
for( int i = 0; i< n; i++ ) {
if( i != 0 )
sb.append( ", " );
String dt = inf.getDataType( i );
sb.append( dt );
}
sb.append( "; " );
}
n = inf.countCategories();
if( n > 0 ) {
sb.append( "categories=" );
for( int i = 0; i< n; i++ ) {
if( i != 0 )
sb.append( ", " );
String ct = inf.getCategory( i );
sb.append( ct );
}
sb.append( "; " );
}
n = inf.countDataSchemes();
if( n > 0 ) {
sb.append( "schemes=" );
for( int i = 0; i< n; i++ ) {
if( i != 0 )
sb.append( ", " );
String ds = inf.getDataScheme( i );
sb.append( ds );
}
}
item.attr = sb.toString();
}
}
else {
if( position <= compItems.length )
return compItems[position-1];
}
return item;
}
@Override
protected int getPredictedAttributesLength() {
return 36; // "com.softwaremanufacturer.productname"
}
private class PackageInfoComparator implements Comparator<PackageInfo> {
int type;
boolean ascending;
ApplicationInfo.DisplayNameComparator aidnc;
public PackageInfoComparator( int type_, boolean case_ignore_, boolean ascending_ ) {
aidnc = new ApplicationInfo.DisplayNameComparator( pm );
type = type_;
ascending = ascending_;
}
@Override
public int compare( PackageInfo pi1, PackageInfo pi2 ) {
int ext_cmp = 0;
try {
switch( type ) {
case CommanderAdapter.SORT_EXT:
if( pi1.packageName != null )
ext_cmp = pi1.packageName.compareTo( pi2.packageName );
break;
case CommanderAdapter.SORT_SIZE: {
File asdf1 = new File( pi1.applicationInfo.sourceDir );
File asdf2 = new File( pi2.applicationInfo.sourceDir );
ext_cmp = asdf1.length() - asdf2.length() < 0 ? -1 : 1;
}
break;
case CommanderAdapter.SORT_DATE: {
File asdf1 = new File( pi1.applicationInfo.sourceDir );
File asdf2 = new File( pi2.applicationInfo.sourceDir );
ext_cmp = asdf1.lastModified() - asdf2.lastModified() < 0 ? -1 : 1;
}
break;
}
if( ext_cmp == 0 )
ext_cmp = aidnc.compare( pi1.applicationInfo, pi2.applicationInfo );
} catch( Exception e ) {}
return ascending ? ext_cmp : -ext_cmp;
}
}
private class ActivityInfoComparator implements Comparator<ActivityInfo> {
private int type;
private boolean ascending;
public final PackageManager pm_;
public ActivityInfoComparator( int type_, boolean case_ignore_, boolean ascending_ ) {
pm_ = pm;
type = type_;
ascending = ascending_;
}
@Override
public int compare( ActivityInfo ai1, ActivityInfo ai2 ) {
int ext_cmp = 0;
try {
switch( type ) {
case CommanderAdapter.SORT_EXT:
if( ai1.packageName != null )
ext_cmp = ai1.name.compareTo( ai2.name );
break;
}
if( ext_cmp == 0 ) {
String cn1 = ai1.loadLabel( pm_ ).toString();
String cn2 = ai2.loadLabel( pm_ ).toString();
ext_cmp = cn1.compareTo( cn2 );
}
} catch( Exception e ) {
}
return ascending ? ext_cmp : -ext_cmp;
}
}
private final void createDesktopShortcut( ComponentName cn, String name, Bitmap ico ) {
Intent shortcutIntent = new Intent();
shortcutIntent.setComponent( cn );
shortcutIntent.setData( uri );
Intent intent = new Intent();
intent.putExtra( Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent );
intent.putExtra( Intent.EXTRA_SHORTCUT_NAME, name );
if( ico != null )
intent.putExtra( Intent.EXTRA_SHORTCUT_ICON, ico );
intent.setAction( "com.android.launcher.action.INSTALL_SHORTCUT" );
ctx.sendBroadcast( intent );
}
}