package com.nolanlawson.logcat.data;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.ClipboardManager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.nolanlawson.logcat.R;
import com.nolanlawson.logcat.util.UtilLogger;
/**
* Adapter that shows any apps in the system that respond to Intent.ACTION_SEND intents. Filters out any apps in
* the FILTER_LIST and, as a bonus, adds the option to just copy the body text to the clipboard.
* @author nlawson
*
*/
public class SenderAppAdapter extends ArrayAdapter<ResolveInfo> {
// used to exclude facebook, but don't need to anymore because it works again
public static final Set<String> FILTER_SET = Collections.emptySet();
private static UtilLogger log = new UtilLogger(SenderAppAdapter.class);
private Context mContext;
public SenderAppAdapter(Context context, boolean addClipboard, SendLogDetails.AttachmentType attachmentType) {
super(context, R.layout.chooser_row, new ArrayList<ResolveInfo>());
mContext = getContext();
List<ResolveInfo> items = createItems(addClipboard, attachmentType);
for (ResolveInfo item : items) {
add(item);
}
}
public void respondToClick(int position, String subject, String body, SendLogDetails.AttachmentType attachmentType, File attachment) {
ResolveInfo launchable = getItem(position);
ActivityInfo activity=launchable.activityInfo;
if (launchable instanceof DummyClipboardLaunchable) {
ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(body);
Toast.makeText(mContext, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show();
} else {
ComponentName name= new ComponentName(activity.applicationInfo.packageName, activity.name);
Intent actionSendIntent= createSendIntent(subject, body, attachmentType, attachment);
actionSendIntent.setComponent(name);
mContext.startActivity(actionSendIntent);
}
}
private List<ResolveInfo> createItems(boolean addClipboard, SendLogDetails.AttachmentType attachmentType) {
List<ResolveInfo> items = mContext.getPackageManager().queryIntentActivities(createDummyIntent(attachmentType), 0);
log.d("items are: %s", items);
filter(items);
Collections.sort(items, new ResolveInfo.DisplayNameComparator(mContext.getPackageManager()));
if (addClipboard) {
items.add(0, new DummyClipboardLaunchable());
}
log.d("items are: %s", items);
return items;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView==null) {
convertView=newView(parent);
}
bindView(position, convertView);
return(convertView);
}
private View newView(ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return inflater.inflate(R.layout.chooser_row, parent, false);
}
private void bindView(int position, View row) {
PackageManager packageManager = mContext.getPackageManager();
ResolveInfo item = getItem(position);
TextView label=(TextView)row.findViewById(android.R.id.title);
label.setText(item.loadLabel(packageManager));
ImageView iconImageView=(ImageView)row.findViewById(android.R.id.icon);
Drawable drawableIcon = item.loadIcon(packageManager);
if (drawableIcon != null) {
Bitmap iconBitmap = resizeBitmap(drawableIcon);
iconImageView.setImageBitmap(iconBitmap);
iconImageView.setVisibility(View.VISIBLE);
} else {
iconImageView.setVisibility(View.INVISIBLE);
}
}
private void filter(List<ResolveInfo> apps) {
for (Iterator<ResolveInfo> iter = apps.iterator(); iter.hasNext();) {
ResolveInfo resolveInfo = iter.next();
if (FILTER_SET.contains(resolveInfo.activityInfo.name)) {
// forget facebook - it doesn't work with anything but URLs
iter.remove();
}
}
}
/**
* Create an intent just for querying available apps.
* @param moreThanOneAttachment
* @return
*/
private static Intent createDummyIntent(SendLogDetails.AttachmentType attachmentType) {
Intent actionSendIntent = new Intent(android.content.Intent.ACTION_SEND);
actionSendIntent.setType(attachmentType.getMimeType());
return actionSendIntent;
}
private static Intent createSendIntent(String subject, String body, SendLogDetails.AttachmentType attachmentType, File attachment) {
String action = android.content.Intent.ACTION_SEND;
Intent actionSendIntent = new Intent(action);
actionSendIntent.setType(attachmentType.getMimeType());
actionSendIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
if (!TextUtils.isEmpty(body)) {
actionSendIntent.putExtra(Intent.EXTRA_TEXT, body);
}
if (attachment != null) {
Uri uri = Uri.fromFile(attachment);
log.d("uri is: %s", uri);
actionSendIntent.putExtra(Intent.EXTRA_STREAM, uri);
}
return actionSendIntent;
}
private Bitmap resizeBitmap(Drawable drawable) {
// resize the icon bitmap, because sometimes, seemingly randomly, an icon from the PackageManager
// will be too large
int iconSize = mContext.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
Bitmap bmp = Bitmap.createBitmap(iconSize, iconSize, Config.ARGB_8888);
Canvas c = new Canvas(bmp);
drawable.setBounds(new Rect(0,0,iconSize,iconSize));
drawable.draw(c);
return bmp;
}
private class DummyClipboardLaunchable extends ResolveInfo {
public Drawable loadIcon(PackageManager pm) {
return null;
}
public CharSequence loadLabel(PackageManager pm) {
return mContext.getResources().getString(R.string.copy_to_clipboard);
}
public String toString() {
return "Dummy";
}
}
}