Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/java/me/firesun/wechat/enhancement/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import me.firesun.wechat.enhancement.plugin.IPlugin;
import me.firesun.wechat.enhancement.plugin.Limits;
import me.firesun.wechat.enhancement.plugin.LuckMoney;
import me.firesun.wechat.enhancement.plugin.SecretFriend;
import me.firesun.wechat.enhancement.util.HookParams;
import me.firesun.wechat.enhancement.util.SearchClasses;

Expand All @@ -33,6 +34,7 @@ public class Main implements IXposedHookLoadPackage {
new HideModule(),
new LuckMoney(),
new Limits(),
new SecretFriend()
};

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ public static boolean isBreakLimit() {
return getInstance().getBoolean("is_break_limit", false);
}

public static boolean isEnableSecretFriend() {
return getInstance().getBoolean("is_secret_friend", false);
}

public static String secretFriendIds() {
return getInstance().getString("secret_friend_ids", "").replace(",", ",");
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package me.firesun.wechat.enhancement.plugin;

import android.app.Activity;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Bundle;
import android.widget.BaseAdapter;
import android.widget.Toast;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import me.firesun.wechat.enhancement.PreferencesUtils;
import me.firesun.wechat.enhancement.util.HookParams;

import static android.widget.Toast.LENGTH_LONG;
import static me.firesun.wechat.enhancement.util.ReflectionUtil.log;

public class SecretFriend implements IPlugin {

//暂时只支持隐藏单个id,多id需要建立对照表
private int secretItemIndex = -1;
private Class conversationWithCacheAdapterClass;

@Override
public void hook(XC_LoadPackage.LoadPackageParam lpparam) {
try {
log("SecretFriend hook " + HookParams.getInstance().ConversationWithCacheAdapterClassName);
conversationWithCacheAdapterClass = XposedHelpers.findClass(HookParams.getInstance().ConversationWithCacheAdapterClassName, lpparam.classLoader);
} catch (Error | Exception e) {
}

XposedHelpers.findAndHookMethod(HookParams.getInstance().ChattingUIClassName, lpparam.classLoader, "onCreate", Bundle.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
try {
if (PreferencesUtils.isEnableSecretFriend()) {
Activity activity = (Activity) param.thisObject;
ClipboardManager cmb = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
String wechatId = activity.getIntent().getStringExtra("Chat_User");
log(wechatId);
cmb.setText(wechatId);
Toast.makeText(activity, "微信ID:" + wechatId + "已复制到剪切板", LENGTH_LONG).show();
}
} catch (Error | Exception e) {
}
}
});

// XposedBridge.hookAllConstructors(HookParams.getInstance().ConversationWithCacheAdapterClass, new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// if (PreferencesUtils.isEnableSecretFriend()) {
// //BaseAdapter adapter = (BaseAdapter) param.thisObject;
// secretItemIndex = -1;
// }
// }
// });

XposedHelpers.findAndHookMethod(conversationWithCacheAdapterClass.getSuperclass(),
HookParams.getInstance().MMBaseAdapter_getItemInternal, int.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
if (PreferencesUtils.isEnableSecretFriend() && secretItemIndex > -1) {
BaseAdapter adapter = (BaseAdapter) param.thisObject;
if (adapter.getClass().equals(conversationWithCacheAdapterClass)) {
int index = (int) param.args[0];
if (index >= secretItemIndex) {
param.args[0] = index + 1;
}
}
}
}
});

XposedHelpers.findAndHookMethod(conversationWithCacheAdapterClass.getSuperclass(),"getCount", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (PreferencesUtils.isEnableSecretFriend()) {
log("getCount: " + param.thisObject.getClass().getName());
if (param.thisObject.getClass().equals(conversationWithCacheAdapterClass)) {
if (secretItemIndex > -1) {
int size = (int) param.getResult();
log("count: " + size);
if (size > 0) {
param.setResult(size - 1);
}
}
}
}
}
});

// Hook notifyDataSetChanged() of base adapters
XposedHelpers.findAndHookMethod(BaseAdapter.class, "notifyDataSetChanged", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
if (PreferencesUtils.isEnableSecretFriend()) {
BaseAdapter adapter = (BaseAdapter) param.thisObject;
if (adapter.getClass().equals(conversationWithCacheAdapterClass)) {
secretItemIndex = -1;
for (int i = 0; i < adapter.getCount(); i++) {
String username = (String) XposedHelpers.getObjectField(adapter.getItem(i), "field_username");
if (username.equals(PreferencesUtils.secretFriendIds())) {
secretItemIndex = i;
break;
}
}
}
}
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class HookParams {
public static final String SAVE_WECHAT_ENHANCEMENT_CONFIG = "wechat.intent.action.SAVE_WECHAT_ENHANCEMENT_CONFIG";
public static final String WECHAT_ENHANCEMENT_CONFIG_NAME = "wechat_enhancement_config";
public static final String WECHAT_PACKAGE_NAME = "com.tencent.mm";
public static final int VERSION_CODE = 46; //大版本变动时候才需要修改
public static final int VERSION_CODE = 47; //大版本变动时候才需要修改

public String SQLiteDatabaseClassName = "com.tencent.wcdb.database.SQLiteDatabase";
public String SQLiteDatabaseUpdateMethod = "updateWithOnConflict";
Expand Down Expand Up @@ -40,6 +40,13 @@ public class HookParams {
public String versionName;
public int versionCode;

public String ChattingUIClassName = "com.tencent.mm.ui.chatting.ChattingUI";
// public Class ConversationWithCacheAdapterClass;
public String ConversationWithCacheAdapterClassName;
// public Class MMBaseAdapterClass;
public String MMBaseAdapterClassName;
public String MMBaseAdapter_getItemInternal;

private static HookParams instance = null;

private HookParams() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,28 @@ public final Classes filterByMethod(Class returnType, String methodName, Class..
return new Classes(arrayList);
}

public final Classes filterByMethod(String methodName, Class... parameterTypes) {
List arrayList = new ArrayList();
for (Object next : this.classes) {
Method method = ReflectionUtil.findMethodExactIfExists((Class) next, methodName, (Class[]) Arrays.copyOf(parameterTypes, parameterTypes.length));
if (method != null) {
arrayList.add(next);
}
}

return new Classes(arrayList);
}

public final Classes filterBySuper(Class superClass) {
List arrayList = new ArrayList();
for (Class next : this.classes) {
if (next.getSuperclass() == superClass) {
arrayList.add(next);
}
}
return new Classes(arrayList);
}

public final Class<?> firstOrNull() {
if (this.classes.isEmpty())
return null;
Expand All @@ -303,5 +325,6 @@ else if (this.classes.size() > 1) {
}
return this.classes.get(0);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import org.json.JSONObject;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -200,6 +201,35 @@ public static void generateConfig(String wechatApk, ClassLoader classLoader, Str
} catch (Error | Exception e) {
log("Search Photo Limits Classes Failed!");
}

//SecretFriend
try {
Class conversationWithCacheAdapterClass = ReflectionUtil.findClassesFromPackage(classLoader, wxClasses, "com.tencent.mm.ui.conversation", 0)
.filterByMethod("clearCache")
.firstOrNull();
hp.ConversationWithCacheAdapterClassName = conversationWithCacheAdapterClass.getName();
log("ConversationWithCacheAdapterClassName: " + hp.ConversationWithCacheAdapterClassName);
log(conversationWithCacheAdapterClass.getSuperclass().getName());

// Class MMBaseAdapterClass = ReflectionUtil.findClassesFromPackage(classLoader, wxClasses, "com.tencent.mm.ui", 0)
// .filterBySuper(BaseAdapter.class)
// .filterByField("TAG", "java.lang.String")
// .firstOrNull();
Class MMBaseAdapterClass = conversationWithCacheAdapterClass.getSuperclass();
hp.MMBaseAdapterClassName = MMBaseAdapterClass.getName();
log("MMBaseAdapterClassName: " + hp.MMBaseAdapterClassName);
for (Method m: MMBaseAdapterClass.getDeclaredMethods()) {
if (m.getParameterTypes().length == 1 && m.getParameterTypes()[0] == int.class
&& !"getItem".equals(m.getName()) && !"getItemId".equals(m.getName())) {
hp.MMBaseAdapter_getItemInternal = m.getName();
log(hp.MMBaseAdapter_getItemInternal);
break;
}
}
} catch (Error | Exception e) {
log("Search ConversationWithCacheAdapter Classes Failed! " + e);
//throw e;
}
}

private static int getVersionNum(String version) {
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@
<string name="generate_success">生成配置成功</string>
<string name="generate_failed">生成配置失败</string>
<string name="generating">正在生成配置…</string>
<string name="secret_friend">私密好友</string>
<string name="pref_enable_secret_friend">启用私密好友</string>
<string name="secret_friend_ids">私密好友清单</string>
</resources>
10 changes: 10 additions & 0 deletions app/src/main/res/xml/pref_setting.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@
</PreferenceCategory>


<PreferenceCategory android:title="@string/secret_friend">
<SwitchPreference
android:defaultValue="true"
android:key="is_secret_friend"
android:title="@string/pref_enable_secret_friend" />
<EditTextPreference
android:dependency="is_secret_friend"
android:key="secret_friend_ids"
android:title="@string/secret_friend_ids" />
</PreferenceCategory>


<PreferenceCategory android:title="@string/about">
Expand Down