package org.bbs.apklauncher.emb; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.Serializable; import java.io.StreamCorruptedException; import java.util.ArrayList; import java.util.Set; import android.app.Application; import android.content.ClipData; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; /** * < 5.0 Intent.putSerizable() do not support classloader. * * init this by IntentHelper.PersistentObject.getInstance().init() * @see {@link #PersistentObject} * * <P> * Created by bysong * */ public class IntentHelper extends android.content.Intent { public static final String TAG = IntentHelper.class.getSimpleName(); /** * type {@link boolean} */ public static final String EXTRA_INJECT = android.content.Intent.class.getName() + ".EXTRA_INJECT"; private android.content.Intent mTarget; public IntentHelper(){ mTarget = new android.content.Intent(); } public IntentHelper(android.content.Intent target) { mTarget = target; } public IntentHelper(Context context, Class clazz) { mTarget = new android.content.Intent(context, clazz); } public IntentHelper(String action) { mTarget = new Intent(action); } public IntentHelper(String action, Uri uri) { mTarget = new Intent(action, uri); } @Override public Object clone() { return mTarget.clone(); } @Override public android.content.Intent cloneFilter() { return mTarget.cloneFilter(); } @Override public String getAction() { return mTarget.getAction(); } @Override public Uri getData() { return mTarget.getData(); } @Override public String getDataString() { return mTarget.getDataString(); } @Override public String getScheme() { return mTarget.getScheme(); } @Override public String getType() { return mTarget.getType(); } @Override public String resolveType(Context context) { return mTarget.resolveType(context); } @Override public String resolveType(ContentResolver resolver) { return mTarget.resolveType(resolver); } @Override public String resolveTypeIfNeeded(ContentResolver resolver) { return mTarget.resolveTypeIfNeeded(resolver); } @Override public boolean hasCategory(String category) { return mTarget.hasCategory(category); } @Override public Set<String> getCategories() { return mTarget.getCategories(); } @Override public android.content.Intent getSelector() { return mTarget.getSelector(); } @Override public ClipData getClipData() { return mTarget.getClipData(); } @Override public void setExtrasClassLoader(ClassLoader loader) { mTarget.setExtrasClassLoader(loader); } @Override public boolean hasExtra(String name) { return mTarget.hasExtra(name); } @Override public boolean hasFileDescriptors() { return mTarget.hasFileDescriptors(); } @Override public boolean getBooleanExtra(String name, boolean defaultValue) { return mTarget.getBooleanExtra(name, defaultValue); } @Override public byte getByteExtra(String name, byte defaultValue) { return mTarget.getByteExtra(name, defaultValue); } @Override public short getShortExtra(String name, short defaultValue) { return mTarget.getShortExtra(name, defaultValue); } @Override public char getCharExtra(String name, char defaultValue) { return mTarget.getCharExtra(name, defaultValue); } @Override public int getIntExtra(String name, int defaultValue) { return mTarget.getIntExtra(name, defaultValue); } @Override public long getLongExtra(String name, long defaultValue) { return mTarget.getLongExtra(name, defaultValue); } @Override public float getFloatExtra(String name, float defaultValue) { return mTarget.getFloatExtra(name, defaultValue); } @Override public double getDoubleExtra(String name, double defaultValue) { return mTarget.getDoubleExtra(name, defaultValue); } @Override public String getStringExtra(String name) { return mTarget.getStringExtra(name); } @Override public CharSequence getCharSequenceExtra(String name) { return mTarget.getCharSequenceExtra(name); } @Override public <T extends Parcelable> T getParcelableExtra(String name) { // notSupported(); // // return mTarget.getParcelableExtra(name); Log.d(TAG, "getParcelableExtra(). name: " + name); T value = null; if (mTarget.getBooleanExtra(EXTRA_INJECT, false) == false){ value = mTarget.getParcelableExtra(name); } else { String fName = null; fName = mTarget.getStringExtra(name); if (!TextUtils.isEmpty(fName)) { value = (T) PersistentObject.getsInstance().getObject(fName); } } Log.d(TAG, "getParcelableExtra(). name: " + name + " value: " + value); return value; } @Override public Parcelable[] getParcelableArrayExtra(String name) { notSupported(); return mTarget.getParcelableArrayExtra(name); } @Override public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra( String name) { notSupported(); return mTarget.getParcelableArrayListExtra(name); } @Override public Serializable getSerializableExtra(String name) { Log.d(TAG, "getSerializableExtra(). name: " + name); String fName = mTarget.getStringExtra(name); Serializable value = null; if (!TextUtils.isEmpty(fName)) { value = (Serializable) PersistentObject.getsInstance().getObject(fName); } Log.d(TAG, "getSerializableExtra(). name: " + name + " value: " + value); return value; // return mTarget.getSerializableExtra(name); } @Override public ArrayList<Integer> getIntegerArrayListExtra(String name) { return mTarget.getIntegerArrayListExtra(name); } @Override public ArrayList<String> getStringArrayListExtra(String name) { return mTarget.getStringArrayListExtra(name); } @Override public ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) { return mTarget.getCharSequenceArrayListExtra(name); } @Override public boolean[] getBooleanArrayExtra(String name) { return mTarget.getBooleanArrayExtra(name); } @Override public byte[] getByteArrayExtra(String name) { return mTarget.getByteArrayExtra(name); } @Override public short[] getShortArrayExtra(String name) { return mTarget.getShortArrayExtra(name); } @Override public char[] getCharArrayExtra(String name) { return mTarget.getCharArrayExtra(name); } @Override public int[] getIntArrayExtra(String name) { return mTarget.getIntArrayExtra(name); } @Override public long[] getLongArrayExtra(String name) { return mTarget.getLongArrayExtra(name); } @Override public float[] getFloatArrayExtra(String name) { return mTarget.getFloatArrayExtra(name); } @Override public double[] getDoubleArrayExtra(String name) { return mTarget.getDoubleArrayExtra(name); } @Override public String[] getStringArrayExtra(String name) { return mTarget.getStringArrayExtra(name); } @Override public CharSequence[] getCharSequenceArrayExtra(String name) { return mTarget.getCharSequenceArrayExtra(name); } @Override public Bundle getBundleExtra(String name) { return mTarget.getBundleExtra(name); } @Override public Bundle getExtras() { return mTarget.getExtras(); } @Override public int getFlags() { return mTarget.getFlags(); } @Override public String getPackage() { return mTarget.getPackage(); } @Override public ComponentName getComponent() { return mTarget.getComponent(); } @Override public Rect getSourceBounds() { return mTarget.getSourceBounds(); } @Override public ComponentName resolveActivity(PackageManager pm) { return mTarget.resolveActivity(pm); } @Override public ActivityInfo resolveActivityInfo(PackageManager pm, int flags) { return mTarget.resolveActivityInfo(pm, flags); } @Override public android.content.Intent setAction(String action) { mTarget.setAction(action); return this; } @Override public android.content.Intent setData(Uri data) { mTarget.setData(data); return this; } @Override public android.content.Intent setDataAndNormalize(Uri data) { mTarget.setDataAndNormalize(data); return this; } @Override public android.content.Intent setType(String type) { mTarget.setType(type); return this; } @Override public android.content.Intent setTypeAndNormalize(String type) { mTarget.setTypeAndNormalize(type); return this; } @Override public android.content.Intent setDataAndType(Uri data, String type) { mTarget.setDataAndType(data, type); return this; } @Override public android.content.Intent setDataAndTypeAndNormalize(Uri data, String type) { mTarget.setDataAndTypeAndNormalize(data, type); return this; } @Override public android.content.Intent addCategory(String category) { mTarget.addCategory(category); return this; } @Override public void removeCategory(String category) { mTarget.removeCategory(category); } @Override public void setSelector(android.content.Intent selector) { mTarget.setSelector(selector); } @Override public void setClipData(ClipData clip) { mTarget.setClipData(clip); } @Override public android.content.Intent putExtra(String name, boolean value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, byte value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, char value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, short value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, int value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, long value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, float value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, double value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, String value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, CharSequence value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, Parcelable value) { mTarget.putExtra(name, value); notSupported(); Log.d(TAG, "putExtra(). name: " + name + " value: " + value); if (! (value instanceof Serializable)) { throw new RuntimeException("input paramater must be Serializable. value: " + value); } File f = PersistentObject.getsInstance().saveObject((Serializable) value); if (f != null) { mTarget.putExtra(name, f.getName()); } return this; } @Override public android.content.Intent putExtra(String name, Parcelable[] value) { mTarget.putExtra(name, value); notSupported(); return this; } @Override public android.content.Intent putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value) { mTarget.putParcelableArrayListExtra(name, value); notSupported(); return this; } @Override public android.content.Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) { mTarget.putIntegerArrayListExtra(name, value); return this; } @Override public android.content.Intent putStringArrayListExtra(String name, ArrayList<String> value) { mTarget.putStringArrayListExtra(name, value); return this; } @Override public android.content.Intent putCharSequenceArrayListExtra(String name, ArrayList<CharSequence> value) { mTarget.putCharSequenceArrayListExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, Serializable value) { // mTarget.putExtra(name, value); Log.d(TAG, "putExtra(). name: " + name + " value: " + value); File f = PersistentObject.getsInstance().saveObject(value); if (f != null) { mTarget.putExtra(name, f.getName()); } return this; } @Override public android.content.Intent putExtra(String name, boolean[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, byte[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, short[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, char[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, int[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, long[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, float[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, double[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, String[] value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtra(String name, CharSequence[] value) { return mTarget.putExtra(name, value); } @Override public android.content.Intent putExtra(String name, Bundle value) { mTarget.putExtra(name, value); return this; } @Override public android.content.Intent putExtras(android.content.Intent src) { mTarget.putExtras(src); return this; } @Override public android.content.Intent putExtras(Bundle extras) { mTarget.putExtras(extras); return this; } @Override public android.content.Intent replaceExtras(android.content.Intent src) { mTarget.replaceExtras(src); return this; } @Override public android.content.Intent replaceExtras(Bundle extras) { mTarget.replaceExtras(extras); return this; } @Override public void removeExtra(String name) { mTarget.removeExtra(name); } @Override public android.content.Intent setFlags(int flags) { mTarget.setFlags(flags); return this; } @Override public android.content.Intent addFlags(int flags) { mTarget.addFlags(flags); return this; } @Override public android.content.Intent setPackage(String packageName) { mTarget.setPackage(packageName); return this; } @Override public android.content.Intent setComponent(ComponentName component) { mTarget.setComponent(component); return this; } @Override public android.content.Intent setClassName(Context packageContext, String className) { mTarget.setClassName(packageContext, className); return this; } @Override public android.content.Intent setClassName(String packageName, String className) { mTarget.setClassName(packageName, className); return this; } @Override public android.content.Intent setClass(Context packageContext, Class<?> cls) { mTarget.setClass(packageContext, cls); return this; } @Override public void setSourceBounds(Rect r) { mTarget.setSourceBounds(r); } @Override public int fillIn(android.content.Intent other, int flags) { return mTarget.fillIn(other, flags); } @Override public boolean filterEquals(android.content.Intent other) { return mTarget.filterEquals(other); } @Override public int filterHashCode() { return mTarget.filterHashCode(); } @Override public String toString() { return mTarget.toString(); } @Override public String toURI() { return mTarget.toURI(); } @Override public String toUri(int flags) { return mTarget.toUri(flags); } @Override public int describeContents() { return mTarget.describeContents(); } @Override public void writeToParcel(Parcel out, int flags) { mTarget.writeToParcel(out, flags); } @Override public void readFromParcel(Parcel in) { mTarget.readFromParcel(in); } void notSupported() { throw new RuntimeException("not supported. you can use putExtra(String,Serializable) instead."); } public static class PersistentObject { private static final String TAG = PersistentObject.class.getSimpleName(); private File mDir; private ClassLoader mClassLoader; private boolean mHasInit; private static PersistentObject sInstance; /** * * @return * * @see #init(Application, ClassLoader) */ public static PersistentObject getsInstance() { if (null == sInstance) { sInstance = new PersistentObject(); } return sInstance; } private PersistentObject(){ } public void init(Context context, ClassLoader classLoader){ if (mHasInit) { Log.i(TAG, "has inited, ignore."); return; } mDir = context.getDir("intent_helper", Context.MODE_WORLD_READABLE); mClassLoader = classLoader; // clean last object // for (File f : mDir.listFiles()){ // f.delete(); // } mHasInit = true; } public File saveObject(Serializable s){ makeSureInited(); File f = null; try { f = File.createTempFile(s.getClass().getName(), ".object", mDir); Log.d(TAG, "saveObject. fileName: " + f.getPath() + " data: " + s); ObjectOutputStream oop = new ObjectOutputStream(new FileOutputStream(f)); oop.writeObject(s); oop.flush(); oop.close(); } catch (IOException e) { e.printStackTrace(); } f.deleteOnExit(); return f; } private void makeSureInited() { if (!mHasInit) { throw new RuntimeException("you must init " + TAG + " with init(Application, ClassLoader)."); } } public Object getObject(String serialFile){ makeSureInited(); File file = new File(mDir, serialFile); Log.d(TAG, "getObject. fileName: " + file.getPath()); Object o = null; try { ObjectInputStream oin = new OIS(new FileInputStream(file)); o = oin.readObject(); oin.close(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return o; } class OIS extends ObjectInputStream { public OIS(InputStream input) throws StreamCorruptedException, IOException { super(input); } @Override protected Class<?> resolveClass(ObjectStreamClass osClass) throws IOException, ClassNotFoundException { try { return super.resolveClass(osClass); } catch (ClassNotFoundException e){ return mClassLoader.loadClass(osClass.getName()); } } } } }