package com.kpstv.youtube.utils; import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ContentUris; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.media.MediaMetadataRetriever; import android.media.RingtoneManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Environment; import android.os.VibrationEffect; import android.os.Vibrator; import android.provider.DocumentsContract; import android.provider.MediaStore; import android.provider.Settings; import android.support.annotation.RequiresApi; import android.support.constraint.ConstraintLayout; import android.support.customtabs.CustomTabsIntent; import android.support.v4.app.ShareCompat; import android.support.v4.content.ContextCompat; import android.support.v4.content.FileProvider; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.os.EnvironmentCompat; import android.support.v7.app.AlertDialog; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.Html; import android.text.Spanned; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RadioButton; import android.widget.TextView; import android.widget.Toast; import com.downloader.Error; import com.downloader.OnDownloadListener; import com.downloader.PRDownloader; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.gms.ads.AdListener; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.InterstitialAd; import com.google.android.gms.common.util.IOUtils; import com.karumi.dexter.Dexter; import com.karumi.dexter.PermissionToken; import com.karumi.dexter.listener.PermissionDeniedResponse; import com.karumi.dexter.listener.PermissionGrantedResponse; import com.karumi.dexter.listener.PermissionRequest; import com.karumi.dexter.listener.single.PermissionListener; import com.kpstv.youtube.AppInterface; import com.kpstv.youtube.AppSettings; import com.kpstv.youtube.BuildConfig; import com.kpstv.youtube.CPlaylistActivity; import com.kpstv.youtube.ErrorActivity; import com.kpstv.youtube.MainActivity; import com.kpstv.youtube.PurchaseActivity; import com.kpstv.youtube.R; import com.kpstv.youtube.adapters.ImportAdapter; import com.kpstv.youtube.helper.BillingUtils; import com.kpstv.youtube.models.ImportModel; import com.kpstv.youtube.models.LocalModel; import com.kpstv.youtube.models.MetaModel; import com.kpstv.youtube.models.YTConfig; import com.kpstv.youtube.services.IntentDownloadService; import com.kpstv.youtube.services.MusicService; import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.nio.channels.FileChannel; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import static android.content.Context.LAYOUT_INFLATER_SERVICE; import static android.content.Context.MODE_PRIVATE; public class YTutils implements AppInterface { private static final String TAG = "YTutils"; public static String[] ConvertToStringArray(ArrayList<String> list) { final String[] arrays = new String[list.size()]; for (int i = 0; i < list.size(); i++) arrays[i] = list.get(i); return arrays; } public static String getImageUrl(String YtUrl) { String quality = MainActivity.activity.getSharedPreferences("appSettings", MODE_PRIVATE) .getString("pref_image_quality", "mq"); return "https://i.ytimg.com/vi/" + getVideoID(YtUrl) + "/" + quality + "default.jpg"; /* String imageUrl = "https://i.ytimg.com/vi/"+getVideoID(YtUrl)+"/mqdefault.jpg"; if (MainActivity.activity.getSharedPreferences("appSettings",MODE_PRIVATE) .getString("pref_image_quality","mq").equals("hq")) imageUrl = "https://i.ytimg.com/vi/"+getVideoID(YtUrl)+"/hqdefault.jpg"; return imageUrl;*/ } static String link; public static void addADView(Activity activity, LinearLayout l) { l.setVisibility(View.VISIBLE); int number = ThreadLocalRandom.current().nextInt(1, 4); l.removeAllViews(); int layout;// = R.layout.ad_banner; if (number==1) { layout = R.layout.ad_banner; link = "https://androdevkit.github.io"; }else if (number==2) { layout = R.layout.ad_banner_2; link = "https://github.com/KaustubhPatange/Kling"; }else { layout = R.layout.ad_banner_3; link = "https://kaustubhpatange.github.io/Iso2Usb"; } View v = LayoutInflater.from(activity).inflate(layout,null); v.findViewById(R.id.ad_banner_click).setOnClickListener(view -> YTutils.StartURL(link,activity)); l.addView(v); } public static String getImageUrlID_HQ(String videoID) { return "https://i.ytimg.com/vi/" + videoID + "/hqdefault.jpg"; } public static String getImageUrlID_MAX(String videoID) { return "https://i.ytimg.com/vi/" + videoID + "/maxresdefault.jpg"; } public static String getImageUrlID_MQ(String videoID) { return "https://i.ytimg.com/vi/" + videoID + "/mqdefault.jpg"; } public static String getImageUrlID(String videoID) { String quality = MainActivity.activity.getSharedPreferences("appSettings", MODE_PRIVATE) .getString("pref_image_quality", "mq"); return "https://i.ytimg.com/vi/" + videoID + "/" + quality + "default.jpg"; /* String imageUrl = "https://i.ytimg.com/vi/"+videoID+"/mqdefault.jpg"; try { if (MainActivity.activity.getSharedPreferences("appSettings",MODE_PRIVATE) .getString("pref_image_quality","mq").equals("hq")) imageUrl = "https://i.ytimg.com/vi/"+videoID+"/hqdefault.jpg"; }catch (Exception e){e.printStackTrace();} return imageUrl;*/ } public static String getImageUrlID(Context context,String videoID) { String quality = context.getSharedPreferences("appSettings", MODE_PRIVATE) .getString("pref_image_quality", "mq"); return "https://i.ytimg.com/vi/" + videoID + "/" + quality + "default.jpg"; /* String imageUrl = "https://i.ytimg.com/vi/"+videoID+"/mqdefault.jpg"; try { if (MainActivity.activity.getSharedPreferences("appSettings",MODE_PRIVATE) .getString("pref_image_quality","mq").equals("hq")) imageUrl = "https://i.ytimg.com/vi/"+videoID+"/hqdefault.jpg"; }catch (Exception e){e.printStackTrace();} return imageUrl;*/ } /*public static String getImageUrlID(Context context,String videoID) { String imageUrl = "https://i.ytimg.com/vi/"+videoID+"/mqdefault.jpg"; if (context.getSharedPreferences("pref_image_quality",MODE_PRIVATE) .getString("pref_image_quality","mq").equals("hq")) imageUrl = "https://i.ytimg.com/vi/"+videoID+"/hqdefault.jpg"; Log.e(TAG, "getImageUrlID: Context ImageUrl: "+imageUrl ); return imageUrl; }*/ public static void openSong(Context context, Intent intent) { try { /* if (MainActivity.activity==null) { Intent im = new Intent(context, MainActivity.class); im.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(im); }*/ Log.e(TAG, "onReceive: triggered"); Log.e(TAG, "onReceive: " + intent.getData().toString()); Uri uri = intent.getData(); Log.e(TAG, "onReceive: " + uri.toString()); File f = new File(uri.getPath()); Log.e(TAG, "onReceive: File: " + f.getPath()); if (!f.exists()) { f = new File(uri.toString().replace(".mp3", ".m4a")); } if (f.exists()) { if (uri.toString().contains(".mp4")) { Intent i = new Intent(); i.setAction(Intent.ACTION_VIEW); i.setDataAndType(uri, "video/*"); i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); return; } File downloads = YTutils.getFile(Environment.DIRECTORY_DOWNLOADS); File[] files = downloads.listFiles(new FileFilter() { @Override public boolean accept(File file) { return (file.getPath().endsWith(".mp3") || file.getPath().endsWith(".m4a") || file.getPath().endsWith(".wav") || file.getPath().endsWith(".aac") || file.getPath().endsWith(".ogg") || file.getPath().endsWith(".flac")); } }); if (files.length > 0) { String[] ids = new String[files.length]; int position = 0; for (int i = 0; i < files.length; i++) { File id = files[i]; ids[i] = files[i].getPath(); Log.e(TAG, "onReceive: ID PATH: " + id.getPath()); if (id.getPath().equals(f.getPath())) { position = i; break; } } MainActivity.PlayVideo_Local(context, ids, position); } else Toast.makeText(context, "There seems to be an error in parsing downloads!", Toast.LENGTH_SHORT).show(); } else Toast.makeText(context, "Error: File not found!", Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(context, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } } public static void commonBilling(Context context) { SharedPreferences pref = context.getSharedPreferences("appSettings", MODE_PRIVATE); if (!pref.getBoolean("pref_audioChange", true)) AppSettings.listenAudioChange = false; if (pref.getBoolean("pref_purchase", false)) BillingUtils.publishPremium(); } public static String getYtUrl(String videoID) { if (videoID.contains("soundcloud.com")) return videoID; return "https://www.youtube.com/watch?v=" + videoID; } public static void showAlert(Activity activity, String title, String message, boolean isalert) { int icon = android.R.drawable.ic_dialog_info; if (isalert) icon = android.R.drawable.ic_dialog_alert; new AlertDialog.Builder(activity) .setTitle(title) .setMessage(message) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .setIcon(icon) .show(); } public static String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line).append('\n'); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } public static void Write(String string, File file) { try { FileOutputStream f = new FileOutputStream(file); PrintWriter pw = new PrintWriter(f); pw.write(string); pw.flush(); pw.close(); f.close(); } catch (FileNotFoundException e) { e.printStackTrace(); Log.i("writeToSDFile2", "******* File not found. Did you" + " add a WRITE_EXTERNAL_STORAGE permission to the manifest?"); } catch (IOException e) { e.printStackTrace(); } Log.e("writeToSDFile3", "\n\nFile written to " + file); } public static File getFile(String targetfolder) { File root = android.os.Environment.getExternalStorageDirectory(); File dir = new File(root.getAbsolutePath() + "/" + targetfolder); return dir; } public static void CreateFile(File file) { /*File root = android.os.Environment.getExternalStorageDirectory(); Log.e("CreateDir",targetfolder);*/ File dir = file; try { dir.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } public static void writeContent(Context activity, String FILE_NAME, String content) { if (applicationContext==null) applicationContext = activity.getApplicationContext(); FileOutputStream fos = null; try { if (FILE_NAME.contains("/")) { fos = new FileOutputStream(new File(FILE_NAME)); } else { fos = applicationContext.openFileOutput(FILE_NAME, MODE_PRIVATE); } fos.write(content.getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } static String formatString(String t) { t = t.replace(",", ""); t = t.replace("|", " "); return t; } static AlertDialog alertDialog; public static void addToPlayList(Context activity, String videoID, String videoTitle, String channelTitle, String imageUrl, long seconds) { Log.e(TAG, "addToPlayList: VideoId" + videoID + ",Seconds: " + seconds); AlertDialog.Builder builder = new AlertDialog.Builder(activity); // builder.setTitle("Add to playlist"); ArrayList<String> configs = new ArrayList<>(); LayoutInflater inflater = (LayoutInflater) activity.getSystemService(LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.alert_playlist_layout, null); ListView listView = view.findViewById(R.id.recyclerView); ConstraintLayout constraintLayout = view.findViewById(R.id.mainLayout); constraintLayout.setOnClickListener(view1 -> { alertDialog.dismiss(); Intent intent = new Intent(activity, CPlaylistActivity.class); activity.startActivity(intent); }); builder.setView(view); String playlist_csv = YTutils.readContent(activity, "playlist.csv"); if (playlist_csv != null && !playlist_csv.isEmpty()) { String[] allPlaylist = playlist_csv.split("\n|\r"); for (String line : allPlaylist) { String[] playlist = line.split(","); configs.add(playlist[1]); } final String[] arrays = new String[configs.size()]; for (int i = 0; i < configs.size(); i++) { arrays[i] = configs.get(i); } ArrayAdapter<String> adapter = new ArrayAdapter<>(activity, android.R.layout.simple_list_item_1, configs); listView.setAdapter(adapter); listView.setOnItemClickListener((adapterView, view1, which, l) -> { boolean alreadPresent = false, added = false; String name = configs.get(which); for (int i = 0; i < configs.size(); i++) { if (allPlaylist[i].contains("," + name) && !allPlaylist[i].contains(videoID + "|")) { allPlaylist[i] += "," + videoID + "|" + seconds + "|" + formatString(videoTitle) + "|" + channelTitle + "|" + imageUrl; writeContent(activity, "playlist.csv", join(allPlaylist, '\n')); added = true; Toast.makeText(activity, "Added to playlist", Toast.LENGTH_SHORT).show(); } else alreadPresent = true; } if (alreadPresent && !added) Toast.makeText(activity, "Already exist in playlist", Toast.LENGTH_SHORT).show(); alertDialog.dismiss(); }); /* builder.setItems(arrays, (dialog, which) -> { });*/ } alertDialog = builder.create(); alertDialog.show(); } /* public Long getTodayTimeString() { Date c = Calendar.getInstance().getTime(); @SuppressLint("SimpleDateFormat") SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); return Long.parseLong(df.format(c)); } public String getLastSavedUrl(Context activity,String videoId) { String data = YTutils.readContent(activity,"lastSavedUrls.csv"); if (data!=null && !data.isEmpty()) { long today_time= String[] items = data.spl it("\n|\r"); for (int i=0;i<items.length;i++) { if (items[0].split("\\|")[0]) } } return null; } */ public static String setVideoTitle(String title) { Log.e("VideoTitle", title); String t = title; if (t.contains("-")) { t = t.split("-")[1].trim(); MusicService.channelTitle = title.split("-")[0]; } // (Mark orision) if (t.contains("(")) { t = t.split("\\(")[0].trim(); } if (t.contains("[")) t = t.split("\\[")[0].trim(); return t; } public static String getVideoTitle(String title) { String t = title; if (t.contains("'")) t = t.replace("'", "'"); if (t.contains("-")) { if (t.split("\\-").length < 3) t = t.split("\\-")[1].trim(); } if (t.contains("(")) { t = t.split("\\(")[0].trim(); } if (t.contains("[")) t = t.split("\\[")[0].trim(); return t.trim(); } public static void setDefaultRingtone(Activity activity, File f) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { boolean retVal = Settings.System.canWrite(activity); if (!retVal) { android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(activity); builder.setTitle("Set ringtone"); builder.setMessage("Allow YTPlayer to modify audio settings"); builder.setNegativeButton("Cancel", null); builder.setPositiveButton("OK", (dialogInterface, i) -> { Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + activity.getPackageName())); activity.startActivity(intent); }); android.app.AlertDialog dialog = builder.create(); dialog.show(); return; } } Toast.makeText(activity, "New ringtone set!", Toast.LENGTH_SHORT).show(); setRingtone(activity, f); } public static String getRedirectAppUrl(String urlOriginal) { if (StringUtils.isEmpty(urlOriginal)) { return null; } URL u = null; try { u = new URL(urlOriginal); HttpURLConnection huc = (HttpURLConnection) u.openConnection(); huc.setInstanceFollowRedirects(false); huc.setReadTimeout(5000); boolean redirect = false; int status = huc.getResponseCode(); if (status != HttpURLConnection.HTTP_OK) { if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM || status == HttpURLConnection.HTTP_SEE_OTHER) { redirect = true; } } if (redirect) { String newUrl = huc.getHeaderField("Location"); return newUrl; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } static void setRingtone(Activity activity, File f) { try { RingtoneManager.setActualDefaultRingtoneUri(activity, RingtoneManager.TYPE_RINGTONE, Uri.fromFile(f)); } catch (Exception t) { t.printStackTrace(); } } public static String getChannelTitle(String title, String defaulttitle) { if (title.contains("'")) title = title.replace("'", "'"); if (defaulttitle.contains("-")) defaulttitle = defaulttitle.split("-")[0]; if (title.contains("-")) { String t = title; if (t.split("\\-").length < 3) t = t.split("\\-")[0].trim(); return t.trim(); } else return defaulttitle; } public static void Vibrate(Context context) { Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { vibrator.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)); } else { vibrator.vibrate(100); } } public static ArrayList<String> convertArrayToArrayList(String[] arr) { ArrayList<String> l = new ArrayList<>(Arrays.asList(arr)); return l; } public static Context applicationContext; public static String readContent(Context activity, String FILE_NAME) { if (applicationContext==null) applicationContext = activity.getApplicationContext(); FileInputStream fis = null; StringBuilder sb = new StringBuilder(); try { if (FILE_NAME.contains("/")) { File f = new File(FILE_NAME); if (!f.exists()) return null; fis = new FileInputStream(f); } else { File f = new File(applicationContext.getFilesDir(), FILE_NAME); if (!f.exists()) return null; fis = applicationContext.openFileInput(FILE_NAME); } if (fis == null) return null; InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String text; while ((text = br.readLine()) != null) { sb.append(text).append("\n"); } return sb.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } public static String getSpotifyID(String spotifyurl) { // https://open.spotify.com/track/4hPpVbbakQNv8YTHYaOJP4 String url; if (spotifyurl.contains("open.spotify")) { url = spotifyurl.split("/")[4]; if (url.contains("?")) return url.split("\\?")[0]; else return url; } return null; } public static String dividePattern(float num1, float num2, String pattern) { DecimalFormat df = new DecimalFormat(pattern); return df.format(num1 / num2) + ""; } public static String getSize(long size) { DecimalFormat df = new DecimalFormat("0.00"); float sizeKb = 1024.0f; float sizeMb = sizeKb * sizeKb; float sizeGb = sizeMb * sizeKb; float sizeTerra = sizeGb * sizeKb; if (size < sizeMb) return df.format(size / sizeKb) + " KB"; else if (size < sizeGb) return df.format(size / sizeMb) + " MB"; else if (size < sizeTerra) return df.format(size / sizeGb) + " GB"; return ""; } public static String getSizeNoDecimal(long size) { DecimalFormat df = new DecimalFormat("0"); float sizeKb = 1024.0f; float sizeMb = sizeKb * sizeKb; float sizeGb = sizeMb * sizeKb; float sizeTerra = sizeGb * sizeKb; if (size < sizeMb) return df.format(size / sizeKb) + " KB"; else if (size < sizeGb) return df.format(size / sizeMb) + " MB"; else if (size < sizeTerra) return df.format(size / sizeGb) + " GB"; return ""; } public static String getSize_withoutPostFix(long size) { DecimalFormat df = new DecimalFormat("0.00"); float sizeKb = 1024.0f; float sizeMb = sizeKb * sizeKb; float sizeGb = sizeMb * sizeKb; float sizeTerra = sizeGb * sizeKb; if (size < sizeMb) return df.format(size / sizeKb); else if (size < sizeGb) return df.format(size / sizeMb); else if (size < sizeTerra) return df.format(size / sizeGb); return "0"; } public static String getViewCount(long number) { if (number > 1000000000) { // billion return number / 1000000000 + "B"; } else if (number > 1000000) { // million return number / 1000000 + "M"; } else if (number > 1000) { return number / 1000 + "K"; } return number + "0"; } public static int progressToTimer(int progress, long totalDuration) { int currentDuration = 0; totalDuration = (int) (totalDuration / 1000); currentDuration = (int) ((((double) progress) / 100) * totalDuration); // return current duration in milliseconds return currentDuration * 1000; } public static boolean isValidID(String url) { return (url.contains("youtube.com") || url.contains("youtu.be")); } public static String convertArrayToStringMethod(String[] strArray) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < strArray.length; i++) { stringBuilder.append(strArray[i]).append("\n"); } return stringBuilder.toString(); } public static String convertListToStringMethod(List<String> strArray) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < strArray.size(); i++) { stringBuilder.append(strArray.get(i)).append("\n"); } return stringBuilder.toString(); } public static String[] convertListToArrayMethod(ArrayList<String> strArray) { String[] arr = new String[strArray.size()]; arr = strArray.toArray(arr); return arr; } public static String getTodayDate() { Date c = Calendar.getInstance().getTime(); @SuppressLint("SimpleDateFormat") SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy"); return df.format(c); } public static String getDate(Date c) { @SuppressLint("SimpleDateFormat") SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); return df.format(c); } public static String getTodayDate_nogaps() { Date c = Calendar.getInstance().getTime(); @SuppressLint("SimpleDateFormat") SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); return df.format(c); } public static String getTomorrowDate_nogap() { Date c = Calendar.getInstance().getTime(); @SuppressLint("SimpleDateFormat") String date = new SimpleDateFormat("dd").format(c); @SuppressLint("SimpleDateFormat") String month = new SimpleDateFormat("MM").format(c); @SuppressLint("SimpleDateFormat") String year = new SimpleDateFormat("yyyy").format(c); return year + "" + month + (Integer.parseInt(date) + 1); } public static String getYesterday_nogap() { Date c = Calendar.getInstance().getTime(); @SuppressLint("SimpleDateFormat") String date = new SimpleDateFormat("dd").format(c); @SuppressLint("SimpleDateFormat") String month = new SimpleDateFormat("MM").format(c); @SuppressLint("SimpleDateFormat") String year = new SimpleDateFormat("yyyy").format(c); return year + "" + month + (Integer.parseInt(date) - 1); } public static String getLocalArtworkImage(Activity activity, LocalModel model) { if (!YTutils.isInternetAvailable()) return null; String data = YTutils.readContent(activity, "artistImages.csv"); String imageUri = null; if (data != null && !data.isEmpty()) { String title = model.getTitle().trim(); if (data.contains(title + "$")) { String[] items = data.split("\n|\r"); for (String item : items) { if (item.isEmpty()) continue; if (item.contains(title + "$")) { imageUri = item.split("\\$")[1]; return imageUri; } } } else { ArtistImage artistImage = new ArtistImage(title); imageUri = artistImage.getImageUri(); YTutils.writeContent(activity, "artistImages.csv", data + title + "$" + imageUri); } } else { String title = model.getTitle().trim(); ArtistImage artistImage = new ArtistImage(title); imageUri = artistImage.getImageUri(); YTutils.writeContent(activity, "artistImages.csv", title + "$" + imageUri); } return imageUri; } public static void openPurchaseActivity(Context context) { Intent intent = new Intent(context, PurchaseActivity.class); context.startActivity(intent); } public static String getPlayBackstate(int state) { switch (state) { case ExoPlayer.STATE_IDLE: return "IDLE"; case ExoPlayer.STATE_BUFFERING: return "BUFFERING"; case ExoPlayer.STATE_READY: return "READY"; case ExoPlayer.STATE_ENDED: return "ENDED"; } return "-1"; } public static String getAudioFormat(File f) { String ext = f.getPath().substring(f.getPath().lastIndexOf("."), f.getPath().length()); switch (ext) { case ".mp3": return "MPEG-1 Audio Layer 3"; case ".m4a": case ".ogg": case ".aac": return "HE-AAC"; } return null; } public static Bitmap getArtworkFromFile(Activity activity, File f) { try { MediaMetadataRetriever mmr = new MediaMetadataRetriever(); mmr.setDataSource(activity, Uri.fromFile(f)); byte[] data = mmr.getEmbeddedPicture(); if (data != null) { return BitmapFactory.decodeByteArray(data, 0, data.length); } } catch (Exception e) { e.getMessage(); } return null; } /*public static String getArtistImage(String query) { // https://www.googleapis.com/youtube/v3/search?part=snippet&q=Ashley%20O&type=channel&key=[YOUR_API_KEY] HttpHandler handler }*/ public static byte[] getByteFromBitmap(Bitmap bmp) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray(); bmp.recycle(); return byteArray; } public static boolean isProcessCompleted(Process process) { try { if (process == null) return true; process.exitValue(); return true; } catch (IllegalThreadStateException e) { // do nothing } return false; } public static boolean isDebug(Context context) { return (0 != (context.getApplicationContext().getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE)); } public static void close(InputStream inputStream) { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { // Do nothing } } } public static void close(OutputStream outputStream) { if (outputStream != null) { try { outputStream.flush(); outputStream.close(); } catch (IOException e) { // Do nothing } } } public static String convertInputStreamToString(InputStream inputStream) { try { BufferedReader r = new BufferedReader(new InputStreamReader(inputStream)); String str; StringBuilder sb = new StringBuilder(); while ((str = r.readLine()) != null) { sb.append(str); } return sb.toString(); } catch (IOException e) { Log.e(TAG, "error converting input stream to string" + e.getMessage()); } return null; } @RequiresApi(api = Build.VERSION_CODES.O) public static void destroyProcess(Process process) { if (process != null) process.destroyForcibly(); } static boolean killAsync(AsyncTask asyncTask) { return asyncTask != null && !asyncTask.isCancelled() && asyncTask.cancel(true); } public static void shareFile(Activity context, File f) { try { Uri uri = Uri.fromFile(f); ShareCompat.IntentBuilder.from(context) .setStream(uri) .setType(URLConnection.guessContentTypeFromName(f.getName())) .startChooser(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(context, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } } public static String getTodayDate_Time() { Date c = Calendar.getInstance().getTime(); @SuppressLint("SimpleDateFormat") SimpleDateFormat df = new SimpleDateFormat("ddMMyyyy_HHmmss"); return df.format(c); } public static String getYesterdayDate() { Date c = Calendar.getInstance().getTime(); @SuppressLint("SimpleDateFormat") String date = new SimpleDateFormat("dd").format(c); @SuppressLint("SimpleDateFormat") String month = new SimpleDateFormat("MM").format(c); @SuppressLint("SimpleDateFormat") String year = new SimpleDateFormat("yyyy").format(c); return (Integer.parseInt(date) - 1) + "-" + month + "-" + year; } public static String getVideoID_ImageUri(String imageUrl) { // "https://i.ytimg.com/vi/"+videoID+"/mqdefault.jpg"; String t = imageUrl; t = t.split("/")[4]; return t; } public static Bitmap getBitmapFromURL(String src) { try { java.net.URL url = new java.net.URL(src); HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setDoInput(true); connection.connect(); InputStream input = connection.getInputStream(); Bitmap myBitmap = BitmapFactory.decodeStream(input); return myBitmap; } catch (IOException e) { e.printStackTrace(); return null; } } public static String getVideoID(String youtube_url) { String t = youtube_url; if (t.contains("soundcloud.com")) return t; if (youtube_url.contains("youtube.com")) { t = youtube_url.split("=")[1]; } else if (youtube_url.contains("youtu.be")) { t = youtube_url.replace("https://youtu.be/", ""); } if (t.contains("&")) t = t.split("&")[0]; return t; } public static void deleteRecursive(File fileOrDirectory) { if (fileOrDirectory.isDirectory()) for (File child : fileOrDirectory.listFiles()) deleteRecursive(child); fileOrDirectory.delete(); } public static void StartURL(String url, Context context) { CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); builder.setToolbarColor(ContextCompat.getColor(context, R.color.colorPrimary)); CustomTabsIntent customTabsIntent = builder.build(); try { PackageInfo packageInfo = context.getPackageManager().getPackageInfo("com.android.chrome", 0); customTabsIntent.intent.setPackage("com.android.chrome"); customTabsIntent.launchUrl(context, Uri.parse(url)); } catch (Exception e) { Log.e("Chrome", "Chrome not installed: " + e.getMessage()); StartURLIntent(url, context); } } public static String getUrlVideoRTSP(String urlYoutube) { try { String gdy = "http://gdata.youtube.com/feeds/api/videos/"; DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); String id = getVideoID(urlYoutube); URL url = new URL(gdy + id); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); Document doc = documentBuilder.parse(connection.getInputStream()); Element el = doc.getDocumentElement(); NodeList list = el.getElementsByTagName("media:content");///media:content String cursor = urlYoutube; for (int i = 0; i < list.getLength(); i++) { Node node = list.item(i); if (node != null) { NamedNodeMap nodeMap = node.getAttributes(); HashMap<String, String> maps = new HashMap<String, String>(); for (int j = 0; j < nodeMap.getLength(); j++) { Attr att = (Attr) nodeMap.item(j); maps.put(att.getName(), att.getValue()); } if (maps.containsKey("yt:format")) { String f = maps.get("yt:format"); if (maps.containsKey("url")) { cursor = maps.get("url"); } if (f.equals("1")) return cursor; } } } return cursor; } catch (Exception ex) { Log.e("RTSP_Video", ex.toString()); } return urlYoutube; } public static long TimertoMilliseconds(String timer) { String[] idls = timer.split(":"); Log.e("IDLS_Count", idls.length + ""); if (idls.length > 2) { // It contains hour... // 3:02:11 long hour = Long.parseLong(idls[0]) * 60 * 60 * 1000; long min = Long.parseLong(idls[1]) * 60 * 1000; long sec = Long.parseLong(idls[2]) * 1000; return hour + min + sec; } else { // It is only minutes... //3:04 long min = Long.parseLong(idls[0]) * 60 * 1000; long sec = Long.parseLong(idls[1]) * 1000; return min + sec; } } public static void setBackroundTint(FrameLayout frameLayout, int color) { Drawable buttonDrawable = frameLayout.getBackground(); buttonDrawable = DrawableCompat.wrap(buttonDrawable); DrawableCompat.setTint(buttonDrawable, color); frameLayout.setBackground(buttonDrawable); } public static Spanned getHtml(String text) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return Html.fromHtml(text, Html.FROM_HTML_MODE_COMPACT); } else { return Html.fromHtml(text); } } public static int getRandomColor() { Random rnd = new Random(); return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); } public static long getFileSize(URL url) { URLConnection conn = null; try { conn = url.openConnection(); if (conn instanceof HttpURLConnection) { ((HttpURLConnection) conn).setRequestMethod("HEAD"); } conn.getInputStream(); return conn.getContentLength(); } catch (IOException e) { Log.e(TAG, "URL-FILE_SIZE ERROR: "+e.getMessage()); e.printStackTrace(); return 0; } finally { if (conn instanceof HttpURLConnection) { ((HttpURLConnection) conn).disconnect(); } } } public static class CheckForUpdates extends AsyncTask<Void, Void, Void> { boolean isAutomatic, permissionGranted; String json; @SuppressLint("StaticFieldLeak") Activity context; String updateName; long downloadID; AsyncTask<Void, Long, Void> updateTask; public CheckForUpdates(Activity context, boolean isAutomatic) { this.context = context; this.isAutomatic = isAutomatic; Log.e(TAG, "CheckForUpdates: Okay I am here..."); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Dexter.withActivity(context) .withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) .withListener(new PermissionListener() { @Override public void onPermissionGranted(PermissionGrantedResponse response) { permissionGranted = true; } @Override public void onPermissionDenied(PermissionDeniedResponse response) { Toast.makeText(context, "Permission denied!", Toast.LENGTH_SHORT).show(); return; } @Override public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) { return; } }).check(); } else permissionGranted = true; } else permissionGranted = true; } void runInstall(Context context, String updateName) { File f = getFile(Environment.DIRECTORY_DOWNLOADS + "/" + updateName); Uri data = Uri.fromFile(f); Log.e(TAG, "runInstall: Uri of FIle: " + data.toString()); if (f.exists()) { Uri uri = getApkUri(f.getPath()); Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); intent.setData(uri); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); intent.putExtra(Intent.EXTRA_RETURN_RESULT, true); intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, context.getApplicationInfo().packageName); if (context.getPackageManager().queryIntentActivities(intent, 0) != null) {// checked on start Activity Activity act = (Activity) context; act.startActivityForResult(intent, 100); ((Activity) context).finish(); } } else Toast.makeText(context, "Update file does not exist!", Toast.LENGTH_SHORT).show(); } private Uri getApkUri(String path) { // Before N, a MODE_WORLD_READABLE file could be passed via the ACTION_INSTALL_PACKAGE // Intent. Since N, MODE_WORLD_READABLE files are forbidden, and a FileProvider is // recommended. boolean useFileProvider = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; // String tempFilename = "tmp.apk"; // byte[] buffer = new byte[16384]; int fileMode = useFileProvider ? Context.MODE_PRIVATE : Context.MODE_WORLD_READABLE; /* try (InputStream is = new FileInputStream(new File(path)); FileOutputStream fout = context.openFileOutput(tempFilename, fileMode)) { int n; while ((n = is.read(buffer)) >= 0) { fout.write(buffer, 0, n); } } catch (IOException e) { Log.i(TAG + ":getApkUri", "Failed to write temporary APK file", e); }*/ if (useFileProvider) { // File toInstall = new File(context.getFilesDir(), tempFilename); File toInstall = new File(path); return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID+".provider", toInstall); } else { return Uri.fromFile(new File(path)); } } @SuppressLint("StaticFieldLeak") ProgressBar progressBar; AlertDialog alertDialog; TextView progressText; @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); if (!permissionGranted) return; if (json == null || json.isEmpty()) return; try { JSONObject object = new JSONObject(json); String changelogHtml = object.getString("changelog"); String downloadUri = object.getString("download"); int newVer = Integer.parseInt(object.getString("newVersion") .replace(".", "")); int deprecatedVersion = Integer.parseInt(object.getString("deprecated") .replace(".", "")); updateName = "YTPlayer_v" + newVer + ".apk"; PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); int curVer = Integer.parseInt(pInfo.versionName.replace(".", "")); Log.e("VersionLOG", "NewVersion: " + newVer + ", currVersion: " + curVer); LayoutInflater inflater = LayoutInflater.from(context); if (deprecatedVersion>=curVer) { ErrorActivity.IsUpdateAvailable = true; View v = inflater.inflate(R.layout.alert_deprecated_error,null); alertDialog = new AlertDialog.Builder(context) .setView(v) .setCancelable(false) .setPositiveButton("OK",null) .setNeutralButton("Visit Website",(dialogInterface, i) -> { StartURL(context.getResources().getString(R.string.weburl),context); }) .create(); alertDialog.show(); return; } if (newVer > curVer) { ErrorActivity.IsUpdateAvailable = true; // if (true) { View v = inflater.inflate(R.layout.alert_download, null); TextView showTxt = v.findViewById(R.id.textTxt); showTxt.setText(getHtml(changelogHtml)); progressBar = v.findViewById(R.id.progressBar); progressText = v.findViewById(R.id.progressText); alertDialog = new AlertDialog.Builder(context) .setView(v) .setCancelable(false) .setPositiveButton("Download", null) .setNegativeButton("Cancel", (dialogInterface, i) -> { if (updateTask != null && updateTask.getStatus() == Status.RUNNING) { updateTask.cancel(true); } }) .create(); alertDialog.show(); alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(view -> { progressBar.setVisibility(View.VISIBLE); progressText.setVisibility(View.VISIBLE); alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setVisibility(View.GONE); updateTask = new downloadTask(downloadUri); updateTask.executeOnExecutor(THREAD_POOL_EXECUTOR); }); } else if (!isAutomatic) { Toast.makeText(context, "No update available!", Toast.LENGTH_SHORT).show(); } } catch (JSONException | PackageManager.NameNotFoundException e) { e.printStackTrace(); } } class downloadTask extends AsyncTask<Void, Long, Void> { String download_Uri; public downloadTask(String download_Uri) { this.download_Uri = download_Uri; } boolean isDownloaded = false; @Override protected void onPostExecute(Void aVoid) { // alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setVisibility(View.GONE); if (getFile(Environment.DIRECTORY_DOWNLOADS + "/" + updateName).exists()) { progressText.setVisibility(View.GONE); Toast.makeText(context, "Download complete, Click Install!", Toast.LENGTH_SHORT).show(); alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setVisibility(View.VISIBLE); alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setText("Install"); alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(view -> { alertDialog.dismiss(); runInstall(context, updateName); }); } else Toast.makeText(context, "There is a problem with update package!", Toast.LENGTH_SHORT).show(); super.onPostExecute(aVoid); } @Override protected void onProgressUpdate(Long... values) { int val = values[0].intValue(); if (val <= 100) progressBar.setProgress(val); progressText.setText((values[1] / 1000) + "/" + (values[2] / 1000)); super.onProgressUpdate(values); } @Override protected Void doInBackground(Void... voids) { File f = new File(YTutils.getFile(Environment.DIRECTORY_DOWNLOADS).getPath(), updateName); if (f.exists()) return null; PRDownloader.download(download_Uri, YTutils.getFile(Environment.DIRECTORY_DOWNLOADS).getPath(), updateName) .build() .setOnProgressListener(progress1 -> { publishProgress((progress1.currentBytes * 100 / progress1.totalBytes), progress1.currentBytes, progress1.totalBytes); }) .start(new OnDownloadListener() { @Override public void onDownloadComplete() { isDownloaded = true; Log.e(TAG, "onDownloadComplete: Completed"); } @Override public void onError(Error error) { isDownloaded = true; } }); /** Wait till download is complete... */ while (!isDownloaded) ; return null; } } @Override protected Void doInBackground(Void... voids) { if (!isInternetAvailable()) { return null; } String updateLink = context.getResources().getString(R.string.updateUri); HttpHandler handler = new HttpHandler(); json = handler.makeServiceCall(updateLink); return null; } } public static void showPurchaseDialog(Context context) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); View v = inflater.inflate(R.layout.alert_buy_premium, null); new AlertDialog.Builder(context) .setView(v).setPositiveButton("Purchase", (dialogInterface, i) -> { YTutils.openPurchaseActivity(context); }).setNegativeButton("Cancel", null) .show(); } public static void downloadDialog(Context context, MetaModel meta) { if (AppSettings.downloadCount <= 0 && AppSettings.setDownloads) { YTutils.showPurchaseDialog(context); return; } else if (AppSettings.setDownloads) AppSettings.downloadCount--; LayoutInflater inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); View v = inflater.inflate(R.layout.alert_download_filter, null); RadioButton m4aRadio = v.findViewById(R.id.radio_m4a); RadioButton v1080Radio = v.findViewById(R.id.radio_1080p); RadioButton v720pRadio = v.findViewById(R.id.radio_720p); RadioButton v480pRadio = v.findViewById(R.id.radio_480p); alertDialog = new AlertDialog.Builder(context) .setView(v) .setNegativeButton("Cancel", null) .setPositiveButton("OK", (dialogInterface, i) -> { String ext = "mp3"; if (m4aRadio.isChecked()) ext = "m4a"; else if (v1080Radio.isChecked()) ext = "1080p"; else if (v720pRadio.isChecked()) ext = "720p"; else if (v480pRadio.isChecked()) ext = "480p"; YTConfig config = new YTConfig("auto-generate", "auto-generate", ext , meta.getTitle(), meta.getAuthor(), true, meta.getImgUrl()); config.setVideoID(meta.getVideoID()); config.setTargetName(YTutils.getTargetName(config)); config.setTaskExtra("autoTask"); if (AppSettings.showAds) showAd(context); Intent serviceIntent = new Intent(context, IntentDownloadService.class); serviceIntent.putExtra("addJob", config); ContextCompat.startForegroundService(context, serviceIntent); }) .create(); alertDialog.show(); } public static void showAd(Context con) { try { InterstitialAd mInterstitialAd = new InterstitialAd(con); mInterstitialAd.setAdUnitId("ca-app-pub-1164424526503510/4801416648"); mInterstitialAd.loadAd(new AdRequest.Builder().addTestDevice("07153BA64BB64F7C3F726B71C4AE30B9").build()); mInterstitialAd.setAdListener(new AdListener() { @Override public void onAdFailedToLoad(int i) { super.onAdFailedToLoad(i); Log.e(TAG, "onAdFailedToLoad: Ad failed to load: " + i); } @Override public void onAdLoaded() { super.onAdLoaded(); mInterstitialAd.show(); } }); } catch (Exception ignored) { } } public static String getTargetName(YTConfig config) { String filename; if (config.getText().length() > 55) { filename = config.getTitle().substring(0, 55).trim(); } else { filename = config.getChannelTitle().trim() + " - " + config.getTitle().trim(); } return filename.replaceAll("[\\\\><\"|*?%:#/]", ""); } public static void showInterstitialAd(Context activity) { if (!AppSettings.showAds) return; //TODO: Change ad unit ID, Sample ca-app-pub-3940256099942544/1033173712 InterstitialAd mInterstitialAd = new InterstitialAd(activity); mInterstitialAd.setAdUnitId("ca-app-pub-1164424526503510/4801416648"); mInterstitialAd.loadAd(new AdRequest.Builder().addTestDevice("07153BA64BB64F7C3F726B71C4AE30B9").build()); mInterstitialAd.setAdListener(new AdListener() { @Override public void onAdFailedToLoad(int i) { super.onAdFailedToLoad(i); Log.e(TAG, "onAdFailedToLoad: Ad failed to load: " + i); } @Override public void onAdLoaded() { super.onAdLoaded(); mInterstitialAd.show(); } }); } public static void moveFile(File file, File dest) throws IOException { FileChannel outputChannel = null; FileChannel inputChannel = null; try { outputChannel = new FileOutputStream(dest).getChannel(); inputChannel = new FileInputStream(file).getChannel(); inputChannel.transferTo(0, inputChannel.size(), outputChannel); inputChannel.close(); file.delete(); } finally { if (inputChannel != null) inputChannel.close(); if (outputChannel != null) outputChannel.close(); } } public static String milliSecondsToTimer(long milliseconds) { String finalTimerString = ""; String secondsString = ""; // Convert total duration into time int hours = (int) (milliseconds / (1000 * 60 * 60)); int minutes = (int) (milliseconds % (1000 * 60 * 60)) / (1000 * 60); int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60) / 1000); // Add hours if there if (hours > 0) { finalTimerString = hours + ":"; } // Prepending 0 to seconds if it is one digit if (seconds < 10) { secondsString = "0" + seconds; } else { secondsString = "" + seconds; } finalTimerString = finalTimerString + minutes + ":" + secondsString; // return timer string return finalTimerString; } public static int getProgressPercentage(long currentDuration, long totalDuration) { Double percentage = (double) 0; long currentSeconds = (int) (currentDuration / 1000); long totalSeconds = (int) (totalDuration / 1000); // calculating percentage percentage = (((double) currentSeconds) / totalSeconds) * 100; // return percentage return percentage.intValue(); } public static String join(String[] arrays, char deliminator) { StringBuilder builder = new StringBuilder(); for (String a : arrays) builder.append(a).append(deliminator); return builder.toString(); } public static Bitmap drawableToBitmap(Drawable drawable) { Bitmap bitmap = null; if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; if (bitmapDrawable.getBitmap() != null) { return bitmapDrawable.getBitmap(); } } if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } public static boolean isInternetAvailable() { try { InetAddress ipAddr = InetAddress.getByName("google.com"); //You can replace it with your name return !ipAddr.equals(""); } catch (Exception e) { return false; } } public static String getDuration(long number) { String returnstring = ""; long no = number / 1000; long mins = no / 60; long seconds = no % 60; if (mins > 9) returnstring += mins; else returnstring += "0" + mins; if (seconds > 9) returnstring += ":" + seconds; else returnstring += ":0" + seconds; return returnstring; } public static int getAvgBitRate(int bitrate) { return (bitrate / 1000); } public static void StartURLIntent(String url, Context context) { Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); context.startActivity(i); } public static void parseDataForPlaylist(Context context, String path) { parseDataForPlaylist(context, path, false,false); } public static void parseDataForPlaylist(Context context, String path, boolean playlist_export) { parseDataForPlaylist(context, path, playlist_export,true); } static AlertDialog alertDialog1; public static void parseDataForPlaylist(Context context, String path, boolean playlist_export,boolean export) { if (path != null) { String[] items_bef = Objects.requireNonNull(YTutils.readContent(context, path)).split("\n|\r"); if (items_bef.length > 0) { String[] items; if (!playlist_export) { items = new String[items_bef.length-1]; if (!items_bef[0].startsWith(context.getResources().getString(R.string.header_playlist))) { Toast.makeText(context, "Invalid playlist file", Toast.LENGTH_SHORT).show(); return; } System.arraycopy(items_bef, 1, items, 0, items_bef.length - 1); }else { List<String> list = Arrays.asList(items_bef); Collections.reverse(list); items = (String[]) list.toArray(); //items = items_bef; } ArrayList<ImportModel> models = new ArrayList<>(); for (String line : items) { String[] childs = line.split(","); int seconds = 0; for (int i = 2; i < childs.length; i++) { String playlist_item = childs[i]; seconds += Integer.parseInt(playlist_item.split("\\|")[1]); } models.add(new ImportModel( childs[1], +childs.length - 2, seconds )); } LayoutInflater inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.alert_import_playlist, null); RecyclerView recyclerView = view.findViewById(R.id.recyclerView); ImportAdapter adapter = new ImportAdapter(context, models, items); adapter.setListener((model, position) -> { model.setChecked(!model.isChecked()); adapter.notifyItemChanged(position); }); recyclerView.setLayoutManager(new LinearLayoutManager(context)); recyclerView.setAdapter(adapter); String text = "Import"; if (export) text = "Export"; ((TextView) view.findViewById(R.id.titleTxt)).setText(text); alertDialog = new AlertDialog.Builder(context) .setView(view) .setNegativeButton("Cancel", null) .setPositiveButton(text, (dialogInterface, i) -> { }) .create(); alertDialog.show(); alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(view2 -> { boolean atleast_one_check=false; if (export) { for (ImportModel importModel:models) { if (importModel.isChecked()) { atleast_one_check=true; break; } } if (!atleast_one_check) { Toast.makeText(context, "Kindly make a selection", Toast.LENGTH_SHORT).show(); return; } View view1 = inflater.inflate(R.layout.alert_export_name,null); EditText editText = view1.findViewById(R.id.editText); alertDialog1 = new AlertDialog.Builder(context) .setView(view1) .setPositiveButton("Export",(dialogInterface, i) -> { }) .setNegativeButton("Cancel",null) .create(); alertDialog1.show(); alertDialog1.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(view3 -> { if (editText.getText().toString().isEmpty()) { Toast.makeText(context, "Playlist name cannot be empty", Toast.LENGTH_SHORT).show(); return; } StringBuilder builder = new StringBuilder(); builder.append(context.getResources().getString(R.string.header_playlist)).append("\n"); for (int i=0;i<models.size();i++) { if (models.get(i).isChecked()) { builder.append(items[i]).append("\n"); } } String path1 = getFile("Playlists/"+editText.getText().toString()+".txt").getPath(); YTutils.writeContent(context,path1,builder.toString()); Toast.makeText(context, "Saved to "+path1, Toast.LENGTH_SHORT).show(); alertDialog1.dismiss(); alertDialog.dismiss(); }); } else { int added = 0, replaced = 0; String playlist_csv = YTutils.readContent(context, "playlist.csv"); if (playlist_csv == null) playlist_csv = ""; StringBuilder playlistBuilder = new StringBuilder(playlist_csv); for (int c = 0; c < models.size(); c++) { if (models.get(c).isChecked()) { atleast_one_check = true; if (!playlist_csv.contains("," + models.get(c).getTitle() + ",")) { playlistBuilder.append(items[c]).append("\n"); added++; } else { String[] playlist_items = playlistBuilder.toString().split("\n|\r"); for (int k = 0; k < playlist_items.length; k++) { if (playlist_items[k].contains("," + models.get(c).getTitle() + ",")) { playlist_items[k] = items[c]; } } playlistBuilder = new StringBuilder(YTutils.join(playlist_items, '\n')); replaced++; } } } if (atleast_one_check) { YTutils.writeContent(context, "playlist.csv", playlistBuilder.toString()); Toast.makeText(context, added + " new playlist added, " + replaced + " replaced!", Toast.LENGTH_SHORT).show(); alertDialog.dismiss(); } else Toast.makeText(context, "Kindly Make a selection", Toast.LENGTH_SHORT).show(); } }); } } else Toast.makeText(context, "Error: Failed to parse playlist!", Toast.LENGTH_SHORT).show(); } public static String[] getExternalStorageDirectories(Context context) { List<String> results = new ArrayList<>(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //Method 1 for KitKat & above File[] externalDirs = context.getExternalFilesDirs(null); String internalRoot = Environment.getExternalStorageDirectory().getAbsolutePath().toLowerCase(); for (File file : externalDirs) { if (file == null) //solved NPE on some Lollipop devices continue; String path = file.getPath().split("/Android")[0]; if (path.toLowerCase().startsWith(internalRoot)) continue; boolean addPath = false; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { addPath = Environment.isExternalStorageRemovable(file); } else { addPath = Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(file)); } if (addPath) { results.add(path); } } } if (results.isEmpty()) { //Method 2 for all versions // better variation of: http://stackoverflow.com/a/40123073/5002496 String output = ""; try { final Process process = new ProcessBuilder().command("mount | grep /dev/block/vold") .redirectErrorStream(true).start(); process.waitFor(); final InputStream is = process.getInputStream(); final byte[] buffer = new byte[1024]; while (is.read(buffer) != -1) { output = output + new String(buffer); } is.close(); } catch (final Exception e) { e.printStackTrace(); } if (!output.trim().isEmpty()) { String devicePoints[] = output.split("\n"); for (String voldPoint : devicePoints) { results.add(voldPoint.split(" ")[2]); } } } //Below few lines is to remove paths which may not be external memory card, like OTG (feel free to comment them out) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { for (int i = 0; i < results.size(); i++) { if (!results.get(i).toLowerCase().matches(".*[0-9a-f]{4}[-][0-9a-f]{4}")) { Log.d("YTUtilsTAG", results.get(i) + " might not be extSDcard"); results.remove(i--); } } } else { for (int i = 0; i < results.size(); i++) { if (!results.get(i).toLowerCase().contains("ext") && !results.get(i).toLowerCase().contains("sdcard")) { Log.d("YTUtilsTAG", results.get(i) + " might not be extSDcard"); results.remove(i--); } } } String[] storageDirectories = new String[results.size()]; for (int i = 0; i < results.size(); ++i) storageDirectories[i] = results.get(i); return storageDirectories; } public static String getTimeString(Long time) { if (time > 60) return (time / 60) + " mins"; else if (time == 60) return "1 min"; else { return time + " secs"; } } /** * Get a file path from a Uri. This will get the the path for Storage Access * Framework Documents, as well as the _data field for the MediaStore and * other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @author paulburke */ public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } else { // Trying to handle non-primary volumes String[] volumes = getExternalStorageDirectories(context); if (volumes.length > 0) return getExternalStorageDirectories(context)[0] + "/" + split[1]; } // TODO handle non-primary volumes } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } final String selection = "_id=?"; final String[] selectionArgs = new String[]{ split[1] }; return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @param selection (Optional) Filter used in the query. * @param selectionArgs (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */ public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = { column }; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { final int column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_index); } } finally { if (cursor != null) cursor.close(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */ public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } public static class ContentProvider { public static String getFilePathFromURI(Context context, Uri contentUri) { //copy file and send new file path String fileName = getFileName(contentUri); if (!TextUtils.isEmpty(fileName)) { File copyFile = new File(context.getCacheDir() + File.separator + fileName); copy(context, contentUri, copyFile); return copyFile.getAbsolutePath(); } return null; } private static String getFileName(Uri uri) { if (uri == null) return null; String fileName = null; String path = uri.getPath(); int cut = path.lastIndexOf('/'); if (cut != -1) { fileName = path.substring(cut + 1); } return fileName; } private static void copy(Context context, Uri srcUri, File dstFile) { try { InputStream inputStream = context.getContentResolver().openInputStream(srcUri); if (inputStream == null) return; OutputStream outputStream = new FileOutputStream(dstFile); IOUtils.copyStream(inputStream, outputStream); inputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /* * * Zips a file at a location and places the resulting zip file at the toLocation * Example: zipFileAtPath("downloads/myfolder", "downloads/myFolder.zip"); */ public static boolean zipFileAtPath(String sourcePath, String toLocation) { final int BUFFER = 2048; File sourceFile = new File(sourcePath); try { BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream(toLocation); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream( dest)); if (sourceFile.isDirectory()) { zipSubFolder(out, sourceFile, sourceFile.getParent().length()); } else { byte data[] = new byte[BUFFER]; FileInputStream fi = new FileInputStream(sourcePath); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath)); entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } } out.close(); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /* * * Zips a subfolder * */ private static void zipSubFolder(ZipOutputStream out, File folder, int basePathLength) throws IOException { final int BUFFER = 2048; File[] fileList = folder.listFiles(); BufferedInputStream origin = null; for (File file : fileList) { if (file.isDirectory()) { zipSubFolder(out, file, basePathLength); } else { byte data[] = new byte[BUFFER]; String unmodifiedFilePath = file.getPath(); String relativePath = unmodifiedFilePath .substring(basePathLength); FileInputStream fi = new FileInputStream(unmodifiedFilePath); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(relativePath); entry.setTime(file.lastModified()); // to keep modification time after unzipping out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } origin.close(); } } } /* * gets the last path component * * Example: getLastPathComponent("downloads/example/fileToZip"); * Result: "fileToZip" */ public static String getLastPathComponent(String filePath) { String[] segments = filePath.split("/"); if (segments.length == 0) return ""; String lastPathComponent = segments[segments.length - 1]; return lastPathComponent; } public static boolean extractZip(String zipFile, String tooutPath) { InputStream is; ZipInputStream zis; try { String filename; is = new FileInputStream(zipFile); zis = new ZipInputStream(new BufferedInputStream(is)); ZipEntry ze; byte[] buffer = new byte[1024]; int count; while ((ze = zis.getNextEntry()) != null) { filename = ze.getName(); // Need to create directories if not exists, or // it will generate an Exception... if (ze.isDirectory()) { File fmd = new File(tooutPath + "/" + filename); fmd.mkdirs(); continue; } FileOutputStream fout = new FileOutputStream(tooutPath + "/" + filename); while ((count = zis.read(buffer)) != -1) { fout.write(buffer, 0, count); } fout.close(); zis.closeEntry(); } zis.close(); } catch (IOException e) { e.printStackTrace(); return false; } return true; } }