diff --git a/app/build.gradle b/app/build.gradle index e095818..f466b12 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -22,7 +22,7 @@ android { defaultConfig { applicationId "bin.xposed.Unblock163MusicClient" minSdkVersion 14 - // target Android P 之后,在安装过程中会对 APP 文件目录实行严格的 SELinux 限制,即使 makeWorkdReadable,其他 APP 也无法读取插件的任何配置文件 + // target Android P 之后,在安装过程中会对 APP 文件目录实行严格的 SELinux 限制,即使 makeWorldReadable,其他 APP 也无法读取插件的任何配置文件 targetSdkVersion 27 versionCode 31 versionName = "0.0.${versionCode}" diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 8e0aa29..145a049 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -19,7 +19,7 @@ -keep class bin.xposed.Unblock163MusicClient.Main -keepclassmembers class bin.xposed.Unblock163MusicClient.HookerDispatcher* { - void dispatch(***); + void dispatch(**); } -keepclassmembernames class bin.xposed.Unblock163MusicClient.ui.SettingsActivity { diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/CloudMusicPackage.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/CloudMusicPackage.java index 5f1d745..5ccb81b 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/CloudMusicPackage.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/CloudMusicPackage.java @@ -45,6 +45,7 @@ import static bin.xposed.Unblock163MusicClient.CloudMusicPackage.ClassHelper.getFilteredClasses; import static bin.xposed.Unblock163MusicClient.Utils.log; +import static de.robv.android.xposed.XposedBridge.invokeOriginalMethod; import static de.robv.android.xposed.XposedHelpers.callMethod; import static de.robv.android.xposed.XposedHelpers.callStaticMethod; import static de.robv.android.xposed.XposedHelpers.findClass; @@ -138,6 +139,7 @@ public static class MusicInfo { private static Class clazz; private final Object musicInfo; + private static Method hasCopyRightMethod; public MusicInfo(Object musicInfo) { this.musicInfo = musicInfo; @@ -151,8 +153,24 @@ public static Class getClazz() { return clazz; } + public static Method getHasCopyRightMethod() { + if (hasCopyRightMethod == null) { + hasCopyRightMethod = findMethodExact(getClazz(), "hasCopyRight"); + } + return hasCopyRightMethod; + } + public static boolean isStarred(long musicId) { - return (boolean) callStaticMethod(MusicInfo.getClazz(), "isStarred", musicId); + return (boolean) callStaticMethod(getClazz(), "isStarred", musicId); + } + + public boolean hasCopyRight() throws InvocationTargetException, IllegalAccessException { + if (Settings.isPreventGrayEnabled()) { + return (boolean) invokeOriginalMethod(getHasCopyRightMethod(), musicInfo, null); + } else { + // workaround "method not hooked, cannot call original method" + return (boolean) getHasCopyRightMethod().invoke(musicInfo); + } } public long getMatchedMusicId() { @@ -175,9 +193,9 @@ public String get3rdSourceString() throws JSONException, IOException { song.parseMatchInfo(new JSONObject(jsonStr)); if (song.is3rdPartySong()) { return String.format("(音源%s:%s - %s)", - song.matchedPlatform, - song.matchedArtistName, - song.matchedSongName); + song.getMatchedPlatform(), + song.getMatchedArtistName(), + song.getMatchedSongName()); } } } @@ -359,7 +377,7 @@ public Uri getUri() throws IllegalAccessException { public static class CookieUtil { private static Class clazz; - private static Method getSingtonMethod; + private static Method getSingletonMethod; private static Method getListMethod; static Class getClazz() { @@ -398,14 +416,14 @@ static Class getClazz() { static String getDefaultCookie() throws InvocationTargetException, IllegalAccessException { - if (getSingtonMethod == null) { - getSingtonMethod = XposedHelpers.findMethodsByExactParameters(getClazz(), getClazz())[0]; + if (getSingletonMethod == null) { + getSingletonMethod = XposedHelpers.findMethodsByExactParameters(getClazz(), getClazz())[0]; } if (getListMethod == null) { getListMethod = XposedHelpers.findMethodsByExactParameters(getClazz(), List.class)[0]; } - Object singleton = getSingtonMethod.invoke(null); + Object singleton = getSingletonMethod.invoke(null); List cookieList = (List) getListMethod.invoke(singleton); return Utils.serialCookies(cookieList, cookieMethodMap, "music.163.com"); @@ -503,15 +521,16 @@ public static Method getLikeButtonOnClickMethod() { return m.find() ? Integer.parseInt(m.group(1)) : -1; }) .filter(g -> g.getKey() > -1) - .max((x, y) -> { - int sizeDiff = x.getValue().size() - y.getValue().size(); - if (sizeDiff != 0) { - return sizeDiff; + .reduce((x, y) -> { + if (x.getValue().size() > y.getValue().size()) { + return x; } - int nameDiff = x.getKey() - y.getKey(); - return -nameDiff; - }).get().getKey(); - + if (x.getKey() > y.getKey()) { + return x; + } + return y; + }) + .get().getKey(); if (num >= 0) { likeButtonOnClickMethod = findMethodExact(playerActivitySuperClass.getName() + "$" + num, getClassLoader(), "onClick", View.class); @@ -585,7 +604,7 @@ static Class getClazz() { return clazz; } - static void showToast(final String text) { + static void showToast(String text) { Utils.postDelayed(() -> { try { // Toast.makeText(NeteaseMusicApplication.getApplication(), text, Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/Handler.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/Handler.java index aab92c3..90bdbb0 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/Handler.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/Handler.java @@ -1,7 +1,5 @@ package bin.xposed.Unblock163MusicClient; -import com.google.common.collect.Iterables; - import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -9,11 +7,9 @@ import java.io.File; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -27,7 +23,7 @@ import static bin.xposed.Unblock163MusicClient.Utils.log; public class Handler { - private static final String XAPI = "http://xmusic.xmusic.top/xapi/v1/"; + private static final String XAPI = "https://xmusic.xmusic.top/xapi/v1/"; private static final Pattern REX_PL = Pattern.compile("\"pl\":(?!999000)\\d+"); private static final Pattern REX_DL = Pattern.compile("\"dl\":(?!999000)\\d+"); private static final Pattern REX_SUBP = Pattern.compile("\"subp\":\\d+"); @@ -40,13 +36,14 @@ public static String modifyByRegex(String originalContent) { return originalContent; } - public static String modifyPlayerOrDownloadApi(String originalContent, HttpEapi eapi, final String from) throws JSONException { + public static String modifyPlayerOrDownloadApi(String originalContent, HttpEapi eapi, String from) throws JSONException { JSONObject originalJson = new JSONObject(originalContent); - int expectBitrate = 320000; + int expectBitrate; try { expectBitrate = Integer.parseInt(eapi.getRequestData().get("br")); } catch (Throwable ignored) { + expectBitrate = 320000; } @@ -56,13 +53,13 @@ public static String modifyPlayerOrDownloadApi(String originalContent, HttpEapi Process.process(originalSong, expectBitrate, from); } else { JSONArray originalSongs = (JSONArray) data; - Set futureSet = new HashSet<>(); + List futures = new ArrayList<>(); final int finalExpectBitrate = expectBitrate; for (int i = 0; i < originalSongs.length(); i++) { - final JSONObject songJson = originalSongs.getJSONObject(i); - futureSet.add(handlerPool.submit(() -> Process.process(songJson, finalExpectBitrate, from))); + JSONObject songJson = originalSongs.getJSONObject(i); + futures.add(handlerPool.submit(() -> Process.process(songJson, finalExpectBitrate, from))); } - for (Future future : futureSet) { + for (Future future : futures) { try { future.get(); } catch (Throwable t) { @@ -124,7 +121,7 @@ public static String modifyPub(String originalContent, HttpEapi eapi) throws Thr return originalContent; } - private static List getSongByRemoteApi(final long songId, final int expectBitrate, final String apiName) { + private static List getSongByRemoteApi(long songId, int expectBitrate, String apiName) { try { Map map = new LinkedHashMap() {{ put("id", String.valueOf(songId)); @@ -137,9 +134,9 @@ private static List getSongByRemoteApi(final long songId, final int expect if (json.getInt("code") == 200) { Object obj = json.get("data"); if (obj instanceof JSONObject) { - return Collections.singletonList(Song.parseFromOther((JSONObject) obj)); + return Collections.singletonList(Song.parse((JSONObject) obj)); } else if (obj instanceof JSONArray) { - return Song.parseFromOther((JSONArray) obj); + return Song.parse((JSONArray) obj); } } } catch (Throwable t) { @@ -172,13 +169,13 @@ static void process(JSONObject oldSongJson, int expectBr, String from) { } boolean isNeedToGetP1() { - return !preferSong.isAccessible() || preferSong.br < expectBr; + return !preferSong.isAccessible() || preferSong.getBr() < expectBr; } boolean isNeedToEnhance() { boolean isNeed = false; - if (preferSong.br < expectBr && originalSong.isFee() && !originalSong.isPayed()) { + if (preferSong.getBr() < expectBr && originalSong.isFee() && !originalSong.isPayed()) { isNeed = true; } @@ -191,7 +188,7 @@ boolean isNeedToEnhance() { } boolean isNeedToGet3rdParty() { - return !preferSong.isAccessible() || (preferSong.br < expectBr && isUpgradeBitrateFrom3rdParty()); + return !preferSong.isAccessible() || (preferSong.getBr() < expectBr && isUpgradeBitrateFrom3rdParty()); } boolean isNeedToProcess() { @@ -203,18 +200,17 @@ boolean isNeedToProcess() { return !originalSong.isAccessible() // 听不了 || originalSong.isFreeTrialFile() // 试听 - || originalSong.br < expectBr; // 音质不够 + || originalSong.getBr() < expectBr; // 音质不够 } - private void addRC(Callable condition, Callable callable) { + private void addRC(Callable condition, Callable> getSongByApi) { try { if ((boolean) condition.call()) { List songList = new ArrayList<>(); songList.add(preferSong); - songList.addAll((List) callable.call()); + songList.addAll(getSongByApi.call()); - Song[] songArray = Iterables.toArray(songList, Song.class); - Song tmp = Song.getPreferSong(songArray); + Song tmp = Song.getPreferSong(songList); if (tmp != null) { preferSong = tmp; } @@ -226,7 +222,7 @@ private void addRC(Callable condition, Callable callable) { void doProcess() throws JSONException { - originalSong = Song.parseFromOther(oldSongJson); + originalSong = Song.parse(oldSongJson); if (originalSong == null) { return; @@ -245,34 +241,33 @@ void doProcess() throws JSONException { preferSong = originalSong; - addRC(this::isNeedToGetP1, () -> getSongByRemoteApi(originalSong.id, expectBr, "songs")); - addRC(this::isNeedToEnhance, () -> getSongByRemoteApi(originalSong.id, expectBr, "songx")); - addRC(this::isNeedToGet3rdParty, () -> getSongByRemoteApi(originalSong.id, expectBr, "match")); + addRC(this::isNeedToGetP1, () -> getSongByRemoteApi(originalSong.getId(), expectBr, "songs")); + addRC(this::isNeedToEnhance, () -> getSongByRemoteApi(originalSong.getId(), expectBr, "songx")); + addRC(this::isNeedToGet3rdParty, () -> getSongByRemoteApi(originalSong.getId(), expectBr, "match")); - if (preferSong.getPrefer() > originalSong.getPrefer()) { - oldSongJson.put("br", preferSong.br) + if (preferSong != originalSong) { + oldSongJson.put("br", preferSong.getBr()) .put("code", 200) - .put("gain", 0) - .put("md5", preferSong.md5) - .put("size", preferSong.size) - .put("type", preferSong.type) - .put("url", preferSong.url); + .put("md5", preferSong.getMd5()) + .put("size", preferSong.getSize()) + .put("type", preferSong.getType()) + .put("url", preferSong.getUrl()); try { File cacheDir = CloudMusicPackage.NeteaseMusicApplication.getMusicCacheDir(); if (preferSong.is3rdPartySong()) { - String fileName = String.format("%s-%s-%s.%s.xp!", preferSong.id, preferSong.br, preferSong.md5, preferSong.type); + String fileName = String.format("%s-%s-%s.%s.xp!", preferSong.getId(), preferSong.getBr(), preferSong.getMd5(), preferSong.getType()); File file = new File(cacheDir, fileName); String str = preferSong.getMatchedJson().toString(); Utils.writeFile(file, str); } else { - String start = String.format("%s-", preferSong.id); + String start = String.format("%s-", preferSong.getId()); String end = ".xp!"; File[] files = Utils.findFiles(cacheDir, start, end, null); Utils.deleteFiles(files); } } catch (Throwable t) { - log("read 3rd party tips failed " + originalSong.id, t); + log("read 3rd party tips failed " + originalSong.getId(), t); } } } diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/HookerDispatcher.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/HookerDispatcher.java index 8cf59c2..bc19fe0 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/HookerDispatcher.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/HookerDispatcher.java @@ -36,23 +36,29 @@ public void dispatch(XC_LoadPackage.LoadPackageParam lpparam) { protected void afterHookedMethod(MethodHookParam param) throws Throwable { Context context = (Context) param.thisObject; + String processName = Utils.getCurrentProcessName(context); + List hookers = null; - if (isInMainProcess(context)) { - CloudMusicPackage.init(context); - hookMainProcess(); + if (processName.equals(CloudMusicPackage.PACKAGE_NAME)) { + hookers = getMainProcessHookers(); - } else if (isInPlayProcess(context)) { - CloudMusicPackage.init(context); - hookPlayProcess(); + } else if (processName.equals(CloudMusicPackage.PACKAGE_NAME + ":play")) { + hookers = getPlayProcessHookers(); } + if (hookers != null && hookers.size() > 0) { + CloudMusicPackage.init(context); + for (Hooker hooker : hookers) { + hooker.startToHook(); + } + } } }); } - - private void hookMainProcess() { + private List getMainProcessHookers() { List list = new ArrayList<>(); + list.add(new About()); if (Settings.isUnblockEnabled()) { list.add(new Eapi()); list.add(new Download()); @@ -60,57 +66,31 @@ private void hookMainProcess() { list.add(new QualityBox()); list.add(new TipsFor3rd()); list.add(new DnsMod()); - - if (Settings.isPreventGrayEnabled()) { list.add(new Gray()); } - } - - if (Settings.isDislikeConfirmEnabled()) { list.add(new Dislike()); } - - if (Settings.isTransparentPlayerNavBar() || Settings.isTransparentBaseNavBar()) { list.add(new Transparent()); } - if (Settings.isMagiskFixEnabled()) { list.add(new MagiskFix()); - - } - - list.add(new About()); - - - for (Hooker hooker : list) { - hooker.startToHook(); } + return list; } - private void hookPlayProcess() { + private List getPlayProcessHookers() { List list = new ArrayList<>(); if (Settings.isUnblockEnabled()) { list.add(new Eapi()); list.add(new HttpMod()); list.add(new DnsMod()); } - - for (Hooker hooker : list) { - hooker.startToHook(); - } - } - - - private boolean isInMainProcess(Context context) { - return Utils.getCurrentProcessName(context).equals(CloudMusicPackage.PACKAGE_NAME); + return list; } - private boolean isInPlayProcess(Context context) { - return Utils.getCurrentProcessName(context).equals(CloudMusicPackage.PACKAGE_NAME + ":play"); - } } \ No newline at end of file diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/Main.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/Main.java index 1350ea7..f3224c3 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/Main.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/Main.java @@ -15,9 +15,8 @@ public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable { if (lpparam.packageName.equals(CloudMusicPackage.PACKAGE_NAME)) { HotXposed.hook(HookerDispatcher.class, lpparam); - } - if (lpparam.packageName.equals(BuildConfig.APPLICATION_ID)) { + } else if (lpparam.packageName.equals(BuildConfig.APPLICATION_ID)) { HotXposed.hook(HookerDispatcherSelf.class, lpparam); } } diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/Song.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/Song.java index 3877f40..834ebf5 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/Song.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/Song.java @@ -1,5 +1,6 @@ package bin.xposed.Unblock163MusicClient; +import com.annimon.stream.ComparatorCompat; import com.annimon.stream.Stream; import org.json.JSONArray; @@ -14,26 +15,26 @@ import static bin.xposed.Unblock163MusicClient.Utils.optString; class Song { - long id; - int code; - int br; - int fee; - String md5; - int payed; - long size; - String type; - JSONObject uf; - String url; - JSONObject freeTrialInfo; - - String matchedPlatform; - String matchedSongName; - String matchedArtistName; - boolean matchedDuration; + private static ComparatorCompat preferComparator; + private long id; + private int code; + private int br; + private int fee; + private String md5; + private int payed; + private long size; + private String type; + private JSONObject uf; + private String url; + private JSONObject freeTrialInfo; + private String matchedPlatform; + private String matchedSongName; + private String matchedArtistName; + private boolean matchedDuration; private Boolean accessible; - static Song parseFromOther(JSONObject songJson) { + static Song parse(JSONObject songJson) { if (songJson == null) { return null; } @@ -54,7 +55,7 @@ static Song parseFromOther(JSONObject songJson) { return song; } - static List parseFromOther(JSONArray songsJson) { + static List parse(JSONArray songsJson) { if (songsJson == null) { return null; } @@ -62,13 +63,12 @@ static List parseFromOther(JSONArray songsJson) { for (int i = 0; i < songsJson.length(); i++) { JSONObject obj = songsJson.optJSONObject(i); if (obj != null) { - songs.add(parseFromOther(obj)); + songs.add(parse(obj)); } } return songs; } - static Song parseFromDetail(JSONObject songJson, long id, int br) { Song song = new Song(); long fid = songJson.optLong("fid"); @@ -84,13 +84,67 @@ static Song parseFromDetail(JSONObject songJson, long id, int br) { return null; } - static Song getPreferSong(Song... songs) { - return Stream.of(songs).sortBy(s -> -s.getPrefer(false)) + static Song getPreferSong(List songs) { + if (preferComparator == null) { + if (Settings.isUpgradeBitrateFrom3rdParty()) { + preferComparator = ComparatorCompat.comparing(Song::isFullMatched).reversed() + .thenComparing(ComparatorCompat.comparing(Song::getBr).reversed()) + .thenComparing(ComparatorCompat.comparing(Song::is3rdPartySong)); + } else { + preferComparator = ComparatorCompat.comparing(Song::isFullMatched).reversed() + .thenComparing(ComparatorCompat.comparing(Song::is3rdPartySong)) + .thenComparing(ComparatorCompat.comparing(Song::getBr).reversed()); + } + } + + return Stream.of(songs).sorted(preferComparator) + .filterNot(Song::isFreeTrialFile) .filter(Song::isAccessible) .findFirst().orElse(null); } + + int getCode() { + return code; + } + + long getId() { + return id; + } + + String getMd5() { + return md5; + } + + long getSize() { + return size; + } + + String getType() { + return type; + } + + String getUrl() { + return url; + } + + String getMatchedArtistName() { + return matchedArtistName; + } + + String getMatchedPlatform() { + return matchedPlatform; + } + + String getMatchedSongName() { + return matchedSongName; + } + + int getBr() { + return br; + } + void parseMatchInfo(JSONObject songJson) { matchedPlatform = optString(songJson, "matchedPlatform"); matchedSongName = optString(songJson, "matchedSongName"); @@ -142,8 +196,8 @@ boolean isFee() { } - private boolean is3rdMatchedDuration() { - return matchedDuration; + private boolean isFullMatched() { + return !is3rdPartySong() || matchedDuration; } JSONObject getMatchedJson() throws JSONException { @@ -153,23 +207,5 @@ JSONObject getMatchedJson() throws JSONException { .put("matchedArtistName", matchedArtistName); } - int getPrefer() { - return getPrefer(true); - } - - int getPrefer(boolean checkAccessible) { - if (checkAccessible && !isAccessible()) { - return 0; - } - - int prefer = br; - if (is3rdPartySong()) { - prefer--; - if (!is3rdMatchedDuration()) { - prefer = 1; - } - } - return prefer; - } } diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/Utils.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/Utils.java index cb6cffe..b4f0d76 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/Utils.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/Utils.java @@ -46,7 +46,7 @@ @SuppressWarnings({"unused", "WeakerAccess"}) public class Utils { private static final String TAG = "unblock163"; - private static Map dnsCache = new HashMap<>(); + private static final Map dnsCache = new HashMap<>(); private static WeakReference moduleResources = new WeakReference<>(null); static String getFirstPartOfString(String str, String separator) { @@ -204,12 +204,12 @@ static void writeFile(File file, String string) throws IOException { Files.asCharSink(file, Charsets.UTF_8).write(string); } - static File findFirstFile(File dir, final String start, final String end) { + static File findFirstFile(File dir, String start, String end) { File[] fs = findFiles(dir, start, end, 1); return fs != null && fs.length > 0 ? fs[0] : null; } - static File[] findFiles(File dir, final String start, final String end, final Integer limit) { + static File[] findFiles(File dir, String start, String end, Integer limit) { if (dir != null && dir.exists() && dir.isDirectory()) { return dir.listFiles(new FilenameFilter() { int find = 0; @@ -282,27 +282,6 @@ public static boolean isAppInstalled(Context context, String packageName) { } } - public static boolean isCallFromMyself() { - StackTraceElement[] elements = Thread.currentThread().getStackTrace(); - boolean findAppStack = false; - boolean findModStack = false; - - for (StackTraceElement element : elements) { - if (!findAppStack && element.getClassName().startsWith(BuildConfig.APPLICATION_ID)) { - findAppStack = true; - continue; - } - if (findAppStack && element.getClassName().startsWith(CloudMusicPackage.PACKAGE_NAME)) { - findModStack = true; - continue; - } - if (findModStack && element.getClassName().startsWith(BuildConfig.APPLICATION_ID)) { - return true; - } - } - return false; - } - public static void postDelayed(Runnable runnable, long delay) { new android.os.Handler(getMainLooper()).postDelayed(runnable, delay); } diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/Dislike.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/Dislike.java index 2546943..16994b0 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/Dislike.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/Dislike.java @@ -5,7 +5,6 @@ import bin.xposed.Unblock163MusicClient.CloudMusicPackage; import bin.xposed.Unblock163MusicClient.Hooker; -import bin.xposed.Unblock163MusicClient.Settings; import de.robv.android.xposed.XC_MethodHook; import static bin.xposed.Unblock163MusicClient.Utils.log; @@ -17,30 +16,28 @@ public class Dislike extends Hooker { @Override protected void howToHook() throws Throwable { - if (Settings.isDislikeConfirmEnabled()) { - hookMethod(CloudMusicPackage.PlayerActivity.getLikeButtonOnClickMethod(), new XC_MethodHook() { - @Override - protected void beforeHookedMethod(final MethodHookParam param) throws Throwable { - Activity currentActivity = (Activity) getObjectField(param.thisObject, "a"); - if (CloudMusicPackage.PlayerActivity.getClazz().isInstance(currentActivity)) { - Object musicInfo = new CloudMusicPackage.PlayerActivity(currentActivity).getMusicInfo(); - long musicId = new CloudMusicPackage.MusicInfo(musicInfo).getMatchedMusicId(); - boolean isStarred = CloudMusicPackage.MusicInfo.isStarred(musicId); - if (isStarred) { - CloudMusicPackage.UIAA.getMaterialDialogWithPositiveBtnMethod().invoke( - null, currentActivity, "确定不再收藏此歌曲吗?", "不再收藏", (View.OnClickListener) v -> { - try { - invokeOriginalMethod(param.method, param.thisObject, param.args); - } catch (Throwable t) { - log(t); - } - }); - param.setResult(null); - } + hookMethod(CloudMusicPackage.PlayerActivity.getLikeButtonOnClickMethod(), new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + Activity currentActivity = (Activity) getObjectField(param.thisObject, "a"); + if (CloudMusicPackage.PlayerActivity.getClazz().isInstance(currentActivity)) { + Object musicInfo = new CloudMusicPackage.PlayerActivity(currentActivity).getMusicInfo(); + long musicId = new CloudMusicPackage.MusicInfo(musicInfo).getMatchedMusicId(); + boolean isStarred = CloudMusicPackage.MusicInfo.isStarred(musicId); + if (isStarred) { + CloudMusicPackage.UIAA.getMaterialDialogWithPositiveBtnMethod().invoke( + null, currentActivity, "确定不再收藏此歌曲吗?", "不再收藏", (View.OnClickListener) v -> { + try { + invokeOriginalMethod(param.method, param.thisObject, param.args); + } catch (Throwable t) { + log(t); + } + }); + param.setResult(null); } } - }); - } + } + }); } } diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/DnsMod.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/DnsMod.java index fa15830..9f4ae76 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/DnsMod.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/DnsMod.java @@ -29,13 +29,13 @@ protected void howToHook() throws Throwable { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { String host = (String) param.args[0]; if (host.endsWith("p1c.music.126.net")) { - Future future = pool.submit(() -> Utils.getIpByHostPretendOverSea(host)); - InetAddress[] ips = (InetAddress[]) future.get(); + Future future = pool.submit(() -> Utils.getIpByHostPretendOverSea(host)); + InetAddress[] ips = future.get(); param.setResult("getAllByName".equals(param.method.getName()) ? ips : ips[0]); } else if (host.endsWith("music.126.net") && Settings.isOverseaModeEnabled()) { - Future future = pool.submit(() -> Utils.getIpByHostPretendInChina(host)); - InetAddress[] ips = (InetAddress[]) future.get(); + Future future = pool.submit(() -> Utils.getIpByHostPretendInChina(host)); + InetAddress[] ips = future.get(); param.setResult("getAllByName".equals(param.method.getName()) ? ips : ips[0]); } } @@ -50,8 +50,8 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { JSONObject json = (JSONObject) param.args[0]; String host = json.optString("host"); if (host.endsWith("p1c.music.126.net")) { - Future future = pool.submit(() -> Utils.getIpByHostPretendOverSea(host)); - InetAddress[] ips = (InetAddress[]) future.get(); + Future future = pool.submit(() -> Utils.getIpByHostPretendOverSea(host)); + InetAddress[] ips = future.get(); if (ips.length > 0) { JSONArray array = new JSONArray(); for (InetAddress ip : ips) { @@ -62,8 +62,8 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } else if (host.endsWith("music.126.net") && Settings.isOverseaModeEnabled()) { - Future future = pool.submit(() -> Utils.getIpByHostPretendInChina(host)); - InetAddress[] ips = (InetAddress[]) future.get(); + Future future = pool.submit(() -> Utils.getIpByHostPretendInChina(host)); + InetAddress[] ips = future.get(); if (ips.length > 0) { JSONArray array = new JSONArray(); for (InetAddress ip : ips) { diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/Gray.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/Gray.java index 420ba9b..112f0f6 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/Gray.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/Gray.java @@ -2,29 +2,18 @@ import bin.xposed.Unblock163MusicClient.CloudMusicPackage; import bin.xposed.Unblock163MusicClient.Hooker; -import bin.xposed.Unblock163MusicClient.Settings; -import bin.xposed.Unblock163MusicClient.Utils; -import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XC_MethodReplacement; -import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; +import static de.robv.android.xposed.XposedBridge.hookMethod; public class Gray extends Hooker { @Override protected void howToHook() throws Throwable { - if (Settings.isPreventGrayEnabled()) { + // 或者 canHighLightMusic + hookMethod(CloudMusicPackage.MusicInfo.getHasCopyRightMethod(), XC_MethodReplacement.returnConstant(true)); - findAndHookMethod(CloudMusicPackage.MusicInfo.getClazz(), "hasCopyRight", new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { - if (!Utils.isCallFromMyself()) { - param.setResult(true); - } - } - }); - - } } } diff --git a/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/QualityBox.java b/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/QualityBox.java index 6c0820b..2463e0a 100644 --- a/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/QualityBox.java +++ b/app/src/main/java/bin/xposed/Unblock163MusicClient/hooker/QualityBox.java @@ -8,7 +8,6 @@ import de.robv.android.xposed.XC_MethodHook; import static de.robv.android.xposed.XposedBridge.hookMethod; -import static de.robv.android.xposed.XposedHelpers.callMethod; public class QualityBox extends Hooker { @@ -20,7 +19,8 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { Object currentActivity = param.args[0]; if (PlayerActivity.getClazz().isInstance(currentActivity)) { Object musicInfo = new PlayerActivity(currentActivity).getMusicInfo(); - if (!(boolean) callMethod(musicInfo, "hasCopyRight")) { + boolean hasCopyRight = new CloudMusicPackage.MusicInfo(musicInfo).hasCopyRight(); + if (!hasCopyRight) { SpannableString ssOld = (SpannableString) param.args[1]; SpannableString ssNew = new SpannableString(ssOld.toString().replace("付费独享", "下架歌曲")); Object[] spans = ssOld.getSpans(0, ssOld.length(), Object.class); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 81c464e..d044ec5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -52,7 +52,7 @@ 不变灰 只影响显示效果,与能否播放无关 - 杂项 + 杂项 hide_module_icon 隐藏本模块图标 diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index 3cc6863..0ff4113 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -24,7 +24,7 @@ android:title="@string/upgrade_bitrate_from_3rd_party_title" /> - +