diff --git a/app/build.gradle b/app/build.gradle index 66a0d96..262a259 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ android { minSdk 27 targetSdk 31 versionCode 505 - versionName "5.0.5" + versionName "5.0.6" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -30,7 +30,10 @@ android { dependencies { compileOnly 'de.robv.android.xposed:api:82' compileOnly 'de.robv.android.xposed:api:82:sources' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.6.0' + implementation 'androidx.preference:preference:1.1.1' // used for debugging only // implementation 'org.apache.commons:commons-lang3:3.12.0' -} +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f4ea3b3..717bcc2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,20 +6,23 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:supportsRtl="true" - android:theme="@style/Theme.MyApplication"> + android:theme="@style/Theme.SettingApp"> + android:value="93+" /> + + diff --git a/app/src/main/java/ma/wanam/youtubeadaway/BFAsync.java b/app/src/main/java/ma/wanam/youtubeadaway/BFAsync.java index f672abc..fb192ab 100644 --- a/app/src/main/java/ma/wanam/youtubeadaway/BFAsync.java +++ b/app/src/main/java/ma/wanam/youtubeadaway/BFAsync.java @@ -22,6 +22,7 @@ import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; import ma.wanam.youtubeadaway.utils.Class3C; +import ma.wanam.youtubeadaway.utils.Constants; public class BFAsync extends AsyncTask { private boolean DEBUG = BuildConfig.DEBUG; @@ -55,24 +56,7 @@ public Handler getHandler() { "_ad_with", "landscape_image_wide_button_layout", "carousel_ad", - "post_base_wrapper", - "community_guidelines", - "sponsorships_comments_upsell", - "member_recognition_shelf", - "compact_banner", - "in_feed_survey", - "medical_panel", - "paid_content_overlay", - "product_carousel", - "publisher_transparency_panel", - "single_item_information_panel", - "horizontal_video_shelf", - "post_shelf", - "channel_guidelines_entry_banner", - "official_card", - "cta_shelf_card", - "expandable_metadata", - "cell_divider" + "paid_content_overlay" })).append(").*").toString(); private static final String filterIgnore = new StringBuffer().append(".*(").append(String.join("|", new String[]{ @@ -89,36 +73,41 @@ public Handler getHandler() { protected Boolean doInBackground(XC_LoadPackage.LoadPackageParam... params) { ClassLoader cl = params[0].classLoader; - XposedHelpers.findAndHookMethod("com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity", cl, "onBackPressed", new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { - if (isAtTopOfView) { - XposedHelpers.callMethod(param.thisObject, "finish"); - } else { - getHandler().removeCallbacksAndMessages(null); - getHandler().postDelayed(() -> isAtTopOfView = true, 1000); - } - } - }); - - XposedHelpers.findAndHookMethod("android.support.v7.widget.RecyclerView", cl, "stopNestedScroll", - new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { + if (params[0].packageName.equals(Constants.GOOGLE_YOUTUBE_PACKAGE)) { + XposedHelpers.findAndHookMethod("com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity", cl, "onBackPressed", new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + if (isAtTopOfView) { + XposedHelpers.callMethod(param.thisObject, "finish"); + } else { getHandler().removeCallbacksAndMessages(null); - isAtTopOfView = false; - getHandler().postDelayed( - () -> isAtTopOfView = !(boolean) XposedHelpers.callMethod(param.thisObject, "canScrollVertically", -1) - , 1000); + getHandler().postDelayed(() -> isAtTopOfView = true, 1000); } - }); + } + }); + + XposedHelpers.findAndHookMethod("android.support.v7.widget.RecyclerView", cl, "stopNestedScroll", + new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + getHandler().removeCallbacksAndMessages(null); + isAtTopOfView = false; + getHandler().postDelayed( + () -> isAtTopOfView = !(boolean) XposedHelpers.callMethod(param.thisObject, "canScrollVertically", -1) + , 1000); + } + }); + } return bruteForceAds(cl); } private boolean bruteForceAds(ClassLoader cl) { Instant start = Instant.now(); - boolean foundBGClass = false, foundInVideoAds = false, foundCardAds = false, skip; + boolean foundBGClass = !Xposed.prefs.getBoolean("enable_bg_playback", true), + foundInVideoAds = false, + foundCardAds = !Xposed.prefs.getBoolean("hide_ad_cards", false), + skip; Class3C heapPermutation = new Class3C(); while (heapPermutation.hasNext()) { @@ -334,4 +323,4 @@ protected void onPostExecute(Boolean found) { } } -} +} \ No newline at end of file diff --git a/app/src/main/java/ma/wanam/youtubeadaway/MainActivity.java b/app/src/main/java/ma/wanam/youtubeadaway/MainActivity.java deleted file mode 100644 index f5daf6d..0000000 --- a/app/src/main/java/ma/wanam/youtubeadaway/MainActivity.java +++ /dev/null @@ -1,64 +0,0 @@ -package ma.wanam.youtubeadaway; - -import android.app.Activity; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.Color; -import android.net.Uri; -import android.os.Bundle; -import android.widget.TextView; -import android.widget.Toast; - -import ma.wanam.youtubeadaway.R.id; - -public class MainActivity extends Activity { - private final String DONATE_URL = "https://www.paypal.me/Wanam"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - String pInfo = ""; - try { - pInfo = getPackageManager().getPackageInfo(getPackageName(), 0).versionName; - } catch (Throwable e) { - e.printStackTrace(); - } - Resources res = getResources(); - String status = res.getString(R.string.app_name) - + " v" - + pInfo - + " " - + (XChecker.isEnabled() ? res.getString(R.string.module_active) : res - .getString(R.string.module_inactive)); - TextView tvStatus = findViewById(id.moduleStatus); - tvStatus.setText(status); - tvStatus.setTextColor((XChecker.isEnabled() ? Color.GREEN : Color.RED)); - - findViewById(id.btnOK).setOnClickListener(v -> finish()); - - findViewById(id.btnDonate).setOnClickListener(v -> { - try { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(DONATE_URL)); - startActivity(browserIntent); - } catch (Throwable e) { - e.printStackTrace(); - } finally { - finish(); - } - }); - - TextView tv = findViewById(id.textViewBTCAdr); - tv.setOnLongClickListener(v -> { - ClipboardManager cm = (ClipboardManager) getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("btc_adr", tv.getText()); - cm.setPrimaryClip(clip); - Toast.makeText(getApplicationContext(), R.string.addr_copied, Toast.LENGTH_SHORT).show(); - return false; - }); - } -} diff --git a/app/src/main/java/ma/wanam/youtubeadaway/SettingsActivity.java b/app/src/main/java/ma/wanam/youtubeadaway/SettingsActivity.java new file mode 100644 index 0000000..e915504 --- /dev/null +++ b/app/src/main/java/ma/wanam/youtubeadaway/SettingsActivity.java @@ -0,0 +1,63 @@ +package ma.wanam.youtubeadaway; + +import android.annotation.SuppressLint; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.util.Log; + +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; + +public class SettingsActivity extends AppCompatActivity { + private static SharedPreferences prefs; + + @SuppressLint("WorldReadableFiles") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.settings_activity); + if (savedInstanceState == null) { + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.settings, new SettingsFragment()) + .commit(); + } + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + try { + prefs = getSharedPreferences(getPackageName() + "_preferences", MODE_WORLD_READABLE); + } catch (SecurityException ignored) { + Log.e(getPackageName(), ignored.toString()); + } + } + + public static class SettingsFragment extends PreferenceFragmentCompat { + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.root_preferences, rootKey); + + // copy btc wallet address to the clipboard + getPreferenceScreen().findPreference("donate_btc") + .setOnPreferenceClickListener(preference -> { + ClipboardManager clipboardManager = (ClipboardManager) + getActivity().getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clipData = ClipData.newPlainText(preference.getKey(), preference.getSummary()); + clipboardManager.setPrimaryClip(clipData); + + return true; + }); + + // set module status + Preference statusPreference = getPreferenceScreen().findPreference("status"); + statusPreference.setIcon(XChecker.isEnabled() ? android.R.drawable.ic_dialog_info : android.R.drawable.ic_dialog_alert); + statusPreference.setSummary(XChecker.isEnabled() ? R.string.module_active : R.string.module_inactive); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ma/wanam/youtubeadaway/Xposed.java b/app/src/main/java/ma/wanam/youtubeadaway/Xposed.java index 25824e3..9a045de 100644 --- a/app/src/main/java/ma/wanam/youtubeadaway/Xposed.java +++ b/app/src/main/java/ma/wanam/youtubeadaway/Xposed.java @@ -1,14 +1,17 @@ package ma.wanam.youtubeadaway; import de.robv.android.xposed.IXposedHookLoadPackage; +import de.robv.android.xposed.IXposedHookZygoteInit; import de.robv.android.xposed.XC_MethodReplacement; +import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; import ma.wanam.youtubeadaway.utils.Constants; import ma.wanam.youtubeadaway.utils.Utils; -public class Xposed implements IXposedHookLoadPackage { +public class Xposed implements IXposedHookLoadPackage, IXposedHookZygoteInit { + public static XSharedPreferences prefs; @Override public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { @@ -24,6 +27,11 @@ public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { String ytVersion = Utils.getPackageVersion(lpparam); XposedBridge.log("Hooking YouTube version: " + lpparam.packageName + " " + ytVersion); + if (prefs != null) { + prefs.reload(); + } else + XposedBridge.log("CANNOT read module preferences!!!"); + new BFAsync().execute(lpparam); } catch (Throwable t) { XposedBridge.log(t); @@ -40,4 +48,9 @@ public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { } } } + + @Override + public void initZygote(StartupParam startupParam) throws Throwable { + prefs = new XSharedPreferences(BuildConfig.APPLICATION_ID); + } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 9c311b5..0000000 --- a/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - -