/* * Copyright 2012 The Stanford MobiSocial Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package mobisocial.musubi.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import mobisocial.musubi.objects.AppObj; import mobisocial.musubi.objects.PictureObj; import mobisocial.musubi.objects.StatusObj; import mobisocial.musubi.objects.StoryObj; import mobisocial.musubi.objects.WebAppObj; import mobisocial.musubi.provider.MusubiContentProvider; import mobisocial.musubi.ui.SendContentActivity; import mobisocial.musubi.util.OGUtil.OGData; import mobisocial.socialkit.Obj; import mobisocial.socialkit.obj.MemObj; import org.json.JSONException; import org.json.JSONObject; import android.app.ActivityManager; import android.app.ActivityManager.RecentTaskInfo; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.util.Patterns; import android.webkit.MimeTypeMap; import android.widget.Toast; public class ObjFactory { public final static String TAG = "ObjFromIntent"; public static Obj objForSendIntent(final Context context, Intent intent) { Obj obj = null; String type = intent.getType(); if (hasImage(intent)) { try { Uri uri = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM); // XXX copy data into Corral? obj = PictureObj.from(context, uri, true); } catch (IOException e) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast.makeText(context, "Remote image sources not supported", Toast.LENGTH_SHORT).show(); } }); Log.e(TAG, "Couldn't load picture", e); return null; } } else if (type.startsWith("vnd.mobisocial.obj/")) { if (intent.hasExtra("json")) { String objType = type.replace("vnd.mobisocial.obj/", ""); try { obj = new MemObj(objType, new JSONObject(intent.getStringExtra("json"))); } catch (JSONException e) { return null; } } return null; } else { Uri data = intent.getData(); String mime = intent.getType(); CharSequence charSequence = intent.getCharSequenceExtra(Intent.EXTRA_TEXT); String txt = charSequence == null ? null : charSequence.toString(); Uri uri; if (data != null) { uri = data; } else if (txt != null) { uri = extractFirstUri(txt); } else { return null; } if(uri != null) { obj = handleSendURLObj(intent, mime, txt, uri); } else if(txt != null){ obj = StatusObj.from(txt); } else { return null; } } if (obj != null) { String callerAppId = getCallerAppId(context, intent); if (obj.getJson() != null && callerAppId != null) { try { obj.getJson().put(AppObj.ANDROID_PACKAGE_NAME, callerAppId); obj.getJson().put(AppObj.CLAIMED_APP_ID, callerAppId); try { PackageManager pm = context.getPackageManager(); PackageInfo info = pm.getPackageInfo(callerAppId, 0); String appName = info.applicationInfo.loadLabel(pm).toString(); obj.getJson().put(AppObj.APP_NAME, appName); } catch (NameNotFoundException e) { Log.w(TAG, "package not found", e); } } catch (JSONException e) { throw new RuntimeException(e); } } } return obj; } public static Obj objForText(String text) { String trim = text.trim(); if (Patterns.WEB_URL.matcher(trim).matches()) { return handleSendURLObj(null, null, null, Uri.parse(trim)); } else { return StatusObj.from(text); } } static Obj handleSendURLObj(Intent intent, String mime, String txt, Uri uri) { if (uri.getPath() != null && uri.getPath().contains("/musubi/app")) { return WebAppObj.forUri(uri); } String url = uri.toString(); String original_url = url; String title = null; byte[] thumbnail_bytes = null; byte[] favicon_bytes = null; if (intent != null) { if (intent.hasExtra(Intent.EXTRA_SUBJECT)) { title = intent.getStringExtra(Intent.EXTRA_SUBJECT); } Bitmap favicon = null; if (intent.hasExtra("share_favicon")) { favicon = (Bitmap)intent.getParcelableExtra("share_favicon"); } if(favicon != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); favicon.compress(Bitmap.CompressFormat.PNG, 100, baos); //bm is the bitmap object favicon_bytes = baos.toByteArray(); } Bitmap thumbnail = null; if (intent.hasExtra(Intent.EXTRA_SHORTCUT_ICON)) { thumbnail = (Bitmap)intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON); } if(thumbnail != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); thumbnail.compress(Bitmap.CompressFormat.PNG, 100, baos); //bm is the bitmap object thumbnail_bytes = baos.toByteArray(); } } OGData og = OGUtil.getOrGuess(url); if (og == null && txt == null && title == null && thumbnail_bytes == null && url != null) { return StatusObj.from(url); } if(og != null) { if(og.mImage != null) thumbnail_bytes = og.mImage; if(og.mDescription != null) txt = og.mDescription; if(og.mMimeType != null) mime = og.mMimeType; if(title == null && og.mTitle != null) title = og.mTitle; if(og.mUrl != null) url = og.mUrl; } //get rid of crap where people send us the same thing under several extras if(txt != null && txt.equals(url)) { txt = null; } if(title != null && title.equals(url)) { title = null; } if((txt != null || title != null) && thumbnail_bytes != null) { //only send a big picture if we have nothing else to send Bitmap b = BitmapFactory.decodeByteArray(thumbnail_bytes, 0, thumbnail_bytes.length); int w = b.getWidth(); int h = b.getHeight(); if(w > h) { h = h * Math.min(100, w) / w; w = Math.min(100, w); } else { w = w * Math.min(100, h) / h; h = Math.min(100, h); } Bitmap b2 = Bitmap.createScaledBitmap(b, w, h, true); b.recycle(); b = b2; ByteArrayOutputStream baos = new ByteArrayOutputStream(); b.compress(Bitmap.CompressFormat.PNG, 100, baos); //bm is the bitmap object thumbnail_bytes = baos.toByteArray(); b.recycle(); } return StoryObj.from(original_url, url, mime, txt, title, favicon_bytes, thumbnail_bytes); } public static String getCallerAppId(Context context, Intent intent) { final String SUPER = MusubiContentProvider.SUPER_APP_ID; ActivityManager manager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningTaskInfo> running = manager.getRunningTasks(1); if (running.size() > 0) { RunningTaskInfo thisTask = running.get(0); String pkg = thisTask.baseActivity.getPackageName(); if (!SUPER.equals(pkg)) { return pkg; } else if (SUPER.equals(intent.getStringExtra(SendContentActivity.EXTRA_CALLING_APP))) { return SUPER; } } // The sending activity issued the SEND intent with FLAG_ACTIVITY_NEW_TASK. List<RecentTaskInfo> infos = manager.getRecentTasks(2, 0); if (infos.size() == 0) { Log.w(TAG, "couldn't get info"); return null; } RecentTaskInfo task = infos.get(0); if (SUPER.equals(task.baseIntent.getComponent().getPackageName()) && infos.size() > 1) { task = infos.get(1); } Intent base = task.baseIntent; return base.getComponent().getPackageName(); } static final Pattern schemePattern = Pattern.compile("\\b[-0-9a-zA-Z+\\.]+:\\S+"); static Uri extractFirstUri(String text) { Matcher m = schemePattern.matcher(text); while(m.find()) { Uri uri = Uri.parse(m.group()); String scheme = uri.getScheme(); if (scheme != null && (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https"))) { return uri; } } return null; } private static boolean hasImage(Intent intent) { if (intent.getType().startsWith("image/")) { return true; } if (intent.hasExtra(Intent.EXTRA_STREAM)) { Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString()); if (extension.equals("jpg") || extension.equals("png")) { return true; } } return false; } }