package com.cradle.iitc_mobile.share; 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.net.Uri; import com.cradle.iitc_mobile.Log; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashSet; import java.util.List; public class IntentGenerator { private static final String EXTRA_FLAG_IS_DEFAULT = "IITCM_IS_DEFAULT"; private static final String EXTRA_FLAG_TITLE = "IITCM_TITLE"; private static final HashSet KNOWN_COPY_HANDLERS = new HashSet(); static { if (KNOWN_COPY_HANDLERS.isEmpty()) { KNOWN_COPY_HANDLERS.add(new ComponentName( "com.google.android.apps.docs", "com.google.android.apps.docs.app.SendTextToClipboardActivity")); KNOWN_COPY_HANDLERS.add(new ComponentName( "com.aokp.romcontrol", "com.aokp.romcontrol.ShareToClipboard")); } } public static String getTitle(final Intent intent) throws IllegalArgumentException { if (intent.hasExtra(EXTRA_FLAG_TITLE)) return intent.getStringExtra(EXTRA_FLAG_TITLE); throw new IllegalArgumentException("Got an intent not generated by IntentGenerator!\n" + "Intent:\n" + intent.toString() + "\n" + "Extras:\n" + intent.getExtras().toString()); } public static boolean isDefault(final Intent intent) { return intent.hasExtra(EXTRA_FLAG_IS_DEFAULT) && intent.getBooleanExtra(EXTRA_FLAG_IS_DEFAULT, false); } private final Context mContext; private final PackageManager mPackageManager; public IntentGenerator(final Context context) { mContext = context; mPackageManager = mContext.getPackageManager(); } private boolean containsCopyIntent(final List targets) { for (final Intent intent : targets) { for (final ComponentName handler : KNOWN_COPY_HANDLERS) { if (handler.equals(intent.getComponent())) return true; } } return false; } private ArrayList resolveTargets(final Intent intent) { final String packageName = mContext.getPackageName(); final List activityList = mPackageManager.queryIntentActivities(intent, 0); final ResolveInfo defaultTarget = mPackageManager.resolveActivity(intent, 0); final ArrayList list = new ArrayList(activityList.size()); for (final ResolveInfo resolveInfo : activityList) { final ActivityInfo activity = resolveInfo.activityInfo; final ComponentName component = new ComponentName(activity.packageName, activity.name); // remove IITCm from list (we only want other apps) if (activity.packageName.equals(packageName)) continue; // bug in package manager. not exported activities shouldn't even appear here // (usually you would have to compare the package name as well, but since we ignore our own activities, // this isn't necessary) if (!activity.exported) continue; final Intent targetIntent = new Intent(intent) .setComponent(component) .putExtra(EXTRA_FLAG_TITLE, activity.loadLabel(mPackageManager)); if (resolveInfo.activityInfo.name.equals(defaultTarget.activityInfo.name) && resolveInfo.activityInfo.packageName.equals(defaultTarget.activityInfo.packageName)) { targetIntent.putExtra(EXTRA_FLAG_IS_DEFAULT, true); } list.add(targetIntent); } return list; } public void cleanup(final Intent intent) { intent.removeExtra(EXTRA_FLAG_IS_DEFAULT); intent.removeExtra(EXTRA_FLAG_TITLE); } public ArrayList getBrowserIntents(final String title, final String url) { final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); return resolveTargets(intent); } public ArrayList getGeoIntents(final String title, final String mLl, final int mZoom) { final Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(String.format("geo:%s?z=%d", mLl, mZoom))) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); final ArrayList targets = resolveTargets(intent); // According to https://developer.android.com/guide/components/intents-common.html, markers can be labeled. // Unfortunately, only Google Maps supports this, most other apps fail for (final Intent target : targets) { final ComponentName cn = target.getComponent(); if ("com.google.android.apps.maps".equals(cn.getPackageName())) { try { final String encodedTitle = URLEncoder.encode(title, "UTF-8"); target.setData(Uri.parse(String.format("geo:0,0?q=%s%%20(%s)&z=%d", mLl, encodedTitle, mZoom))); } catch (final UnsupportedEncodingException e) { Log.w(e); } break; } } return targets; } public ArrayList getShareIntents(final String title, final String text) { final Intent intent = new Intent(Intent.ACTION_SEND) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) .setType("text/plain") .putExtra(Intent.EXTRA_TEXT, text) .putExtra(Intent.EXTRA_SUBJECT, title); final ArrayList targets = resolveTargets(intent); if (!containsCopyIntent(targets)) { // add SendToClipboard intent in case Drive is not installed Intent copyToClipboardIntent = new Intent(intent); copyToClipboardIntent.setComponent(new ComponentName(mContext, SendToClipboard.class)); ResolveInfo activity = mPackageManager.resolveActivity(copyToClipboardIntent, 0); copyToClipboardIntent.putExtra(EXTRA_FLAG_TITLE, activity.loadLabel(mPackageManager)); targets.add(copyToClipboardIntent); } return targets; } }