package me.ele.amigo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Handler;
import android.os.Message;
import me.ele.amigo.reflect.FieldUtils;
import static me.ele.amigo.AmigoInstrumentation.EXTRA_TARGET_INFO;
import static me.ele.amigo.AmigoInstrumentation.EXTRA_TARGET_INTENT;
import static me.ele.amigo.utils.component.ActivityFinder.getActivityInfoInNewApp;
import static me.ele.amigo.utils.component.ActivityFinder.getLauncherComponent;
import static me.ele.amigo.utils.component.ActivityFinder.getNewLauncherComponent;
public class AmigoCallback implements Handler.Callback {
public static final int LAUNCH_ACTIVITY = 100;
private static final String TAG = AmigoCallback.class.getSimpleName();
private Handler.Callback mCallback = null;
private Context context;
public AmigoCallback(Context context, Handler.Callback callback) {
this.mCallback = callback;
this.context = context;
}
@Override
public boolean handleMessage(Message msg) {
if (msg.what == LAUNCH_ACTIVITY) {
return handleLaunchActivity(msg);
}
if (mCallback != null) {
return mCallback.handleMessage(msg);
}
return false;
}
private boolean handleLaunchActivity(Message msg) {
try {
Amigo.rollAmigoBack(context);
ClassLoader classLoader = context.getClassLoader();
Intent intent = (Intent) FieldUtils.readField(msg.obj, "intent");
intent.setExtrasClassLoader(classLoader);
Intent targetIntent = intent.getParcelableExtra(EXTRA_TARGET_INTENT);
if (targetIntent != null) {
ComponentName targetComponentName = targetIntent.resolveActivity(context.getPackageManager());
ActivityInfo targetActivityInfo = getActivityInfoInNewApp(context, targetComponentName.getClassName());
if (targetActivityInfo != null) {
targetIntent.setExtrasClassLoader(classLoader);
targetIntent.putExtra(EXTRA_TARGET_INFO, targetActivityInfo);
FieldUtils.writeDeclaredField(msg.obj, "intent", targetIntent);
FieldUtils.writeDeclaredField(msg.obj, "activityInfo", targetActivityInfo);
}
} else {
ActivityInfo activityInfo = (ActivityInfo) FieldUtils.readField(msg.obj, "activityInfo");
String activityName = activityInfo.targetActivity != null ? activityInfo.targetActivity : activityInfo.name;
ActivityInfo newActivityInfo = null;
if (isLaunchActivity(intent, activityName)) {
activityInfo.targetActivity = getNewLauncherComponent(context).getClassName();
newActivityInfo = getActivityInfoInNewApp(context, activityInfo.targetActivity);
newActivityInfo.targetActivity = activityInfo.targetActivity;
FieldUtils.writeDeclaredField(msg.obj, "activityInfo", newActivityInfo);
} else if ((newActivityInfo = getActivityInfoInNewApp(context, activityName)) != null) {
// TODO check intent filter ?
FieldUtils.writeDeclaredField(msg.obj, "activityInfo", newActivityInfo);
} else {
// TODO this host activity was launched by using a scheme url,
// we can navigate to a matched patch activity instead.
Intent toPatchLauncherIntent = new Intent().setComponent(
getNewLauncherComponent(context))
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(toPatchLauncherIntent);
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (mCallback != null) {
return mCallback.handleMessage(msg);
}
return false;
}
private boolean isLaunchActivity(Intent intent, String targetActivity) {
return (Intent.ACTION_MAIN.equals(intent.getAction()) && intent.hasCategory(Intent.CATEGORY_LAUNCHER))
|| targetActivity.equals(getLauncherComponent(context).getClassName());
}
}