package com.germainz.activityforcenewtask;
import android.app.AndroidAppHelper;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import static de.robv.android.xposed.XposedHelpers.findClass;
import static de.robv.android.xposed.XposedHelpers.getIntField;
import static de.robv.android.xposed.XposedHelpers.getObjectField;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
public class XposedMod implements IXposedHookLoadPackage {
private final static SettingsHelper settingsHelper = new SettingsHelper();
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("android"))
return;
XC_MethodHook hook = new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
settingsHelper.reload();
if (settingsHelper.isModDisabled())
return;
Intent intent = (Intent) XposedHelpers.getObjectField(param.thisObject, "intent");
// The launching app does not expect data back. It's safe to run the activity in a
// new task.
int requestCode = getIntField(param.thisObject, "requestCode");
if (requestCode != -1)
return;
// The intent already has FLAG_ACTIVITY_NEW_TASK set, no need to do anything.
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == Intent.FLAG_ACTIVITY_NEW_TASK)
return;
String intentAction = intent.getAction();
// If the intent is not a known safe intent (as in, the launching app does not expect
// data back, so it's safe to run in a new task,) ignore it straight away.
if (intentAction == null)
return;
// If the app is launching one of its own activities, we shouldn't open it in a new task.
int uid = ((ActivityInfo) getObjectField(param.thisObject, "info")).applicationInfo.uid;
if (getIntField(param.thisObject, "launchedFromUid") == uid)
return;
ComponentName componentName = (ComponentName) getObjectField(param.thisObject, "realActivity");
String componentNameString = componentName.flattenToString();
// Log if necessary.
if (settingsHelper.isLogEnabled()) {
// Get context
Context context = AndroidAppHelper.currentApplication();
if (context != null)
context.sendBroadcast(new Intent(Common.INTENT_LOG).putExtra(Common.INTENT_COMPONENT_EXTRA, componentNameString));
else
XposedBridge.log("activityforcenewtask: couldn't get context.");
XposedBridge.log("activityforcenewtask: componentString: " + componentNameString);
}
// If the blacklist is used and the component is in the blacklist, or if the
// whitelist is used and the component isn't whitelisted, we shouldn't modify
// the intent's flags.
boolean isListed = settingsHelper.isListed(componentNameString);
String listType = settingsHelper.getListType();
if ((listType.equals(Common.PREF_BLACKLIST) && isListed) ||
(listType.equals(Common.PREF_WHITELIST) && !isListed))
return;
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
};
Class ActivityRecord = findClass("com.android.server.am.ActivityRecord", lpparam.classLoader);
XposedBridge.hookAllConstructors(ActivityRecord, hook);
}
}