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> <PersistentState>
<option name="values"> <option name="values">
<map> <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> </map>
</option> </option>
</PersistentState> </PersistentState>
@ -330,9 +330,8 @@
</option> </option>
<option name="values"> <option name="values">
<map> <map>
<entry key="assetSourceType" value="FILE" />
<entry key="color" value="00a6ff" /> <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" /> <entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
</map> </map>
</option> </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_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_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_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_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_launcher_foreground.xml" value="0.1965" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_lines.xml" value="0.109" /> <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:name=".DownloaderService"
android:enabled="true" android:enabled="true"
android:exported="false" /> android:exported="false" />
<meta-data
android:name="ytAPIkey"
android:value="${ytAPI}" />
</application> </application>
</manifest> </manifest>

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

@ -16,6 +16,7 @@ public class Video implements Parcelable {
private int downloadedVideo; private int downloadedVideo;
private String downloadedTime; private String downloadedTime;
private int isPlaylistItem; private int isPlaylistItem;
private String downloadPath;
private String website; private String website;
// RESULTS OBJECT // RESULTS OBJECT
@ -34,17 +35,18 @@ public class Video implements Parcelable {
} }
//HISTORY OBJECT //HISTORY OBJECT
public Video(int id, String videoId, String title, String author, String duration, String thumb, public Video(int id, String url, String title, String author, String duration, String thumb,
String downloadedType, String downloadedTime, int isPlaylistItem) { String downloadedType, String downloadedTime, String downloadPath, String website) {
this.id = id; this.id = id;
this.videoId = videoId; this.url = url;
this.title = title; this.title = title;
this.author = author; this.author = author;
this.duration = duration; this.duration = duration;
this.thumb = thumb; this.thumb = thumb;
this.downloadedType = downloadedType; this.downloadedType = downloadedType;
this.downloadedTime = downloadedTime; this.downloadedTime = downloadedTime;
this.isPlaylistItem = isPlaylistItem; this.downloadPath = downloadPath;
this.website = website;
} }
@ -61,6 +63,7 @@ public class Video implements Parcelable {
downloadedVideo = in.readInt(); downloadedVideo = in.readInt();
downloadedTime = in.readString(); downloadedTime = in.readString();
isPlaylistItem = in.readInt(); isPlaylistItem = in.readInt();
downloadPath = in.readString();
website = in.readString(); website = in.readString();
} }
@ -148,6 +151,54 @@ public class Video implements Parcelable {
public void setWebsite(String site){ this.website = site; } 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 @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
@ -167,6 +218,7 @@ public class Video implements Parcelable {
parcel.writeInt(downloadedVideo); parcel.writeInt(downloadedVideo);
parcel.writeString(downloadedTime); parcel.writeString(downloadedTime);
parcel.writeInt(isPlaylistItem); parcel.writeInt(isPlaylistItem);
parcel.writeString(downloadPath);
parcel.writeString(website); parcel.writeString(website);
} }

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

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

@ -29,6 +29,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
Preference videoPath; Preference videoPath;
Preference commandPath; Preference commandPath;
EditTextPreference apiKey;
SeekBarPreference concurrentFragments; SeekBarPreference concurrentFragments;
EditTextPreference limitRate; EditTextPreference limitRate;
SwitchPreferenceCompat aria2; SwitchPreferenceCompat aria2;
@ -70,6 +71,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
videoPath = findPreference("video_path"); videoPath = findPreference("video_path");
commandPath = findPreference("command_path"); commandPath = findPreference("command_path");
apiKey = findPreference("api_key");
concurrentFragments = findPreference("concurrent_fragments"); concurrentFragments = findPreference("concurrent_fragments");
limitRate = findPreference("limit_rate"); limitRate = findPreference("limit_rate");
aria2 = findPreference("aria2"); aria2 = findPreference("aria2");
@ -96,6 +98,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
editor.putString("command_path", getString(R.string.command_path)); editor.putString("command_path", getString(R.string.command_path));
} }
editor.putString("api_key", apiKey.getText());
editor.putInt("concurrent_fragments", concurrentFragments.getValue()); editor.putInt("concurrent_fragments", concurrentFragments.getValue());
editor.putString("limit_rate", limitRate.getText()); editor.putString("limit_rate", limitRate.getText());
editor.putBoolean("aria2", aria2.isChecked()); editor.putBoolean("aria2", aria2.isChecked());
@ -136,6 +139,12 @@ public class SettingsFragment extends PreferenceFragmentCompat {
return true; return true;
}); });
apiKey.setOnPreferenceChangeListener((preference, newValue) -> {
editor.putString("api_key", String.valueOf(newValue));
editor.apply();
return true;
});
concurrentFragments.setOnPreferenceChangeListener((preference, newValue) -> { concurrentFragments.setOnPreferenceChangeListener((preference, newValue) -> {
int value = Integer.parseInt(String.valueOf(newValue)); int value = Integer.parseInt(String.valueOf(newValue));
editor.putInt("concurrent_fragments", value); 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.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.text.Html; import android.text.Html;
import android.util.Log; import android.util.Log;
import android.widget.Toast; 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.YoutubeDL;
import com.yausername.youtubedl_android.YoutubeDLRequest; import com.yausername.youtubedl_android.YoutubeDLRequest;
import com.yausername.youtubedl_android.YoutubeDLResponse; import com.yausername.youtubedl_android.YoutubeDLResponse;
import com.yausername.youtubedl_android.mapper.VideoInfo;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -24,19 +23,18 @@ import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
public class YoutubeAPIManager { public class InfoUtil {
private static final String TAG = "API MANAGER"; private static final String TAG = "API MANAGER";
private static String countryCODE = "US"; private static String countryCODE = "US";
private ArrayList<Video> videos; private ArrayList<Video> videos;
private String key; private String key;
private DBManager dbManager; private DBManager dbManager;
private YoutubeDLRequest youtubeDLRequest;
public YoutubeAPIManager(Context context) { public InfoUtil(Context context) {
@Nullable ApplicationInfo applicationInfo; @Nullable ApplicationInfo applicationInfo;
try{ try{
applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
key = applicationInfo.metaData.getString("ytAPIkey"); key = sharedPreferences.getString("api_key", "");
dbManager = new DBManager(context); dbManager = new DBManager(context);
Thread thread = new Thread(() -> { Thread thread = new Thread(() -> {
@ -57,6 +55,8 @@ public class YoutubeAPIManager {
} }
public ArrayList<Video> search(String query) throws JSONException{ public ArrayList<Video> search(String query) throws JSONException{
if (key.isEmpty()) return getFromYTDL(query);
videos = new ArrayList<>(); videos = new ArrayList<>();
//short data //short data
JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/search?part=snippet&q="+query+"&maxResults=25&regionCode="+countryCODE+"&key="+key); 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{ 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<>(); videos = new ArrayList<>();
String url = "https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet&pageToken="+nextPageToken+"&maxResults=50&regionCode="+countryCODE+"&playlistId="+id+"&key="+key; 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 { public Video getVideo(String id) throws JSONException {
if (key.isEmpty()) return getFromYTDL("https://www.youtube.com/watch?v="+id).get(0);
//short data //short data
JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id="+id+"&key="+key); 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"); String duration = res.getJSONArray("items").getJSONObject(0).getJSONObject("contentDetails").getString("duration");
@ -178,10 +181,9 @@ public class YoutubeAPIManager {
String duration = obj.getString("duration"); String duration = obj.getString("duration");
String thumb = obj.getString("thumb"); 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; String url = "https://www.youtube.com/watch?v=" + id;
int downloadedAudio = dbManager.checkDownloaded(url, "audio");
int downloadedVideo = dbManager.checkDownloaded(url, "video");
int isPLaylist = 0; int isPLaylist = 0;
video = new Video(id, url, title, author, duration, thumb, downloadedAudio, downloadedVideo, isPLaylist, "youtube"); video = new Video(id, url, title, author, duration, thumb, downloadedAudio, downloadedVideo, isPLaylist, "youtube");
@ -257,33 +259,74 @@ public class YoutubeAPIManager {
return o; return o;
} }
public Video getFromYTDL(String query){ public ArrayList<Video> getFromYTDL(String query){
Video video = null; videos = new ArrayList<>();
try { try {
VideoInfo streamInfo = YoutubeDL.getInstance().getInfo(query); YoutubeDLRequest request = new YoutubeDLRequest(query);
String id = streamInfo.getId(); request.addOption("--flat-playlist");
request.addOption("-J");
video = new Video( request.addOption("--skip-download");
id, if (!query.contains("http")) request.addOption("--default-search", "ytsearch25");
streamInfo.getUrl(),
streamInfo.getTitle(), YoutubeDLResponse youtubeDLResponse = YoutubeDL.getInstance().execute(request);
streamInfo.getUploader(), JSONObject jsonObject = new JSONObject(youtubeDLResponse.getOut());
formatIntegerDuration(streamInfo.getDuration()),
streamInfo.getThumbnail(), if(!jsonObject.has("entries")){
dbManager.checkDownloaded(id, "audio"), String url = jsonObject.getString("webpage_url");
dbManager.checkDownloaded(id, "video"), videos.add(new Video(
0, jsonObject.getString("id"),
streamInfo.getWebpageUrlBasename() 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){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();
} }
return video; return videos;
} }
public ArrayList<Video> getTrending(Context context) throws JSONException{ public ArrayList<Video> getTrending(Context context) throws JSONException{
if (key.isEmpty()) return new ArrayList<>();
videos = 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; 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){ 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; return format;
int minutes = (dur % 10000) / 100;
int seconds = dur % 100;
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", hours, minutes, seconds);
} }
// public ArrayList<String> getSearchHints(String query){ // 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"?> <?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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
@ -148,5 +148,4 @@
<include layout="@layout/home_download_all_bottom_sheet" <include layout="@layout/home_download_all_bottom_sheet"
android:visibility="gone" /> android:visibility="gone" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

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

@ -93,4 +93,10 @@
<string name="command_download_notification_channel_name">Command Downloads</string> <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="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="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> </resources>

@ -23,6 +23,13 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/downloading"> <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 <SeekBarPreference
app:dependency="aria2" app:dependency="aria2"
android:defaultValue="1" android:defaultValue="1"

Loading…
Cancel
Save