package com.openfarmanager.android.adapters; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Intent; import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageManager; import android.content.pm.PackageStats; import android.content.pm.ResolveInfo; import android.graphics.Color; import android.graphics.Typeface; import android.net.Uri; import android.os.AsyncTask; import android.os.Environment; import android.os.Handler; import android.os.RemoteException; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import com.openfarmanager.android.App; import com.openfarmanager.android.R; import com.openfarmanager.android.filesystem.FileProxy; import com.openfarmanager.android.fragments.GenericPanel; import com.openfarmanager.android.fragments.MainPanel; import com.openfarmanager.android.model.Bookmark; import com.openfarmanager.android.model.FileActionEnum; import com.openfarmanager.android.utils.FileUtilsExt; import com.openfarmanager.android.view.ToastNotification; import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Semaphore; import rx.Observable; import rx.Observer; import rx.Subscriber; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; import rx.schedulers.Schedulers; import rx.subscriptions.CompositeSubscription; public class LauncherAdapter extends FileSystemAdapter { private Handler mHandler; private List<String> mSelectedPackages = new ArrayList<String>(); private CompositeSubscription mSubscription; public LauncherAdapter(Handler handler, CompositeSubscription subscription) { mHandler = handler; mSubscription = subscription; refresh(); } public void refresh() { mSelectedPackages.clear(); mHandler.sendEmptyMessage(GenericPanel.START_LOADING); Subscription subscription = Observable.create(new Observable.OnSubscribe<List<FileProxy>>() { @Override public void call(final Subscriber<? super List<FileProxy>> subscriber) { List<FileProxy> result = new LinkedList<FileProxy>(); final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); final PackageManager manager = App.sInstance.getPackageManager(); final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0); if (apps != null) { for (ResolveInfo info : apps) { ComponentName componentName = new ComponentName(info.activityInfo.applicationInfo.packageName, info.activityInfo.name); ComponentProxy applicationInfo = new ComponentProxy(); applicationInfo.mComponentName = componentName; applicationInfo.mName = String.valueOf(info.loadLabel(manager)); applicationInfo.mPackagePath = info.activityInfo.applicationInfo.sourceDir; if (TextUtils.isEmpty(applicationInfo.mName)) { applicationInfo.mName = info.activityInfo.name; } result.add(applicationInfo); } } Collections.sort(result, new Comparator<FileProxy>() { @Override public int compare(FileProxy applicationInfo, FileProxy applicationInfo2) { return applicationInfo.getName().compareToIgnoreCase(applicationInfo2.getName()); } }); subscriber.onNext(result); } }).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<List<FileProxy>>() { @Override public void call(List<FileProxy> result) { mFiles = result; notifyDataSetChanged(); mHandler.sendEmptyMessage(GenericPanel.STOP_LOADING); populateApplicationSize(); } }); mSubscription.add(subscription); } private void populateApplicationSize() { Subscription subscription = Observable.create(new Observable.OnSubscribe<Void>() { @Override public void call(final Subscriber<? super Void> subscriber) { try { final PackageManager manager = App.sInstance.getPackageManager(); Method getPackageSizeInfo = manager.getClass().getMethod("getPackageSizeInfo", String.class, IPackageStatsObserver.class); final Semaphore codeSizeSemaphore = new Semaphore(1, true); for (FileProxy param : mFiles) { try { codeSizeSemaphore.acquire(); } catch (InterruptedException e) { e.printStackTrace(System.err); } final FileProxy final_param = param; getPackageSizeInfo.invoke(manager, ((ComponentProxy) param).mComponentName.getPackageName(), new IPackageStatsObserver.Stub() { public void onGetStatsCompleted(PackageStats pStats, boolean succeedded) throws RemoteException { ((ComponentProxy) final_param).mSize = pStats.codeSize + pStats.dataSize; codeSizeSemaphore.release(); if (!subscriber.isUnsubscribed()) { subscriber.onNext(null); } } }); } } catch (Exception e) { e.printStackTrace(System.err); } } }).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Void>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Void aVoid) { notifyDataSetChanged(); } }); mSubscription.add(subscription); } public void setSelectedFiles(List<FileProxy> selectedFiles) { super.setSelectedFiles(selectedFiles); mSelectedPackages.clear(); for (FileProxy proxy : selectedFiles) { mSelectedPackages.add(proxy.getId()); } } @Override public int getItemCount() { return mFiles.size(); } @Override public FileProxy getItem(int i) { return mFiles.get(i); } @Override public long getItemId(int i) { return i; } @Override protected void bindView(ViewHolder holder, final int position) { FileProxy info = getItem(position); holder.name.setText(info.getName()); holder.info.setText(info.getSize() > 0 ? FileUtilsExt.byteCountToDisplaySize(info.getSize()) : null); holder.configureCell(App.sInstance.getSettings()); holder.name.setTextColor(mSelectedPackages.contains(info.getId()) ? App.sInstance.getSettings().getSelectedColor() : App.sInstance.getSettings().getInstallColor()); // int size = App.sInstance.getSettings().getMainPanelFontSize(); // holder.name.setTextSize(TypedValue.COMPLEX_UNIT_SP, size); // holder.info.setTextSize(TypedValue.COMPLEX_UNIT_SP, size); // to adjust item size // // Typeface typeface = App.sInstance.getSettings().getMainPanelFontType(); // holder.name.setTypeface(typeface); // holder.info.setTypeface(typeface); } public void onItemClick(int i) { try { final PackageManager manager = App.sInstance.getPackageManager(); Intent intent = manager.getLaunchIntentForPackage(getItem(i).getFullPath()); App.sInstance.startActivity(intent); } catch (Exception e) { e.printStackTrace(); ToastNotification.makeText(App.sInstance.getApplicationContext(), App.sInstance.getString(R.string.error_can_t_open_app), Toast.LENGTH_LONG).show(); } } public FileActionEnum[] getAvailableActions() { if (mSelectedFiles.size() > 1) { return new FileActionEnum[]{ FileActionEnum.DELETE, FileActionEnum.SHARE }; } else { return new FileActionEnum[]{ FileActionEnum.OPEN, FileActionEnum.INFO, FileActionEnum.DELETE, FileActionEnum.SHARE }; } } public void executeAction(final FileActionEnum action, MainPanel inactivePanel) { if (mSelectedFiles.isEmpty()) { return; } Intent intent; String fullPath = mSelectedFiles.get(0).getFullPath(); switch (action) { case OPEN: final PackageManager manager = App.sInstance.getPackageManager(); App.sInstance.startActivity(manager.getLaunchIntentForPackage(fullPath)); break; case INFO: try { intent = new Intent() .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", fullPath, null)); App.sInstance.startActivity(intent); } catch (ActivityNotFoundException e) { e.printStackTrace(); ToastNotification.makeText(App.sInstance, App.sInstance.getString(R.string.error_not_supported), Toast.LENGTH_LONG).show(); } break; case DELETE: for (FileProxy file : mSelectedFiles) { doDelete(file.getFullPath()); } break; case SHARE: intent = new Intent(Intent.ACTION_SEND_MULTIPLE); intent.setType("text/plain"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ArrayList<Uri> files = new ArrayList<Uri>(); for (FileProxy file : mSelectedFiles) { File f = new File(file.getParentPath()); Uri uri = Uri.fromFile(f); files.add(uri); } intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, files); App.sInstance.startActivity(intent); break; } } private void doDelete(String fullPath) { try { Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package", fullPath, null)). setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); App.sInstance.startActivity(uninstallIntent); } catch (ActivityNotFoundException e) { e.printStackTrace(); ToastNotification.makeText(App.sInstance, App.sInstance.getString(R.string.error_not_supported), Toast.LENGTH_LONG).show(); } } public class ComponentProxy implements FileProxy<ComponentProxy> { private ComponentName mComponentName; private String mName; private String mPackagePath; private long mSize; @Override public String getId() { return getFullPath(); } @Override public String getName() { return mName; } @Override public boolean isDirectory() { return false; } @Override public long getSize() { return mSize; } @Override public long lastModifiedDate() { return 0; } @Override public List<ComponentProxy> getChildren() { return null; } @Override public String getFullPath() { return mComponentName.getPackageName(); } @Override public String getFullPathRaw() { return mComponentName.getPackageName(); } @Override public String getParentPath() { return mPackagePath; } @Override public boolean isUpNavigator() { return false; } @Override public boolean isRoot() { return false; } @Override public boolean isVirtualDirectory() { return false; } @Override public boolean isBookmark() { return false; } @Override public Bookmark getBookmark() { return null; } @Override public String getMimeType() { return null; } } }