added new way of music downloading

This commit is contained in:
Vologhat
2022-07-24 02:17:20 +03:00
parent 63d1c1a3b0
commit d55361fd72
7 changed files with 239 additions and 36 deletions
@@ -15,30 +15,40 @@ import ru.vtosters.lite.downloaders.notifications.NotificationChannels;
import ru.vtosters.lite.music.Callback;
import ru.vtosters.lite.music.FFMpeg;
import ru.vtosters.lite.music.M3UDownloader;
import ru.vtosters.lite.music.MP3Downloader;
import ru.vtosters.lite.utils.Globals;
public class AudioDownloader{
public class AudioDownloader {
private static NotificationManagerCompat notificationManager = NotificationManagerCompat.from(Globals.getContext());
public static void downloadAudio(MusicTrack track){
public static void downloadAudio(MusicTrack track) {
if (Globals.getDefprefs().getBoolean("new_music_downloading_way", false)) {
downloadMP3(track);
} else {
downloadM3U8(track);
}
}
public static void downloadM3U8(MusicTrack track) {
if (track.D == null) {
ToastUtils.a("Не удалось найти ссылку на аудиозапись");
return;
}
var musicPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath();
var tempId = track.d;
var downloadPath = musicPath + File.separator + tempId;
var notification = buildDownloadNotification(track, tempId);
downloadM3U8(track, downloadPath, new Callback(){
var notification = buildDownloadNotification(track, tempId);
downloadM3U8(track, downloadPath, new Callback() {
@Override
public void onProgress(int progress){
public void onProgress(int progress) {
notification.setProgress(100, progress, false);
notificationManager.notify(tempId, notification.build());
}
@Override
public void onSuccess(){
public void onSuccess() {
try {
var fileName = track.toString();
var success = FFMpeg.convert(downloadPath, musicPath + File.separator + fileName + ".mp3");
@@ -59,19 +69,19 @@ public class AudioDownloader{
}
@Override
public void onFailure(){
public void onFailure() {
notification.setContentText("Не удалось загрузить аудиозапись").setProgress(0, 0, false);
notificationManager.notify(tempId, notification.build());
}
@Override
public void onSizeReceived(long size, long header){
public void onSizeReceived(long size, long header) {
}
});
}
private static void downloadM3U8(MusicTrack track, String path, Callback callback){
private static void downloadM3U8(MusicTrack track, String path, Callback callback) {
File outDir = new File(path);
if (!outDir.exists())
if (outDir.mkdir())
@@ -82,7 +92,11 @@ public class AudioDownloader{
new M3UDownloader(track.D, outDir, callback).execute();
}
private static NotificationCompat.Builder buildDownloadNotification(MusicTrack track, int id){
private static void downloadMP3(MusicTrack track) {
new MP3Downloader().execute(track);
}
private static NotificationCompat.Builder buildDownloadNotification(MusicTrack track, int id) {
var notificationBuilder = new NotificationCompat.Builder(Globals.getContext(), NotificationChannels.MUSIC_DOWNLOAD_CHANNEL_ID)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentTitle("Загрузка аудиозаписи")
@@ -0,0 +1,86 @@
package ru.vtosters.lite.music;
import android.app.DownloadManager;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import com.vk.dto.music.MusicTrack;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import ru.vtosters.lite.downloaders.AudioDownloader;
import ru.vtosters.lite.utils.Globals;
public class MP3Downloader {
private static final String URL_FORMAT = "https://api.vk.com/method/audio.getById?v=5.131&access_token=%s&audios=%s&copyright=https://vtosters.app/";
private static final OkHttpClient client = new OkHttpClient();
public MP3Downloader() {
}
public void execute(MusicTrack track) {
var token = Globals.getPreferences().getString("vk_admin_token", "");
if (token.isEmpty()) {
Toast.makeText(Globals.getContext(), "Обновите токен VK Admin в настройках", Toast.LENGTH_SHORT).show();
return;
}
var request = new Request.a()
.b(String.format(URL_FORMAT, token, track.y1()))
.a();
client.a(request).a(new Callback() {
@Override
public void a(Call call, IOException e) {
Log.d("MP3Downloader", e+"");
}
@Override
public void a(Call call, Response response) throws IOException {
var payload = response.a().g();
Log.d("MP3Downloader", payload);
try {
JSONObject jsonObj = new JSONObject(payload);
if (jsonObj.has("response")) {
JSONObject responseNode = new JSONObject(payload).getJSONArray("response")
.getJSONObject(0);
if (responseNode.has("url")) {
var url = responseNode.optString("url");
Log.d("MP3Downloader", url);
if (url != null) {
if (url.endsWith(".mp3")) {
downloadMP3(track.toString(), url);
} else if (VKM3UParser.isM3U8(url)) {
AudioDownloader.downloadM3U8(track);
}
}
}
}
} catch (JSONException e) {
Log.d("MP3Downloader", e+"");
}
}
});
}
private void downloadMP3(String title, String url) {
var downloadManager = Globals.getContext().getSystemService(DownloadManager.class);
var request = new DownloadManager.Request(Uri.parse(url))
.setAllowedOverRoaming(true)
.setTitle("Downloading " + title)
.setDestinationInExternalFilesDir(Globals.getContext(),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(),
title + ".mp3")
.setVisibleInDownloadsUi(true);
downloadManager.enqueue(request);
}
}
@@ -40,7 +40,7 @@ public class VKM3UParser{
} else if (line.startsWith("#EXTINF")) {
if (mTransportStreams.size() == i)
mTransportStreams.add(new TransportStream());
} else if (line.endsWith(".ts") || line.endsWith(".tp") || line.endsWith(".mpeg-ts") || line.endsWith(".m2ts")) {
} else if (isM3U8(line)) {
mTransportStreams.get(i).setName(line);
++i;
}
@@ -51,6 +51,10 @@ public class VKM3UParser{
return directive.substring(directive.indexOf(":") + 1);
}
public static boolean isM3U8(String str) {
return str.endsWith(".ts") || str.endsWith(".tp") || str.endsWith(".mpeg-ts") || str.endsWith(".m2ts");
}
public int getHeapSize(){
return mHeapSize;
}
@@ -0,0 +1,61 @@
package ru.vtosters.lite.ui.activities;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import ru.vtosters.lite.utils.LayoutHelper;
public class VKAdminTokenActivity extends AppCompatActivity {
private static final String URL = "https://oauth.vk.com/authorize?client_id=6121396&scope=1073737727&redirect_uri=https://oauth.vk.com/blank.html&display=page&response_type=token&revoke=1";
@Override
protected void onCreate(@Nullable Bundle bundle) {
super.onCreate(bundle);
var container = new FrameLayout(this);
container.setLayoutParams(LayoutHelper.createFrame(-1, -1));
setContentView(container);
var webView = new WebView(this);
container.addView(webView, LayoutHelper.createFrame(-1, -1));
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
var url = request.getUrl().toString();
if (url.startsWith("https://oauth.vk.com/auth_redirect?")) {
var redirectUri = Uri.parse(URLDecoder.decode(url));
var authorizeUrl = redirectUri.getQueryParameter("authorize_url");
var accessToken = authorizeUrl.substring(authorizeUrl.indexOf("=") + 1, authorizeUrl.indexOf("&"));
var data = new Intent();
data.putExtra("token", accessToken);
setResult(Activity.RESULT_OK, data);
finish();
return false;
}
return super.shouldOverrideUrlLoading(view, request);
}
});
Map<String, String> headers = new HashMap<>();
headers.put("User-Agent", System.getProperty("http.agent"));
webView.loadUrl(URL, headers);
}
}
@@ -13,11 +13,14 @@ import static ru.vtosters.lite.utils.SettBackup.deletePrefs;
import static ru.vtosters.lite.utils.SettBackup.restoreBackup;
import static ru.vtosters.lite.utils.Themes.getAlertStyle;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
import android.widget.ArrayAdapter;
import android.widget.Toast;
@@ -38,19 +41,36 @@ import com.vtosters.lite.im.ImEngineProvider;
import java.io.IOException;
import b.h.g.m.FileUtils;
import ru.vtosters.lite.ui.activities.VKAdminTokenActivity;
import ru.vtosters.lite.utils.Globals;
import ru.vtosters.lite.utils.SettBackup;
public class OtherFragment extends MaterialPreferenceToolbarFragment{
public class OtherFragment extends MaterialPreferenceToolbarFragment {
private static final int VK_ADMIN_TOKEN_REQUEST_CODE = 1;
@Override
public void onCreate(Bundle bundle){
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
addPreferencesFromResource(getIdentifier("preferences_other", "xml"));
prefs();
}
private void prefs(){
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == VK_ADMIN_TOKEN_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
String token = data.getStringExtra("token");
Globals.getPreferences().edit().putString("vk_admin_token", token).apply();
Log.d("VkAdminToken", token);
Toast.makeText(getContext(), "Токен успешно сохранён", LENGTH_SHORT).show();
}
}
}
private void prefs() {
findPreference("firebasefix").setOnPreferenceClickListener(new a());
findPreference("applicationstop").setOnPreferenceClickListener(new b());
findPreference("tokencopy").setOnPreferenceClickListener(new c());
@@ -62,19 +82,30 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment{
findPreference("saveprefs").setOnPreferenceClickListener(new saveprefs());
findPreference("restoreprefs").setOnPreferenceClickListener(new restoreprefs());
var vkAdminTokenPref = findPreference("vk_admin_token");
vkAdminTokenPref.setVisible(Globals.getDefprefs().getBoolean("new_music_downloading_way", false));
if (vkAdminTokenPref.isVisible()) {
vkAdminTokenPref.setOnPreferenceClickListener(preference -> {
startActivityForResult(new Intent(getContext(), VKAdminTokenActivity.class), VK_ADMIN_TOKEN_REQUEST_CODE);
return true;
});
}
}
public static class d implements Preference.OnPreferenceClickListener{
public static class d implements Preference.OnPreferenceClickListener {
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
restartApplication();
return true;
}
}
public class onlines implements Preference.OnPreferenceClickListener{
public class onlines implements Preference.OnPreferenceClickListener {
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
try {
backupOnlines();
} catch (IOException e) {
@@ -84,40 +115,40 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment{
}
}
public static class b implements Preference.OnPreferenceClickListener{
public static class b implements Preference.OnPreferenceClickListener {
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
System.exit(0);
return true;
}
}
public static class deleteprefs implements Preference.OnPreferenceClickListener{
public static class deleteprefs implements Preference.OnPreferenceClickListener {
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
deletePrefs();
restartApplication();
return true;
}
}
class c implements Preference.OnPreferenceClickListener{
public void copy(Context context, String str){
class c implements Preference.OnPreferenceClickListener {
public void copy(Context context, String str) {
((ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("MBH-ST", str));
makeText(context, Globals.getString("copybtn"), LENGTH_SHORT).show();
ToastUtils.a(Globals.getString("tokenwarning"));
}
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
copy(getContext(), getUserToken());
return true;
}
}
public class e implements Preference.OnPreferenceClickListener{
public class e implements Preference.OnPreferenceClickListener {
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
prefs2.edit().clear().commit();
new WebView(getActivity()).clearCache(true);
@@ -132,9 +163,9 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment{
}
}
public class a implements Preference.OnPreferenceClickListener{
public class a implements Preference.OnPreferenceClickListener {
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
VKAccount b = VKAccountManager.d();
PushSubscriber.e.a();
ToastUtils.a(Globals.getString("fcmtokenrem"));
@@ -148,9 +179,9 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment{
}
}
public class f implements Preference.OnPreferenceClickListener{
public class f implements Preference.OnPreferenceClickListener {
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
prefs2.edit().clear().commit();
deleteCache();
@@ -159,20 +190,20 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment{
}
}
public class saveprefs implements Preference.OnPreferenceClickListener{
saveprefs(){
public class saveprefs implements Preference.OnPreferenceClickListener {
saveprefs() {
}
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
backupSettings();
return true;
}
}
public class restoreprefs implements Preference.OnPreferenceClickListener{
public class restoreprefs implements Preference.OnPreferenceClickListener {
@Override // android.support.v7.preference.Preference.c
public boolean onPreferenceClick(Preference preference){
public boolean onPreferenceClick(Preference preference) {
var arr = SettBackup.getBackupsNames();
var adapter = new ArrayAdapter(getContext(), android.R.layout.simple_list_item_1, arr);
new AlertDialog.Builder(getContext(), getAlertStyle())
+4
View File
@@ -60,6 +60,10 @@
android:defaultValue="true"
android:key="musicFixNew"
android:title="Фикс музыки v2" />
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="new_music_downloading_way"
android:title="Новый способ скачивания музыки" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/debug_developer_functions">
<com.vtosters.lite.ui.MaterialSwitchPreference
+3
View File
@@ -28,6 +28,9 @@
<Preference
android:key="tokencopy"
android:title="@string/copytokenbtn" />
<Preference
android:key="vk_admin_token"
android:title="Токен от VK Admin" />
</PreferenceCategory>
<PreferenceCategory android:title="Бэкапы">
<Preference