package org.bbs.osgi.activity;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
/**
* all method will call through {@link #mTargetActivity}, so, we can
* "embed' an exist activity to {@link BundleActivity}.
* @author luoqii
*
* @see {@link BundleActivity}
*
*/
public abstract class EmbeddedActivityAgent extends ActivityAgent {
private static final String TAG = EmbeddedActivityAgent.class.getSimpleName();
protected Activity mTargetActivity;
public abstract Activity getTargetActivity();
protected void onCreate(Bundle savedInstanceState) {
mTargetActivity = getTargetActivity();
// prepare new activity.
// ActivityUtil.attach(mHostActivity, mTargetActivity);
ActivityUtil.attachBaseContext(mTargetActivity, mHostActivity.getApplication());
ActivityUtil.copyFields(mHostActivity, mTargetActivity);
ActivityUtil.onCreate(mTargetActivity, savedInstanceState);
}
protected void onResume() {
ActivityUtil.onResume(mTargetActivity);
}
protected void onPause() {
ActivityUtil.onPause(mTargetActivity);
}
protected void onDestroy() {
ActivityUtil.onDestroy(mTargetActivity);
}
public boolean onPreparePanel(int arg0, View arg1, Menu arg2) {
return mTargetActivity.onPreparePanel(arg0, arg1, arg2);
}
public boolean onPrepareOptionsMenu(Menu menu) {
return mTargetActivity.onPrepareOptionsMenu(menu);
}
public boolean onCreateOptionsMenu(Menu menu) {
return mTargetActivity.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return mTargetActivity.onOptionsItemSelected(item);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
mTargetActivity.onCreateContextMenu(menu, v, menuInfo);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
return mTargetActivity.onContextItemSelected(item);
}
@Override
public void onContextMenuClosed(Menu menu) {
mTargetActivity.onContextMenuClosed(menu);
}
public void onActivityResult(int arg0, int arg1, Intent arg2) {
ActivityUtil.onActivityResult(mTargetActivity, arg0, arg1, arg2);
}
/**
* keep function name consistency with {@link Activity}
*
* @author bysong
*
*/
public static class ActivityUtil {
public static void onCreate(Activity activity, Bundle savedInstanceState){
try {
Method m = Activity.class.getDeclaredMethod("onCreate", new Class[]{Bundle.class});
m.setAccessible(true);
m.invoke(activity, new Object[]{savedInstanceState});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void onResume(Activity activity){
try {
Method m = Activity.class.getDeclaredMethod("onResume", (Class[]) null);
m.setAccessible(true);
m.invoke(activity, (Object[]) null);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void onPause(Activity activity){
try {
Method m = Activity.class.getDeclaredMethod("onPause", (Class[]) null);
m.setAccessible(true);
m.invoke(activity, (Object[]) null);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void onDestroy(Activity activity){
try {
Method m = Activity.class.getDeclaredMethod("onResume", (Class[])null);
m.setAccessible(true);
m.invoke(activity, (Object[])null);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void onResume(Activity activity, Bundle savedInstanceState){
try {
Method m = Activity.class.getDeclaredMethod("onResume", new Class[]{Bundle.class});
m.setAccessible(true);
m.invoke(activity, new Object[]{savedInstanceState});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void onContextMenuClosed(Activity activity,
Menu menu) {
try {
Method m = Activity.class.getDeclaredMethod("onContextMenuClosed", new Class[]{Menu.class});
m.setAccessible(true);
m.invoke(activity, new Object[]{menu});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean onContextItemSelected(Activity activity,
MenuItem item) {
try {
Method m = Activity.class.getDeclaredMethod("onContextItemSelected", new Class[]{MenuItem.class});
m.setAccessible(true);
return (Boolean) m.invoke(activity, new Object[]{item});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public static void onCreateContextMenu(Activity activity,
ContextMenu menu, View v, ContextMenuInfo menuInfo) {
try {
Method m = Activity.class.getDeclaredMethod("onCreateContextMenu", new Class[]{ContextMenu.class, View.class, ContextMenuInfo.class});
m.setAccessible(true);
m.invoke(activity, new Object[]{menu, v, menuInfo});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void onActivityResult(Activity activity, int arg0,
int arg1, Intent arg2) {
try {
Method m = Activity.class.getDeclaredMethod("onActivityResult", new Class[]{int.class, int.class, Intent.class});
m.setAccessible(true);
m.invoke(activity, new Object[]{arg0, arg1, arg2});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean onOptionsItemSelected(Activity activity, MenuItem item) {
try {
Method m = Activity.class.getDeclaredMethod("onOptionsItemSelected", new Class[]{MenuItem.class});
m.setAccessible(true);
return (Boolean) m.invoke(activity, new Object[]{item});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public static boolean onCreateOptionsMenu(Activity activity, Menu menu) {
try {
Method m = Activity.class.getDeclaredMethod("onCreateOptionsMenu", new Class[]{Menu.class});
return (Boolean) m.invoke(activity, new Object[]{menu});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public static void attach(Activity hostActivity,
Activity embeddedActivity) {
try {
Method[] methods = Activity.class.getDeclaredMethods();
for (Method m: methods) {
if (m.getName().startsWith("attach")) {
Log.d(TAG, "method name: " + m.getName());
Log.d(TAG, "paramter: [");
Class<?>[] parameterTypes = m.getParameterTypes();
for (Class p : parameterTypes) {
Log.d(TAG, "" + p.getCanonicalName());
}
Log.d(TAG, "]");
}
}
/*
* final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, IVoiceInteractor voiceInteractor) {
*/
Class<Object>[] parameters = new Class[]{Context.class, Class.forName("android.app.ActivityThread"),
Class.forName("android.app.Instrumentation"), Class.forName("android.os.IBinder"), int.class, Application.class,
Intent.class,
Class.forName("android.content.pm.ActivityInfo"),
// Class.forName("android.os.IBinder"),
CharSequence.class,
Activity.class,
String.class,
Class.forName("android.app.Activity$NonConfigurationInstances"),
Configuration.class,
Class.forName("com.android.internal.app.IVoiceInteractor")
};
Method m = Activity.class.getDeclaredMethod("attach", parameters);
m.setAccessible(true);
Object[] args = new Object[]{
hostActivity.getBaseContext(),
getFiledValue(hostActivity, "mMainThread"),
getFiledValue(hostActivity, "mInstrumentation"),
getFiledValue(hostActivity, "mToken"),
getFiledValue(hostActivity, "mIdent"),
getFiledValue(hostActivity, "mApplication"),
getFiledValue(hostActivity, "mIntent"),
getFiledValue(hostActivity, "mActivityInfo"),
getFiledValue(hostActivity, "mTitle"),
getFiledValue(hostActivity, "mParent"),
getFiledValue(hostActivity, "mEmbeddedID"),
getFiledValue(hostActivity, "mLastNonConfigurationInstances"),
getFiledValue(hostActivity, "mCurrentConfig"),
null};
m.invoke(embeddedActivity, args );
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void attachBaseContext(Activity activity,
Application application) {
try {
Method m = ContextWrapper.class.getDeclaredMethod("attachBaseContext", new Class[]{Context.class});
m.setAccessible(true);
m.invoke(activity, new Object[]{application});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void copyFields(Activity host, Activity target) {
String[] fields = new String[] {
"mMainThread",
"mInstrumentation",
"mToken",
"mIdent",
"mApplication",
"mIntent",
"mActivityInfo",
"mTitle",
"mParent",
"mEmbeddedID",
"mLastNonConfigurationInstances",
"mFragments",// java.lang.IllegalStateException
// FragmentManagerImpl.moveToState
"mWindow",
"mWindowManager",
"mCurrentConfig"
};
copyFields(Activity.class, fields, host, target);
fields = new String[] {
// "mBase", // android.content.ContextWrapper
};
copyFields(ContextWrapper.class, fields, host, target);
try {
LayoutInflater in = LayoutInflater.from(host);
Field inflator = Class.forName("com.android.internal.policy.impl.PhoneWindow").getDeclaredField("mLayoutInflater");
inflator.setAccessible(true);
Object winF = getFiledValue(host, "mWindow");
inflator.set(winF, in);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void copyFields(Class clazz, String[] fields, Activity host, Activity target) {
try {
for (String f : fields) {
Field declaredField = clazz.getDeclaredField(f);
setField(target, declaredField, getFiledValue(host, f));
}
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void setField(Object object, Field field, Object value) {
field.setAccessible(true);
try {
field.set(object, value);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Object getFiledValue(Object object, String fieldName) {
Object f = null;
try {
Class<?> ACTIVITY = Class.forName("android.app.Activity");
Field declaredField = ACTIVITY.getDeclaredField(fieldName);
declaredField.setAccessible(true);
f = declaredField.get(object);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Log.d(TAG, "getFiledValue(). fieldName: " + fieldName + " field: " + f);
return f;
}
}
}