From 9d8533e066e7ee45d82eb22036ed26fa627f62ca Mon Sep 17 00:00:00 2001 From: aliveoutside <53598473+aliveoutside@users.noreply.github.com> Date: Thu, 15 Sep 2022 20:30:27 +0300 Subject: [PATCH 1/8] fix external video player --- .../java/ru/vtosters/lite/utils/ExternalLinkParser.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/utils/ExternalLinkParser.java b/app/src/main/java/ru/vtosters/lite/utils/ExternalLinkParser.java index f8f8e7ecf..e3f957f22 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/ExternalLinkParser.java +++ b/app/src/main/java/ru/vtosters/lite/utils/ExternalLinkParser.java @@ -59,12 +59,12 @@ public class ExternalLinkParser { if (checkVkVideo(file)) { if (qualities.size() == 1) { - startExternalVideo((String) qualities.values().toArray()[0]); + startExternalVideo((String) qualities.values().toArray()[0], context); } else { String[] titles = qualities.keySet().toArray(new String[0]); new AlertDialog.Builder(context) .setItems(titles, ((dialog, which) -> { - startExternalVideo(qualities.get(titles[which])); + startExternalVideo(qualities.get(titles[which]), context); })) .show(); } @@ -117,7 +117,7 @@ public class ExternalLinkParser { return qualities.size() > 0; } - public static boolean startExternalVideo(String url) { + public static boolean startExternalVideo(String url, Context ctx) { try { qualities.clear(); @@ -136,7 +136,7 @@ public class ExternalLinkParser { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } - getGlobalContext().startActivity(intent); + ctx.startActivity(intent); return true; } catch (Exception e) { e.printStackTrace(); From 371f9ae4a61dc6731323b8bb69cd2f7a29c0531f Mon Sep 17 00:00:00 2001 From: aliveoutside <53598473+aliveoutside@users.noreply.github.com> Date: Thu, 15 Sep 2022 22:51:25 +0300 Subject: [PATCH 2/8] what the fuck? @Vologhat --- app/src/main/java/ru/vtosters/lite/foaf/FoafBase.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/foaf/FoafBase.java b/app/src/main/java/ru/vtosters/lite/foaf/FoafBase.java index 01ff0092b..4bdfa60a2 100644 --- a/app/src/main/java/ru/vtosters/lite/foaf/FoafBase.java +++ b/app/src/main/java/ru/vtosters/lite/foaf/FoafBase.java @@ -13,8 +13,6 @@ import android.app.ProgressDialog; import android.content.Context; import android.util.Log; -import androidx.exifinterface.media.ExifInterface; - import com.vk.core.dialogs.alert.VkAlertDialog; import com.vk.core.network.Network; @@ -165,7 +163,7 @@ public class FoafBase { } private static String getNormalHumanDate(String str) { - String[] split = str.split(ExifInterface.GPS_DIRECTION_TRUE); + String[] split = str.split("T"); return split[1].split("\\+")[0] + " " + split[0]; } } From 96d71394fd9c9651650759a865b54b82470260cb Mon Sep 17 00:00:00 2001 From: aliveoutside <53598473+aliveoutside@users.noreply.github.com> Date: Thu, 15 Sep 2022 23:40:24 +0300 Subject: [PATCH 3/8] merge .ts files more properly use copying instead of recoding merged .ts to mp3 fixes #688 fixes #630 --- .../java/ru/vtosters/lite/music/FFMpeg.java | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/music/FFMpeg.java b/app/src/main/java/ru/vtosters/lite/music/FFMpeg.java index a1a81689a..a1848d30a 100644 --- a/app/src/main/java/ru/vtosters/lite/music/FFMpeg.java +++ b/app/src/main/java/ru/vtosters/lite/music/FFMpeg.java @@ -13,6 +13,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.util.Arrays; import ru.vtosters.lite.utils.AndroidUtils; import ru.vtosters.lite.utils.IOUtils; @@ -52,46 +53,56 @@ public class FFMpeg { public static boolean convert(String in, String out) { checkFFMpegLibs(); - var list = new File(in); - var outputTs = new File(in, "all.ts"); + var tsesList = new File(in).listFiles(); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - for (var file : list.listFiles()) { + if (tsesList == null) { + return false; + } + + var mergedTsFile = new File(in, "all.ts"); + var mergedByteArrayStream = new ByteArrayOutputStream(); + + Arrays.sort(tsesList, (o1, o2) -> { + var index1 = Integer.parseInt(o1.getName().split("-")[1]); + var index2 = Integer.parseInt(o2.getName().split("-")[1]); + return index1 - index2; + }); + + for (var file : tsesList) { if (file.getName().endsWith(".ts")) { try { - outputStream.write(IOUtils.readAllBytes(file)); + mergedByteArrayStream.write(IOUtils.readAllBytes(file)); } catch (IOException e) { e.printStackTrace(); + return false; } } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { try { - Files.write(outputTs.toPath(), outputStream.toByteArray()); + Files.write(mergedTsFile.toPath(), mergedByteArrayStream.toByteArray()); } catch (IOException e) { e.printStackTrace(); + return false; } } else { - try { - FileOutputStream fos = new FileOutputStream(outputTs); - fos.write(outputStream.toByteArray()); - fos.close(); + try (FileOutputStream fos = new FileOutputStream(mergedTsFile)) { + fos.write(mergedByteArrayStream.toByteArray()); } catch (IOException e) { e.printStackTrace(); + return false; } } // convert .ts file to .mp3 file via ffmpeg // var session = FFmpegKit.execute("-i " + in + "/all.ts -f mp3 -acodec mp3 -q:a 0 -y '" + out + "'"); - var session = FFmpegKit.execute("-i " + in + "/all.ts -map 0 -dn -c copy '" + out + "'"); - + var session = FFmpegKit.execute("-y -i " + in + "/all.ts -map 0 -dn -c copy '" + out + "'"); var rc = session.getReturnCode(); + IOUtils.deleteRecursive(new File(in)); if (ReturnCode.isSuccess(rc)) { - // remove temp files - IOUtils.deleteRecursive(new File(in)); return true; } From 7bb0d69a96b0f163a01a27e56269b793ca1b4953 Mon Sep 17 00:00:00 2001 From: aliveoutside <53598473+aliveoutside@users.noreply.github.com> Date: Thu, 15 Sep 2022 23:43:42 +0300 Subject: [PATCH 4/8] parallel .ts downloading --- .../ru/vtosters/lite/music/M3UDownloader.java | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/music/M3UDownloader.java b/app/src/main/java/ru/vtosters/lite/music/M3UDownloader.java index 31a5bb4ac..00f4abc6a 100644 --- a/app/src/main/java/ru/vtosters/lite/music/M3UDownloader.java +++ b/app/src/main/java/ru/vtosters/lite/music/M3UDownloader.java @@ -1,17 +1,18 @@ package ru.vtosters.lite.music; -import android.util.Log; - import java.io.File; import java.io.IOException; import java.io.InputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import javax.crypto.NoSuchPaddingException; +import java8.util.concurrent.CompletableFuture; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -40,31 +41,40 @@ public class M3UDownloader { } private static void parse(String payload, File outDir, Callback callback) { - try { - VKM3UParser parser = new VKM3UParser(payload); - List tses = parser.getTransportStreams(); - callback.onProgress(5); - for (TransportStream ts : tses) { - String tsURL = parser.getBaseUrl() + ts.getName(); - Log.d("M3UDownloader", "Downloading " + tsURL); - InputStream is = IOUtils.openStream(tsURL); - byte[] content; - if (TransportStream.METHOD_AES128.equals(ts.getMethod())) { - String key = IOUtils.readAllLines(IOUtils.openStream(ts.getKeyURL())); - content = IOUtils.decodeStream(is, key); - } else { - content = IOUtils.readAllBytes(is); + VKM3UParser parser = new VKM3UParser(payload); + List tses = parser.getTransportStreams(); + AtomicInteger progress = new AtomicInteger(0); + List> futures = new ArrayList<>(); + + callback.onProgress(5); + for (TransportStream ts : tses) { + String tsURL = parser.getBaseUrl() + ts.getName(); + + futures.add(CompletableFuture.runAsync(() -> { + try { + // Log.d("M3UDownloader", "Downloading " + tsURL); + InputStream is = IOUtils.openStream(tsURL); + byte[] content; + if (TransportStream.METHOD_AES128.equals(ts.getMethod())) { + String key = IOUtils.readAllLines(IOUtils.openStream(ts.getKeyURL())); + content = IOUtils.decodeStream(is, key); + } else { + content = IOUtils.readAllBytes(is); + } + File tsDump = new File(outDir, ts.getName()); + IOUtils.writeToFile(tsDump, content); + callback.onSizeReceived((long) content.length * tses.size(), parser.getHeapSize()); + } catch (IOException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException e) { + e.printStackTrace(); + callback.onFailure(); } - File tsDump = new File(outDir, ts.getName()); - IOUtils.writeToFile(tsDump, content); - callback.onSizeReceived((long) content.length * tses.size(), parser.getHeapSize()); - callback.onProgress(10 + Math.round(80.0f * tses.indexOf(ts) / tses.size())); - } - } catch (IOException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException e) { - e.printStackTrace(); - callback.onFailure(); - return; + }).thenRun(() -> callback.onProgress(10 + Math.round(80.0f * progress.addAndGet(1) / tses.size())))); } + // wait for all futures + for (var future: futures) { + future.join(); + } + callback.onSuccess(); } } From 80d2045fbb0e1c47d3f5842567ecece82567d902 Mon Sep 17 00:00:00 2001 From: aliveoutside <53598473+aliveoutside@users.noreply.github.com> Date: Thu, 15 Sep 2022 23:51:18 +0300 Subject: [PATCH 5/8] update build.gradle --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 0b5d4f986..450e6b3ab 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -88,8 +88,8 @@ android { } dependencies { + implementation 'net.sourceforge.streamsupport:streamsupport-minifuture:1.7.4' implementation 'com.google.android.material:material:1.6.1' - implementation 'androidx.exifinterface:exifinterface:1.3.3' implementation 'androidx.preference:preference:1.2.0' implementation fileTree(dir: 'libs', include: ['*.aar']) compileOnly fileTree(dir: 'libs', include: ['*.jar']) From 0efdefb207656e7a5ecb64b39641910e496e71f5 Mon Sep 17 00:00:00 2001 From: gdlbo <41114720+gdlbo@users.noreply.github.com> Date: Thu, 15 Sep 2022 23:57:15 +0300 Subject: [PATCH 6/8] ThemeChanging meme --- .../ru/vtosters/lite/hooks/JsonInjectors.java | 2 +- .../lite/ui/dialogs/ThemeChanging.java | 33 +++++++++++++++++++ .../navigation/right/RightMenuPresenter.smali | 4 +-- 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/ru/vtosters/lite/ui/dialogs/ThemeChanging.java diff --git a/app/src/main/java/ru/vtosters/lite/hooks/JsonInjectors.java b/app/src/main/java/ru/vtosters/lite/hooks/JsonInjectors.java index cd1eecf7d..b51e2d501 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/JsonInjectors.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/JsonInjectors.java @@ -447,7 +447,7 @@ public class JsonInjectors { } public static JSONObject fetchCatalogId(String section) { - if (section == null) return null; + if (section.isEmpty()) return null; var request = new Request.a() .b("https://" + getApi() + "/method/catalog.getAudio" diff --git a/app/src/main/java/ru/vtosters/lite/ui/dialogs/ThemeChanging.java b/app/src/main/java/ru/vtosters/lite/ui/dialogs/ThemeChanging.java new file mode 100644 index 000000000..6889428e5 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/dialogs/ThemeChanging.java @@ -0,0 +1,33 @@ +package ru.vtosters.lite.ui.dialogs; +import static ru.vtosters.lite.utils.AndroidUtils.edit; +import static ru.vtosters.lite.utils.Preferences.getBoolValue; + +import android.app.Activity; + +import com.vk.core.dialogs.alert.VkAlertDialog; +import com.vk.core.ui.themes.VKThemeHelper; + +import ru.vtosters.lite.hooks.VKUIHook; + +public class ThemeChanging{ + public static void changeTheme(Activity activity, float[] f){ + if (getBoolValue("systemtheme", true)) { + new VkAlertDialog.Builder(activity) + .setTitle("Внимание!") + .setMessage("У вас включена системная тема \n" + + "При переключении темы системная тема будет отключена \n\n" + + "Вы действительно хотите отключить её?") + .setCancelable(false) + .setPositiveButton("Отключить", (dialogInterface, i) -> { + edit().putBoolean("systemtheme", false).commit(); + VKThemeHelper.b(activity, f); + VKUIHook.clearWebCache(); + }) + .setNeutralButton("Отмена", null) + .show(); + } else { + VKThemeHelper.b(activity, f); + VKUIHook.clearWebCache(); + } + } +} diff --git a/smali/smali_classes3/com/vk/navigation/right/RightMenuPresenter.smali b/smali/smali_classes3/com/vk/navigation/right/RightMenuPresenter.smali index f94f9c665..1e5fbb1d4 100644 --- a/smali/smali_classes3/com/vk/navigation/right/RightMenuPresenter.smali +++ b/smali/smali_classes3/com/vk/navigation/right/RightMenuPresenter.smali @@ -242,9 +242,7 @@ if-eqz v0, :cond_0 .line 6 - invoke-static {v0, p1}, Lcom/vk/core/ui/themes/VKThemeHelper;->b(Landroid/app/Activity;[F)V - - invoke-static {}, Lru/vtosters/lite/hooks/VKUIHook;->clearWebCache()V + invoke-static {v0, p1}, Lru/vtosters/lite/ui/dialogs/ThemeChanging;->changeTheme(Landroid/app/Activity;[F)V :cond_0 return-void From 22e12b64224ed3514b47edacec8d6f0df3fd8a3c Mon Sep 17 00:00:00 2001 From: aliveoutside <53598473+aliveoutside@users.noreply.github.com> Date: Fri, 16 Sep 2022 00:13:09 +0300 Subject: [PATCH 7/8] close streams in IOUtils --- .../java/ru/vtosters/lite/utils/IOUtils.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/utils/IOUtils.java b/app/src/main/java/ru/vtosters/lite/utils/IOUtils.java index a0b7db6e3..d736f16e0 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/IOUtils.java +++ b/app/src/main/java/ru/vtosters/lite/utils/IOUtils.java @@ -26,7 +26,10 @@ public class IOUtils { public static byte[] decodeStream(InputStream encIs, String keyURL) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException { CipherInputStream cip = new CipherInputStream(encIs, getCipher(keyURL)); - return readAllBytes(cip); + var bytes = readAllBytes(cip); + cip.close(); + + return bytes; } public static Cipher getCipher(String key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException { @@ -46,7 +49,11 @@ public class IOUtils { } public static String readAllLines(File file) throws IOException { - return readAllLines(new FileInputStream(file)); + var is = new FileInputStream(file); + var bytes = readAllBytes(is); + is.close(); + + return new String(bytes, StandardCharsets.UTF_8); } public static String readAllLines(InputStream is) throws IOException { @@ -54,7 +61,11 @@ public class IOUtils { } public static byte[] readAllBytes(File file) throws IOException { - return readAllBytes(new FileInputStream(file)); + var is = new FileInputStream(file); + var bytes = readAllBytes(is); + is.close(); + + return bytes; } public static byte[] readAllBytes(InputStream is) throws IOException { @@ -63,7 +74,11 @@ public class IOUtils { int len; while ((len = is.read(buffer)) > 0) bos.write(buffer, 0, len); - return bos.toByteArray(); + + var bytes = bos.toByteArray(); + bos.close(); + + return bytes; } public static void writeToFile(File file, String content) throws IOException { @@ -73,6 +88,7 @@ public class IOUtils { public static void writeToFile(File file, byte[] content) throws IOException { FileOutputStream fos = new FileOutputStream(file); fos.write(content); + fos.close(); } public static void deleteRecursive(File f) { From 24c41e5a6d328a2ccaab194cffec7a139ba817b2 Mon Sep 17 00:00:00 2001 From: aliveoutside <53598473+aliveoutside@users.noreply.github.com> Date: Fri, 16 Sep 2022 00:37:08 +0300 Subject: [PATCH 8/8] bypass android notification updates rate limits --- .../lite/downloaders/AudioDownloader.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java b/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java index f3863631b..f7abe9bde 100644 --- a/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java +++ b/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java @@ -50,11 +50,23 @@ public class AudioDownloader { var downloadPath = musicPath + File.separator + tempId; var notification = buildDownloadNotification(track, tempId); + + downloadM3U8(track, downloadPath, new Callback() { + long startTime = 0; + long elapsedTime = 0; + @Override public void onProgress(int progress) { - notification.setProgress(100, progress, false); - notificationManager.notify(tempId, notification.build()); + if (elapsedTime > 1000) { + notification.setProgress(100, progress, false); + notificationManager.notify(tempId, notification.build()); + + startTime = System.currentTimeMillis(); + elapsedTime = 0; + } else { + elapsedTime = System.currentTimeMillis() - startTime; + } } @Override