fixed api issues and other stuff

Due to high app usage my personal youtube api key was throttled. I removed the built-in api key for default yt-dlp requests. slower but usable to everyone. You can add your own youtube api key in the setttings for faster responses
fixed downloaded items other than youtube not having proper download links
fixed app crashing when pressing download all button
pull/1/head
Denis Çerri 4 years ago
parent f735314cc0
commit dfd560204e
No known key found for this signature in database
GPG Key ID: 3F50F14A8E7F7A13

@ -320,7 +320,7 @@
<PersistentState>
<option name="values">
<map>
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/videocam_off/baseline_videocam_off_24.xml" />
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/vpn_key/baseline_vpn_key_24.xml" />
</map>
</option>
</PersistentState>
@ -330,9 +330,8 @@
</option>
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="color" value="00a6ff" />
<entry key="outputName" value="ic_launcher_foreground" />
<entry key="outputName" value="ic_key" />
<entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
</map>
</option>

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="192.168.1.131:43815" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2022-09-27T10:56:58.187849900Z" />
</component>
</project>

@ -49,6 +49,7 @@
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_home.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_image.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_info.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_key.xml" value="0.1965" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_launcher_background.xml" value="0.2395" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_launcher_foreground.xml" value="0.1965" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_lines.xml" value="0.109" />

@ -49,9 +49,6 @@
android:name=".DownloaderService"
android:enabled="true"
android:exported="false" />
<meta-data
android:name="ytAPIkey"
android:value="${ytAPI}" />
</application>
</manifest>

@ -10,7 +10,7 @@ import java.util.ArrayList;
public class DBManager extends SQLiteOpenHelper {
public static final String db_name = "ytdlnis_db";
public static final int db_version = 6;
public static final int db_version = 7;
public static final String results_table_name = "results";
public static final String history_table_name = "history";
public static final String id = "id";
@ -26,6 +26,7 @@ public class DBManager extends SQLiteOpenHelper {
public static final String time = "time";
public static final String isPlaylistItem = "isPlaylistItem";
public static final String website = "website";
public static final String downloadPath = "downloadPath";
public DBManager(Context context){
@ -51,14 +52,15 @@ public class DBManager extends SQLiteOpenHelper {
query = "CREATE TABLE " + history_table_name + " ("
+ id + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ videoId + " TEXT,"
+ url + " TEXT,"
+ title + " TEXT,"
+ author + " TEXT,"
+ duration + " TEXT,"
+ thumb + " TEXT,"
+ type + " TEXT,"
+ time + " TEXT,"
+ isPlaylistItem + " INTENGER)";
+ downloadPath + " TEXT,"
+ website + " TEXT)";
sqLiteDatabase.execSQL(query);
}
@ -96,7 +98,7 @@ public class DBManager extends SQLiteOpenHelper {
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVer, int newVer) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + results_table_name);
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + history_table_name);
onCreate(sqLiteDatabase);
@ -146,7 +148,8 @@ public class DBManager extends SQLiteOpenHelper {
cursor.getString(5),
cursor.getString(6),
cursor.getString(7),
cursor.getInt(8)));
cursor.getString(8),
cursor.getString(9)));
} while (cursor.moveToNext());
}
@ -181,13 +184,15 @@ public class DBManager extends SQLiteOpenHelper {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(videoId, v.getVideoId());
values.put(url, v.getURL());
values.put(title, v.getTitle());
values.put(author, v.getAuthor());
values.put(duration, v.getDuration());
values.put(thumb, v.getThumb());
values.put(type, v.getDownloadedType());
values.put(time, v.getDownloadedTime());
values.put(downloadPath, v.getDownloadPath());
values.put(website, v.getWebsite());
db.insert(history_table_name, null, values);
db.close();
@ -209,10 +214,10 @@ public class DBManager extends SQLiteOpenHelper {
db.update(results_table_name, values, "videoId = ?", new String[]{id});
}
public int checkDownloaded(String id, String downloadType){
public int checkDownloaded(String url, String downloadType){
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + history_table_name + " WHERE videoId='" +
id + "' AND type='"+downloadType + "' LIMIT 1", null);
Cursor cursor = db.rawQuery("SELECT * FROM " + history_table_name + " WHERE url='" +
url + "' AND type='"+downloadType + "' LIMIT 1", null);
if(cursor.moveToFirst()){
return 1;

@ -16,6 +16,7 @@ public class Video implements Parcelable {
private int downloadedVideo;
private String downloadedTime;
private int isPlaylistItem;
private String downloadPath;
private String website;
// RESULTS OBJECT
@ -34,17 +35,18 @@ public class Video implements Parcelable {
}
//HISTORY OBJECT
public Video(int id, String videoId, String title, String author, String duration, String thumb,
String downloadedType, String downloadedTime, int isPlaylistItem) {
public Video(int id, String url, String title, String author, String duration, String thumb,
String downloadedType, String downloadedTime, String downloadPath, String website) {
this.id = id;
this.videoId = videoId;
this.url = url;
this.title = title;
this.author = author;
this.duration = duration;
this.thumb = thumb;
this.downloadedType = downloadedType;
this.downloadedTime = downloadedTime;
this.isPlaylistItem = isPlaylistItem;
this.downloadPath = downloadPath;
this.website = website;
}
@ -61,6 +63,7 @@ public class Video implements Parcelable {
downloadedVideo = in.readInt();
downloadedTime = in.readString();
isPlaylistItem = in.readInt();
downloadPath = in.readString();
website = in.readString();
}
@ -148,6 +151,54 @@ public class Video implements Parcelable {
public void setWebsite(String site){ this.website = site; }
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public void setAuthor(String author) {
this.author = author;
}
public void setDuration(String duration) {
this.duration = duration;
}
public void setThumb(String thumb) {
this.thumb = thumb;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getDownloadedAudio() {
return downloadedAudio;
}
public void setDownloadedAudio(int downloadedAudio) {
this.downloadedAudio = downloadedAudio;
}
public int getDownloadedVideo() {
return downloadedVideo;
}
public void setDownloadedVideo(int downloadedVideo) {
this.downloadedVideo = downloadedVideo;
}
public String getDownloadPath() {
return downloadPath;
}
public void setDownloadPath(String downloadPath) {
this.downloadPath = downloadPath;
}
@Override
public int describeContents() {
return 0;
@ -167,6 +218,7 @@ public class Video implements Parcelable {
parcel.writeInt(downloadedVideo);
parcel.writeString(downloadedTime);
parcel.writeInt(isPlaylistItem);
parcel.writeString(downloadPath);
parcel.writeString(website);
}

@ -44,6 +44,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
private View fragmentView;
private DBManager dbManager;
Context context;
Context fragmentContext;
private LayoutInflater layoutinflater;
private ShimmerFrameLayout shimmerCards;
private MaterialToolbar topAppBar;
@ -52,10 +53,8 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
private BottomSheetDialog bottomSheet;
private Handler uiHandler;
private RelativeLayout no_results;
private ArrayList<Video> historyObjects;
private static final String TAG = "HistoryFragment";
private static final String youtubeVideoURL = "https://www.youtube.com/watch?v=";
public HistoryFragment() {
}
@ -79,7 +78,8 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
Bundle savedInstanceState) {
fragmentView = inflater.inflate(R.layout.fragment_history, container, false);
context = fragmentView.getContext();
context = fragmentView.getContext().getApplicationContext();
fragmentContext = fragmentView.getContext();
layoutinflater = LayoutInflater.from(context);
shimmerCards = fragmentView.findViewById(R.id.shimmer_history_framelayout);
topAppBar = fragmentView.findViewById(R.id.history_toolbar);
@ -181,29 +181,27 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
topAppBar.setOnClickListener(view -> scrollToTop());
topAppBar.setOnMenuItemClickListener((MenuItem m) -> {
switch (m.getItemId()){
case R.id.delete_history:
if(historyObjects.size() == 0){
Toast.makeText(context, "History is Empty!", Toast.LENGTH_SHORT).show();
return true;
}
MaterialAlertDialogBuilder delete_dialog = new MaterialAlertDialogBuilder(context);
delete_dialog.setTitle(getString(R.string.confirm_delete_history));
delete_dialog.setMessage(getString(R.string.confirm_delete_history_desc));
delete_dialog.setNegativeButton(getString(R.string.cancel), (dialogInterface, i) -> {
dialogInterface.cancel();
});
delete_dialog.setPositiveButton(getString(R.string.ok), (dialogInterface, i) -> {
dbManager.clearHistory();
historyRecyclerViewAdapter.clear();
no_results.setVisibility(View.VISIBLE);
});
delete_dialog.show();
return true;
case R.id.refresh_history:
initCards();
int itemID = m.getItemId();
if(itemID == R.id.delete_history){
if(historyObjects.size() == 0){
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show();
return true;
}
MaterialAlertDialogBuilder delete_dialog = new MaterialAlertDialogBuilder(context);
delete_dialog.setTitle(getString(R.string.confirm_delete_history));
delete_dialog.setMessage(getString(R.string.confirm_delete_history_desc));
delete_dialog.setNegativeButton(getString(R.string.cancel), (dialogInterface, i) -> {
dialogInterface.cancel();
});
delete_dialog.setPositiveButton(getString(R.string.ok), (dialogInterface, i) -> {
dbManager.clearHistory();
historyRecyclerViewAdapter.clear();
no_results.setVisibility(View.VISIBLE);
});
delete_dialog.show();
}else if(itemID == R.id.refresh_history){
initCards();
}
return true;
});
@ -213,16 +211,12 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
@Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.bottomsheet_remove_button:
removeHistoryItem((Integer) v.getTag());
break;
case R.id.bottom_sheet_link:
copyLinkToClipBoard((Integer) v.getTag());
break;
case R.id.bottomsheet_open_link_button:
openLinkIntent((Integer) v.getTag());
break;
if(id == R.id.bottomsheet_remove_button){
removeHistoryItem((Integer) v.getTag());
}else if(id == R.id.bottom_sheet_link){
copyLinkToClipBoard((Integer) v.getTag());
}else if(id == R.id.bottomsheet_open_link_button){
openLinkIntent((Integer) v.getTag());
}
}
@ -232,7 +226,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
Video v = historyObjects.get(position);
MaterialAlertDialogBuilder delete_dialog = new MaterialAlertDialogBuilder(context);
delete_dialog.setTitle(getString(R.string.confirm_delete_history));
delete_dialog.setMessage("You are going to delete \""+v.getTitle()+"\"!");
delete_dialog.setMessage(getString(R.string.you_are_going_to_delete) + " \""+v.getTitle()+"\"!");
delete_dialog.setNegativeButton(getString(R.string.cancel), (dialogInterface, i) -> {
dialogInterface.cancel();
});
@ -250,16 +244,16 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
}
private void copyLinkToClipBoard(int position){
String url = youtubeVideoURL + historyObjects.get(position).getVideoId();
String url = historyObjects.get(position).getURL();
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Youtube URL", url);
ClipData clip = ClipData.newPlainText(getString(R.string.youtube_url), url);
clipboard.setPrimaryClip(clip);
if(bottomSheet != null) bottomSheet.hide();
Toast.makeText(context, "Link copied to clipboard", Toast.LENGTH_SHORT).show();
Toast.makeText(context, getString(R.string.link_copied_to_clipboard), Toast.LENGTH_SHORT).show();
}
private void openLinkIntent(int position){
String url = youtubeVideoURL + historyObjects.get(position).getVideoId();
String url =historyObjects.get(position).getURL();
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
if(bottomSheet != null) bottomSheet.hide();
@ -268,7 +262,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
@Override
public void onCardClick(int position) {
bottomSheet = new BottomSheetDialog(context);
bottomSheet = new BottomSheetDialog(fragmentContext);
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE);
bottomSheet.setContentView(R.layout.history_bottom_sheet);
Video video = historyObjects.get(position);
@ -280,7 +274,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
author.setText(video.getAuthor());
Button link = bottomSheet.findViewById(R.id.bottom_sheet_link);
String url = youtubeVideoURL+video.getVideoId();
String url = video.getURL();
link.setText(url);
link.setTag(position);
link.setOnClickListener(this);

@ -15,7 +15,6 @@ import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.widget.Button;
import android.widget.ProgressBar;
@ -29,7 +28,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.deniscerri.ytdlnis.MainActivity;
import com.deniscerri.ytdlnis.R;
import com.deniscerri.ytdlnis.adapter.HomeRecyclerViewAdapter;
import com.deniscerri.ytdlnis.api.YoutubeAPIManager;
import com.deniscerri.ytdlnis.util.InfoUtil;
import com.deniscerri.ytdlnis.database.DBManager;
import com.deniscerri.ytdlnis.database.Video;
import com.deniscerri.ytdlnis.service.DownloadInfo;
@ -50,7 +49,6 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -68,6 +66,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
private CoordinatorLayout homeFabs;
private BottomSheetDialog bottomSheet;
Context context;
Context fragmentContext;
Activity activity;
private MaterialToolbar topAppBar;
@ -76,7 +75,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
private ArrayList<Video> resultObjects;
public ArrayList<Video> selectedObjects;
private DBManager dbManager;
private YoutubeAPIManager youtubeAPIManager;
private InfoUtil infoUtil;
private ArrayList<Video> downloadQueue;
MainActivity mainActivity;
@ -147,9 +146,6 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
}
}
addToHistory(item, new Date());
updateDownloadStatusOnResult(item, type);
downloading = false;
topAppBar.getMenu().findItem(R.id.cancel_download).setVisible(false);
@ -166,6 +162,8 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
for (int i = 0; i < files.size(); i++) paths[i] = files.get(i).getAbsolutePath();
MediaScannerConnection.scanFile(context, paths, null, null);
addToHistory(item, new Date(), paths);
updateDownloadStatusOnResult(item, type);
mainActivity.updateHistoryFragment();
}catch(Exception ignored){}
}
@ -200,6 +198,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
// Inflate the layout for this fragment
fragmentView = inflater.inflate(R.layout.fragment_home, container, false);
context = fragmentView.getContext().getApplicationContext();
fragmentContext = fragmentView.getContext();
activity = getActivity();
mainActivity = (MainActivity) activity;
@ -212,8 +211,6 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
homeRecyclerViewAdapter = new HomeRecyclerViewAdapter(resultObjects, this, activity);
recyclerView.setAdapter(homeRecyclerViewAdapter);
youtubeAPIManager = new YoutubeAPIManager(context);
initMenu();
if (inputQuery != null) {
@ -253,10 +250,10 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
Handler uiHandler = new Handler(Looper.getMainLooper());
dbManager = new DBManager(context);
resultObjects = dbManager.getResults();
if (resultObjects.size() == 0) {
try {
resultObjects = youtubeAPIManager.getTrending(context);
infoUtil = new InfoUtil(context);
resultObjects = infoUtil.getTrending(context);
} catch (Exception e) {
Log.e(TAG, e.toString());
}
@ -372,8 +369,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
shimmerCards.startShimmer();
shimmerCards.setVisibility(View.VISIBLE);
homeRecyclerViewAdapter.clear();
Log.e(TAG, String.valueOf(homeRecyclerViewAdapter.getItemCount()));
infoUtil = new InfoUtil(context);
dbManager = new DBManager(context);
scrollToTop();
@ -405,7 +401,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
@Override
public void run() {
try {
resultObjects = youtubeAPIManager.search(query);
resultObjects = infoUtil.search(query);
} catch (Exception e) {
Log.e(TAG, e.toString());
}
@ -445,7 +441,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
public void run() {
try {
resultObjects.clear();
resultObjects.add(youtubeAPIManager.getVideo(query));
resultObjects.add(infoUtil.getVideo(query));
} catch (Exception e) {
Log.e(TAG, e.toString());
}
@ -480,7 +476,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
resultObjects.clear();
homeRecyclerViewAdapter.setVideoList(new ArrayList<>(), true);
do {
YoutubeAPIManager.PlaylistTuple tmp = youtubeAPIManager.getPlaylist(query, nextPageToken);
InfoUtil.PlaylistTuple tmp = infoUtil.getPlaylist(query, nextPageToken);
ArrayList<Video> tmp_vids = tmp.getVideos();
String tmp_token = tmp.getNextPageToken();
resultObjects.addAll(tmp_vids);
@ -520,9 +516,9 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
public void run() {
try {
resultObjects.clear();
Video video = youtubeAPIManager.getFromYTDL(query);
ArrayList<Video> video = infoUtil.getFromYTDL(query);
if (video != null) {
resultObjects.add(video);
resultObjects.addAll(video);
dbManager.clearResults();
dbManager.addToResults(resultObjects);
}
@ -591,7 +587,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
}
public void addToHistory(Video video, Date date) {
public void addToHistory(Video video, Date date, String[] paths) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int day = cal.get(Calendar.DAY_OF_MONTH);
@ -602,10 +598,18 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
String time = formatter.format(date);
String downloadedTime = day + " " + month + " " + year + " " + time;
String path = "";
try{
path = paths[0];
}catch(Exception e){
e.printStackTrace();
}
if (video != null) {
dbManager = new DBManager(context);
try {
video.setDownloadedTime(downloadedTime);
video.setDownloadPath(path);
dbManager.addToHistory(video);
} catch (Exception ignored) {
}
@ -682,7 +686,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
selectedObjects = new ArrayList<>();
downloadFabs.setVisibility(View.GONE);
bottomSheet = new BottomSheetDialog(context);
bottomSheet = new BottomSheetDialog(fragmentContext);
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE);
bottomSheet.setContentView(R.layout.home_download_all_bottom_sheet);

@ -29,6 +29,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
Preference videoPath;
Preference commandPath;
EditTextPreference apiKey;
SeekBarPreference concurrentFragments;
EditTextPreference limitRate;
SwitchPreferenceCompat aria2;
@ -70,6 +71,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
videoPath = findPreference("video_path");
commandPath = findPreference("command_path");
apiKey = findPreference("api_key");
concurrentFragments = findPreference("concurrent_fragments");
limitRate = findPreference("limit_rate");
aria2 = findPreference("aria2");
@ -96,6 +98,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
editor.putString("command_path", getString(R.string.command_path));
}
editor.putString("api_key", apiKey.getText());
editor.putInt("concurrent_fragments", concurrentFragments.getValue());
editor.putString("limit_rate", limitRate.getText());
editor.putBoolean("aria2", aria2.isChecked());
@ -136,6 +139,12 @@ public class SettingsFragment extends PreferenceFragmentCompat {
return true;
});
apiKey.setOnPreferenceChangeListener((preference, newValue) -> {
editor.putString("api_key", String.valueOf(newValue));
editor.apply();
return true;
});
concurrentFragments.setOnPreferenceChangeListener((preference, newValue) -> {
int value = Integer.parseInt(String.valueOf(newValue));
editor.putInt("concurrent_fragments", value);

@ -1,8 +1,9 @@
package com.deniscerri.ytdlnis.api;
package com.deniscerri.ytdlnis.util;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.text.Html;
import android.util.Log;
import android.widget.Toast;
@ -12,8 +13,6 @@ import com.deniscerri.ytdlnis.database.Video;
import com.yausername.youtubedl_android.YoutubeDL;
import com.yausername.youtubedl_android.YoutubeDLRequest;
import com.yausername.youtubedl_android.YoutubeDLResponse;
import com.yausername.youtubedl_android.mapper.VideoInfo;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -24,19 +23,18 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Locale;
public class YoutubeAPIManager {
public class InfoUtil {
private static final String TAG = "API MANAGER";
private static String countryCODE = "US";
private ArrayList<Video> videos;
private String key;
private DBManager dbManager;
private YoutubeDLRequest youtubeDLRequest;
public YoutubeAPIManager(Context context) {
public InfoUtil(Context context) {
@Nullable ApplicationInfo applicationInfo;
try{
applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
key = applicationInfo.metaData.getString("ytAPIkey");
SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
key = sharedPreferences.getString("api_key", "");
dbManager = new DBManager(context);
Thread thread = new Thread(() -> {
@ -57,6 +55,8 @@ public class YoutubeAPIManager {
}
public ArrayList<Video> search(String query) throws JSONException{
if (key.isEmpty()) return getFromYTDL(query);
videos = new ArrayList<>();
//short data
JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/search?part=snippet&q="+query+"&maxResults=25&regionCode="+countryCODE+"&key="+key);
@ -104,6 +104,7 @@ public class YoutubeAPIManager {
}
public PlaylistTuple getPlaylist(String id, String nextPageToken) throws JSONException{
if (key.isEmpty()) return new PlaylistTuple("", getFromYTDL("https://www.youtube.com/playlist?list="+id));
videos = new ArrayList<>();
String url = "https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet&pageToken="+nextPageToken+"&maxResults=50&regionCode="+countryCODE+"&playlistId="+id+"&key="+key;
@ -150,6 +151,8 @@ public class YoutubeAPIManager {
public Video getVideo(String id) throws JSONException {
if (key.isEmpty()) return getFromYTDL("https://www.youtube.com/watch?v="+id).get(0);
//short data
JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id="+id+"&key="+key);
String duration = res.getJSONArray("items").getJSONObject(0).getJSONObject("contentDetails").getString("duration");
@ -178,10 +181,9 @@ public class YoutubeAPIManager {
String duration = obj.getString("duration");
String thumb = obj.getString("thumb");
int downloadedAudio = dbManager.checkDownloaded(id, "audio");
int downloadedVideo = dbManager.checkDownloaded(id, "video");
String url = "https://www.youtube.com/watch?v=" + id;
int downloadedAudio = dbManager.checkDownloaded(url, "audio");
int downloadedVideo = dbManager.checkDownloaded(url, "video");
int isPLaylist = 0;
video = new Video(id, url, title, author, duration, thumb, downloadedAudio, downloadedVideo, isPLaylist, "youtube");
@ -257,33 +259,74 @@ public class YoutubeAPIManager {
return o;
}
public Video getFromYTDL(String query){
Video video = null;
public ArrayList<Video> getFromYTDL(String query){
videos = new ArrayList<>();
try {
VideoInfo streamInfo = YoutubeDL.getInstance().getInfo(query);
String id = streamInfo.getId();
video = new Video(
id,
streamInfo.getUrl(),
streamInfo.getTitle(),
streamInfo.getUploader(),
formatIntegerDuration(streamInfo.getDuration()),
streamInfo.getThumbnail(),
dbManager.checkDownloaded(id, "audio"),
dbManager.checkDownloaded(id, "video"),
0,
streamInfo.getWebpageUrlBasename()
);
YoutubeDLRequest request = new YoutubeDLRequest(query);
request.addOption("--flat-playlist");
request.addOption("-J");
request.addOption("--skip-download");
if (!query.contains("http")) request.addOption("--default-search", "ytsearch25");
YoutubeDLResponse youtubeDLResponse = YoutubeDL.getInstance().execute(request);
JSONObject jsonObject = new JSONObject(youtubeDLResponse.getOut());
if(!jsonObject.has("entries")){
String url = jsonObject.getString("webpage_url");
videos.add(new Video(
jsonObject.getString("id"),
url,
jsonObject.getString("title"),
jsonObject.getString("uploader"),
formatIntegerDuration(jsonObject.getInt("duration")),
jsonObject.getString("thumbnail"),
dbManager.checkDownloaded(url, "audio"),
dbManager.checkDownloaded(url, "video"),
0,
jsonObject.getString("extractor"))
);
}else{
JSONArray jsonArray = jsonObject.getJSONArray("entries");
for (int i = 0; i < jsonArray.length(); i++){
jsonObject = jsonArray.getJSONObject(i);
String url = jsonObject.getString("url");
String thumb = "";
if (jsonObject.has("thumbnail")){
thumb = jsonObject.getString("thumbnail");
}else {
JSONArray thumbs = jsonObject.getJSONArray("thumbnails");
thumb = thumbs.getJSONObject(thumbs.length()-1).getString("url");
}
String website = "";
if (jsonObject.has("ie_key")) website = jsonObject.getString("ie_key");
else website = jsonObject.getString("extractor");
videos.add(new Video(
jsonObject.getString("id"),
url,
jsonObject.getString("title"),
jsonObject.getString("uploader"),
formatIntegerDuration(jsonObject.getInt("duration")),
thumb,
dbManager.checkDownloaded(url, "audio"),
dbManager.checkDownloaded(url, "video"),
0,
website)
);
}
}
}catch(Exception e){
e.printStackTrace();
}
return video;
return videos;
}
public ArrayList<Video> getTrending(Context context) throws JSONException{
if (key.isEmpty()) return new ArrayList<>();
videos = new ArrayList<>();
String url = "https://www.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&videoCategoryId=10&regionCode="+countryCODE+"&maxResults=25&key="+key;
@ -371,12 +414,13 @@ public class YoutubeAPIManager {
}
public String formatIntegerDuration(int dur){
String format = String.format(Locale.getDefault(), "%02d:%02d:%02d", (dur/3600), ((dur % 3600)/60), (dur % 60));
// 00:00:00
if (dur < 600) format = format.substring(4);
else if (dur < 3600) format = format.substring(3);
else if (dur < 36000) format = format.substring(1);
int hours = dur / 10000;
int minutes = (dur % 10000) / 100;
int seconds = dur % 100;
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", hours, minutes, seconds);
return format;
}
// public ArrayList<String> getSearchHints(String query){

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M12.65,10C11.83,7.67 9.61,6 7,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6c2.61,0 4.83,-1.67 5.65,-4H17v4h4v-4h2v-4H12.65zM7,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
</vector>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:tools="http://schemas.android.com/tools"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
@ -148,5 +148,4 @@
<include layout="@layout/home_download_all_bottom_sheet"
android:visibility="gone" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/home_download_all_bottom_sheet"
<FrameLayout android:id="@+id/history_element_bottom_sheet"
style="@style/Widget.Material3.BottomSheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -10,7 +10,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:orientation="vertical"
>
<LinearLayout
android:layout_width="wrap_content"
@ -41,14 +42,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal">
android:orientation="horizontal"
android:baselineAligned="false">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/first_textinput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="45"
android:layout_marginLeft="30dp"
android:layout_marginStart="30dp"
app:errorEnabled="true"
android:hint="@string/first"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
@ -89,7 +91,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:gravity="right"
android:gravity="end"
android:layout_margin="20dp"
android:orientation="horizontal">
@ -98,7 +100,7 @@
android:id="@+id/bottomsheet_audio_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_music"
android:text="@string/audio" />

@ -93,4 +93,10 @@
<string name="command_download_notification_channel_name">Command Downloads</string>
<string name="command_download_notification_channel_description">Notification that shows the download progress of a yt-dlp command</string>
<string name="items_left">item(s) left</string>
<string name="history_is_empty">History is Empty!</string>
<string name="you_are_going_to_delete">You are going to delete</string>
<string name="youtube_url">Youtube URL</string>
<string name="link_copied_to_clipboard">Link copied to clipboard</string>
<string name="api_key">YouTube API Key</string>
<string name="api_key_summary">Use an api key to get faster results from YouTube</string>
</resources>

@ -23,6 +23,13 @@
</PreferenceCategory>
<PreferenceCategory app:title="@string/downloading">
<EditTextPreference
android:icon="@drawable/ic_key"
app:key="api_key"
app:defaultValue=""
app:summary="@string/api_key_summary"
app:title="@string/api_key" />
<SeekBarPreference
app:dependency="aria2"
android:defaultValue="1"

Loading…
Cancel
Save