Back to project page YouTubeBackgroundPlayback.
The source code is released under:
Copyright (c) 2015, pyler All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redist...
If you think the Android project YouTubeBackgroundPlayback listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.pyler.youtubebackgroundplayback; // ww w. ja v a 2s . c om import android.content.Context; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; public class YouTubeBackgroundPlayback implements IXposedHookLoadPackage { public static final String YOUTUBE_PACKAGE = "com.google.android.youtube"; public static final String BACKGROUND_PLAYER_SERVICE = "com.google.android.apps.youtube.core.player.BackgroundPlayerService"; public static final String[] CLASS_ENABLE_BACKGROUND_PLAYBACK = { "cti", "ctz", "cyj", "cyy", "cyk", "cyl" }; public static final String METHOD_ENABLE_BACKGROUND_PLAYBACK = "u"; public static final String FIELD_PLAYBACK_CONTROL = "i"; public static final String[] METHOD_RESTART_PLAYBACK = { "k", "k", "k", "k", "k", "j" }; public static final String FIELD_ENABLE_NOTIFICATION = "e"; public static final String METHOD_NEXT_TRACK = "d"; public static final String FIELD_TIME_MILLS = "a"; public static final String FIELD_LENGTH_MILLS = "b"; public int id; public long prevTime = -1; public boolean advanceSent = false; @Override public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { if (!YOUTUBE_PACKAGE.equals(lpparam.packageName)) { return; } XC_MethodHook restartPlayback = new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { Object playbackControl = (Object) XposedHelpers.getObjectField( param.thisObject, FIELD_PLAYBACK_CONTROL); XposedHelpers.callMethod(playbackControl, METHOD_RESTART_PLAYBACK[id]); } }; XC_MethodHook enableNotification = new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { XposedHelpers.setBooleanField(param.thisObject, FIELD_ENABLE_NOTIFICATION, true); } }; XC_MethodHook advanceNextTrack = new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { long time = XposedHelpers.getLongField(param.args[0], FIELD_TIME_MILLS); long length = XposedHelpers.getLongField(param.args[0], FIELD_LENGTH_MILLS); if (time == prevTime && time > 0 && length > 0 && time + 2000 > length) { if (!advanceSent) { advanceSent = true; Object playbackControl = (Object) XposedHelpers .getObjectField(param.thisObject, FIELD_PLAYBACK_CONTROL); XposedHelpers.callMethod(playbackControl, METHOD_NEXT_TRACK); } } else { prevTime = time; advanceSent = false; } } }; Object activityThread = XposedHelpers.callStaticMethod( XposedHelpers.findClass("android.app.ActivityThread", null), "currentActivityThread"); Context context = (Context) XposedHelpers.callMethod(activityThread, "getSystemContext"); int versionCode = context.getPackageManager().getPackageInfo( lpparam.packageName, 0).versionCode; id = getVersionIndex(versionCode); if (id != -1) { XposedHelpers.findAndHookMethod( CLASS_ENABLE_BACKGROUND_PLAYBACK[id], lpparam.classLoader, METHOD_ENABLE_BACKGROUND_PLAYBACK, XC_MethodReplacement.returnConstant(true)); XposedBridge.hookAllMethods(XposedHelpers.findClass( BACKGROUND_PLAYER_SERVICE, lpparam.classLoader), "handlePlaybackServiceException", restartPlayback); XposedBridge.hookAllConstructors(XposedHelpers.findClass( BACKGROUND_PLAYER_SERVICE, lpparam.classLoader), enableNotification); XposedBridge.hookAllMethods(XposedHelpers.findClass( BACKGROUND_PLAYER_SERVICE, lpparam.classLoader), "handleVideoTimeEvent", advanceNextTrack); } else { XposedBridge.log("This YouTube version is not supported yet."); } } public int getVersionIndex(int version) { if ((version == 100852130) || (version == 100852170)) { // YouTube 10.08.52 return 5; } else if ((version == 100603130) || (version == 100603170)) { // YouTube 10.06.3 return 4; } else if ((version == 100506130) || (version == 100506170)) { // YouTube 10.05.6 return 3; } else if ((version == 100405130) || (version == 100405170)) { // YouTube 10.04.5 return 2; } else if ((version == 100305130) || (version == 100305170)) { // YouTube 10.03.5 return 1; } else if ((version == 100203130) || (version == 100203170)) { // YouTube 10.02.3 return 0; } else { // Unsupported version return -1; } } }