Android Open Source - YouTubeBackgroundPlayback You Tube Background Playback






From Project

Back to project page YouTubeBackgroundPlayback.

License

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.

Java Source Code

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;
    }
  }
}




Java Source Code List

com.pyler.youtubebackgroundplayback.YouTubeBackgroundPlayback.java