mirror of https://github.com/deniscerri/ytdlnis
parent
f2c4fc33a3
commit
604fd300c8
@ -0,0 +1 @@
|
||||
YTDLnis
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,192 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 7,
|
||||
"identityHash": "9951239671c916d8805c4156bb69cb6b",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "results",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `videoId` TEXT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `downloadedAudio` INTEGER NOT NULL, `downloadedVideo` INTEGER NOT NULL, `isPlaylistItem` INTEGER NOT NULL, `website` TEXT NOT NULL, `downloadingAudio` INTEGER NOT NULL, `downloadingVideo` INTEGER NOT NULL, `playlistTitle` TEXT NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "videoId",
|
||||
"columnName": "videoId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "url",
|
||||
"columnName": "url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "author",
|
||||
"columnName": "author",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "duration",
|
||||
"columnName": "duration",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "thumb",
|
||||
"columnName": "thumb",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "downloadedAudio",
|
||||
"columnName": "downloadedAudio",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "downloadedVideo",
|
||||
"columnName": "downloadedVideo",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isPlaylistItem",
|
||||
"columnName": "isPlaylistItem",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "website",
|
||||
"columnName": "website",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "downloadingAudio",
|
||||
"columnName": "downloadingAudio",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "downloadingVideo",
|
||||
"columnName": "downloadingVideo",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "playlistTitle",
|
||||
"columnName": "playlistTitle",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "history",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `time` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `isQueuedDownload` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "url",
|
||||
"columnName": "url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "author",
|
||||
"columnName": "author",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "duration",
|
||||
"columnName": "duration",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "thumb",
|
||||
"columnName": "thumb",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "downloadPath",
|
||||
"columnName": "downloadPath",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "website",
|
||||
"columnName": "website",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isQueuedDownload",
|
||||
"columnName": "isQueuedDownload",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '9951239671c916d8805c4156bb69cb6b')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,359 +0,0 @@
|
||||
package com.deniscerri.ytdlnis;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.deniscerri.ytdlnis.database.DBManager;
|
||||
import com.deniscerri.ytdlnis.database.Video;
|
||||
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding;
|
||||
import com.deniscerri.ytdlnis.page.DownloadsFragment;
|
||||
import com.deniscerri.ytdlnis.page.HomeFragment;
|
||||
import com.deniscerri.ytdlnis.page.MoreFragment;
|
||||
import com.deniscerri.ytdlnis.page.settings.SettingsActivity;
|
||||
import com.deniscerri.ytdlnis.service.IDownloaderListener;
|
||||
import com.deniscerri.ytdlnis.service.IDownloaderService;
|
||||
import com.deniscerri.ytdlnis.util.UpdateUtil;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MainActivity extends AppCompatActivity{
|
||||
|
||||
ActivityMainBinding binding;
|
||||
Context context;
|
||||
|
||||
private static final String TAG = "MainActivity";
|
||||
|
||||
private HomeFragment homeFragment;
|
||||
private DownloadsFragment downloadsFragment;
|
||||
private MoreFragment moreFragment;
|
||||
|
||||
private Fragment lastFragment;
|
||||
private FragmentManager fm;
|
||||
|
||||
private boolean isDownloadServiceRunning = false;
|
||||
public DownloaderService downloaderService;
|
||||
private ArrayList<IDownloaderListener> listeners = null;
|
||||
private IDownloaderService iDownloaderService;
|
||||
|
||||
public final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
downloaderService = ((DownloaderService.LocalBinder) service).getService();
|
||||
iDownloaderService = (IDownloaderService) service;
|
||||
isDownloadServiceRunning = true;
|
||||
try{
|
||||
iDownloaderService.addActivity(MainActivity.this, listeners);
|
||||
for (int i = 0; i < listeners.size(); i++){
|
||||
IDownloaderListener listener = listeners.get(i);
|
||||
listener.onDownloadStart(iDownloaderService.getDownloadInfo());
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName componentName) {
|
||||
downloaderService = null;
|
||||
iDownloaderService = null;
|
||||
isDownloadServiceRunning = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
setContentView(binding.getRoot());
|
||||
context = getBaseContext();
|
||||
reconnectDownloadService();
|
||||
checkUpdate();
|
||||
|
||||
fm = getSupportFragmentManager();
|
||||
|
||||
homeFragment = new HomeFragment();
|
||||
downloadsFragment = new DownloadsFragment();
|
||||
moreFragment = new MoreFragment();
|
||||
|
||||
initFragments();
|
||||
|
||||
binding.bottomNavigationView.setOnItemSelectedListener(item -> {
|
||||
int id = item.getItemId();
|
||||
if(id == R.id.home){
|
||||
if(lastFragment == homeFragment){
|
||||
homeFragment.scrollToTop();
|
||||
}else{
|
||||
this.setTitle(R.string.app_name);;
|
||||
}
|
||||
replaceFragment(homeFragment);
|
||||
}else if(id == R.id.downloads){
|
||||
if(lastFragment == downloadsFragment){
|
||||
downloadsFragment.scrollToTop();
|
||||
}else {
|
||||
this.setTitle(getString(R.string.downloads));
|
||||
}
|
||||
replaceFragment(downloadsFragment);
|
||||
}else if(id == R.id.more){
|
||||
if(lastFragment == moreFragment){
|
||||
Intent intent = new Intent(context, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
}else{
|
||||
this.setTitle(getString(R.string.more));
|
||||
}
|
||||
replaceFragment(moreFragment);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
getWindow().getDecorView().setOnApplyWindowInsetsListener((view, windowInsets) -> {
|
||||
WindowInsetsCompat windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(windowInsets, view);
|
||||
boolean isImeVisible = windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime());
|
||||
binding.bottomNavigationView.setVisibility(isImeVisible ? View.GONE : View.VISIBLE);
|
||||
view.onApplyWindowInsets(windowInsets);
|
||||
return windowInsets;
|
||||
});
|
||||
|
||||
askPermissions();
|
||||
|
||||
Intent intent = getIntent();
|
||||
handleIntents(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
try {
|
||||
iDownloaderService.removeActivity(this);
|
||||
context.getApplicationContext().unbindService(serviceConnection);
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
handleIntents(intent);
|
||||
}
|
||||
|
||||
public void handleIntents(Intent intent){
|
||||
String action = intent.getAction();
|
||||
String type = intent.getType();
|
||||
if(Intent.ACTION_SEND.equals(action) && type != null){
|
||||
Log.e(TAG, action);
|
||||
|
||||
homeFragment = new HomeFragment();
|
||||
downloadsFragment = new DownloadsFragment();
|
||||
moreFragment = new MoreFragment();
|
||||
if (type.equalsIgnoreCase("application/txt")){
|
||||
try{
|
||||
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
InputStream is = getContentResolver().openInputStream(uri);
|
||||
StringBuilder textBuilder = new StringBuilder();
|
||||
Reader reader = new BufferedReader(new InputStreamReader
|
||||
(is, Charset.forName(StandardCharsets.UTF_8.name())));
|
||||
int c = 0;
|
||||
while ((c = reader.read()) != -1) {
|
||||
textBuilder.append((char) c);
|
||||
}
|
||||
List<String> l = Arrays.asList(textBuilder.toString().split("\n"));
|
||||
LinkedList<String> lines = new LinkedList<>(l);
|
||||
homeFragment.handleFileIntent(lines);
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}else{
|
||||
homeFragment.handleIntent(intent);
|
||||
}
|
||||
initFragments();
|
||||
}
|
||||
}
|
||||
|
||||
private void initFragments(){
|
||||
fm.beginTransaction()
|
||||
.replace(R.id.frame_layout, homeFragment)
|
||||
.add(R.id.frame_layout, downloadsFragment)
|
||||
.add(R.id.frame_layout, moreFragment)
|
||||
.hide(downloadsFragment)
|
||||
.hide(moreFragment)
|
||||
.commit();
|
||||
|
||||
lastFragment = homeFragment;
|
||||
|
||||
listeners = new ArrayList<>();
|
||||
listeners.add(homeFragment.listener);
|
||||
listeners.add(downloadsFragment.listener);
|
||||
}
|
||||
|
||||
private void replaceFragment(Fragment f){
|
||||
fm.beginTransaction().hide(lastFragment).show(f).commit();
|
||||
lastFragment = f;
|
||||
}
|
||||
|
||||
public void startDownloadService(ArrayList<Video> downloadQueue, IDownloaderListener awaitingListener){
|
||||
addQueueToDownloads(downloadQueue);
|
||||
if(isDownloadServiceRunning){
|
||||
iDownloaderService.updateQueue(downloadQueue);
|
||||
return;
|
||||
}
|
||||
if(!listeners.contains(awaitingListener)) listeners.add(awaitingListener);
|
||||
Intent serviceIntent = new Intent(context, DownloaderService.class);
|
||||
serviceIntent.putParcelableArrayListExtra("queue", downloadQueue);
|
||||
context.getApplicationContext().startService(serviceIntent);
|
||||
context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
public void addQueueToDownloads(ArrayList<Video> downloadQueue) {
|
||||
try {
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
|
||||
if (!sharedPreferences.getBoolean("incognito", false)) {
|
||||
DBManager dbManager = new DBManager(context);
|
||||
for (int i = downloadQueue.size() - 1; i >= 0; i--){
|
||||
Video v = downloadQueue.get(i);
|
||||
v.setQueuedDownload(true);
|
||||
dbManager.addToHistory(v);
|
||||
}
|
||||
dbManager.close();
|
||||
downloadsFragment.setDownloading(true);
|
||||
downloadsFragment.initCards();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopDownloadService(){
|
||||
if(!isDownloadServiceRunning) return;
|
||||
try {
|
||||
iDownloaderService.removeActivity(this);
|
||||
context.getApplicationContext().unbindService(serviceConnection);
|
||||
context.getApplicationContext().stopService(new Intent(context.getApplicationContext(), DownloaderService.class));
|
||||
}catch (Exception ignored){}
|
||||
isDownloadServiceRunning = false;
|
||||
}
|
||||
|
||||
public void cancelDownloadService(){
|
||||
if(!isDownloadServiceRunning) return;
|
||||
iDownloaderService.cancelDownload(true);
|
||||
stopDownloadService();
|
||||
}
|
||||
|
||||
public void removeItemFromDownloadQueue(Video video, String type){
|
||||
iDownloaderService.removeItemFromDownloadQueue(video, type);
|
||||
}
|
||||
|
||||
public boolean isDownloadServiceRunning() {
|
||||
ActivityManager.RunningServiceInfo service = getService(DownloaderService.class);
|
||||
if(service != null){
|
||||
if (service.foreground) {
|
||||
isDownloadServiceRunning = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void reconnectDownloadService(){
|
||||
ActivityManager.RunningServiceInfo service = getService(DownloaderService.class);
|
||||
if(service != null){
|
||||
Intent serviceIntent = new Intent(context.getApplicationContext(), DownloaderService.class);
|
||||
serviceIntent.putExtra("rebind", true);
|
||||
context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||
isDownloadServiceRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
private ActivityManager.RunningServiceInfo getService(Class className){
|
||||
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
|
||||
if (className.getName().equals(service.service.getClassName())) {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkUpdate(){
|
||||
SharedPreferences preferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
|
||||
if(preferences.getBoolean("update_app", false)){
|
||||
UpdateUtil updateUtil = new UpdateUtil(this);
|
||||
updateUtil.updateApp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void askPermissions(){
|
||||
if(!checkFilePermission()){
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
Log.e(TAG, String.valueOf(grantResults[0]));
|
||||
for(int i = 0; i < permissions.length; i++){
|
||||
if(grantResults[i] == PackageManager.PERMISSION_DENIED){
|
||||
createPermissionRequestDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void exit(){
|
||||
this.finishAffinity();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private boolean checkFilePermission(){
|
||||
return ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
private void createPermissionRequestDialog(){
|
||||
MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(this);
|
||||
dialog.setTitle(getString(R.string.warning));
|
||||
dialog.setMessage(getString(R.string.request_permission_desc));
|
||||
dialog.setOnCancelListener(dialogInterface -> exit());
|
||||
dialog.setNegativeButton(getString(R.string.exit_app), (dialogInterface, i) -> exit());
|
||||
dialog.setPositiveButton(getString(R.string.ok), (dialogInterface, i) -> {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", getPackageName(), null));
|
||||
startActivity(intent);
|
||||
System.exit(0);
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,363 @@
|
||||
package com.deniscerri.ytdlnis
|
||||
|
||||
import android.Manifest
|
||||
import android.app.ActivityManager
|
||||
import android.content.*
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.deniscerri.ytdlnis.DownloaderService.LocalBinder
|
||||
import com.deniscerri.ytdlnis.database.DatabaseManager
|
||||
import com.deniscerri.ytdlnis.database.Video
|
||||
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding
|
||||
import com.deniscerri.ytdlnis.page.DownloadsFragment
|
||||
import com.deniscerri.ytdlnis.page.HomeFragment
|
||||
import com.deniscerri.ytdlnis.page.MoreFragment
|
||||
import com.deniscerri.ytdlnis.page.settings.SettingsActivity
|
||||
import com.deniscerri.ytdlnis.service.IDownloaderListener
|
||||
import com.deniscerri.ytdlnis.service.IDownloaderService
|
||||
import com.deniscerri.ytdlnis.util.UpdateUtil
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.io.Reader
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
lateinit var context: Context
|
||||
private lateinit var homeFragment: HomeFragment
|
||||
private lateinit var downloadsFragment: DownloadsFragment
|
||||
private lateinit var moreFragment: MoreFragment
|
||||
private lateinit var lastFragment: Fragment
|
||||
private lateinit var fm: FragmentManager
|
||||
private var isDownloadServiceRunning = false
|
||||
var downloaderService: DownloaderService? = null
|
||||
private lateinit var listeners: ArrayList<IDownloaderListener>
|
||||
private var iDownloaderService: IDownloaderService? = null
|
||||
|
||||
private val serviceConnection: ServiceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
downloaderService = (service as LocalBinder).service
|
||||
iDownloaderService = service
|
||||
isDownloadServiceRunning = true
|
||||
try {
|
||||
iDownloaderService!!.addActivity(this@MainActivity, listeners)
|
||||
for (i in listeners.indices) {
|
||||
val listener = listeners[i]
|
||||
listener.onDownloadStart(iDownloaderService!!.downloadInfo)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(componentName: ComponentName) {
|
||||
downloaderService = null
|
||||
iDownloaderService = null
|
||||
isDownloadServiceRunning = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
setContentView(binding.root)
|
||||
context = baseContext
|
||||
reconnectDownloadService()
|
||||
checkUpdate()
|
||||
fm = supportFragmentManager
|
||||
homeFragment = HomeFragment()
|
||||
downloadsFragment = DownloadsFragment()
|
||||
moreFragment = MoreFragment()
|
||||
initFragments()
|
||||
binding.bottomNavigationView.setOnItemSelectedListener { item: MenuItem ->
|
||||
when (item.itemId) {
|
||||
R.id.home -> {
|
||||
if (lastFragment === homeFragment) {
|
||||
homeFragment.scrollToTop()
|
||||
} else {
|
||||
this.setTitle(R.string.app_name)
|
||||
}
|
||||
replaceFragment(homeFragment)
|
||||
}
|
||||
R.id.downloads -> {
|
||||
if (lastFragment === downloadsFragment) {
|
||||
downloadsFragment.scrollToTop()
|
||||
} else {
|
||||
this.title = getString(R.string.downloads)
|
||||
}
|
||||
replaceFragment(downloadsFragment)
|
||||
}
|
||||
R.id.more -> {
|
||||
if (lastFragment === moreFragment) {
|
||||
val intent = Intent(context, SettingsActivity::class.java)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
this.title = getString(R.string.more)
|
||||
}
|
||||
replaceFragment(moreFragment)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
window.decorView.setOnApplyWindowInsetsListener { view: View, windowInsets: WindowInsets? ->
|
||||
val windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(
|
||||
windowInsets!!, view
|
||||
)
|
||||
val isImeVisible = windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime())
|
||||
binding.bottomNavigationView.visibility =
|
||||
if (isImeVisible) View.GONE else View.VISIBLE
|
||||
view.onApplyWindowInsets(windowInsets)
|
||||
windowInsets
|
||||
}
|
||||
askPermissions()
|
||||
val intent = intent
|
||||
handleIntents(intent)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
try {
|
||||
iDownloaderService!!.removeActivity(this)
|
||||
context.applicationContext.unbindService(serviceConnection)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
handleIntents(intent)
|
||||
}
|
||||
|
||||
private fun handleIntents(intent: Intent) {
|
||||
val action = intent.action
|
||||
val type = intent.type
|
||||
if (Intent.ACTION_SEND == action && type != null) {
|
||||
Log.e(TAG, action)
|
||||
homeFragment = HomeFragment()
|
||||
downloadsFragment = DownloadsFragment()
|
||||
moreFragment = MoreFragment()
|
||||
if (type.equals("application/txt", ignoreCase = true)) {
|
||||
try {
|
||||
val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
|
||||
val `is` = contentResolver.openInputStream(uri!!)
|
||||
val textBuilder = StringBuilder()
|
||||
val reader: Reader = BufferedReader(
|
||||
InputStreamReader(
|
||||
`is`, Charset.forName(
|
||||
StandardCharsets.UTF_8.name()
|
||||
)
|
||||
)
|
||||
)
|
||||
var c: Int
|
||||
while (reader.read().also { c = it } != -1) {
|
||||
textBuilder.append(c.toChar())
|
||||
}
|
||||
val l = listOf(*textBuilder.toString().split("\n").toTypedArray())
|
||||
val lines = LinkedList(l)
|
||||
homeFragment.handleFileIntent(lines)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} else {
|
||||
homeFragment.handleIntent(intent)
|
||||
}
|
||||
initFragments()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initFragments() {
|
||||
fm.beginTransaction()
|
||||
.replace(R.id.frame_layout, homeFragment)
|
||||
.add(R.id.frame_layout, downloadsFragment)
|
||||
.add(R.id.frame_layout, moreFragment)
|
||||
.hide(downloadsFragment)
|
||||
.hide(moreFragment)
|
||||
.commit()
|
||||
lastFragment = homeFragment
|
||||
listeners = ArrayList()
|
||||
listeners.add(homeFragment.listener)
|
||||
listeners.add(downloadsFragment.listener)
|
||||
}
|
||||
|
||||
private fun replaceFragment(f: Fragment) {
|
||||
fm.beginTransaction().hide(lastFragment).show(f).commit()
|
||||
lastFragment = f
|
||||
}
|
||||
|
||||
fun startDownloadService(
|
||||
downloadQueue: ArrayList<Video>,
|
||||
awaitingListener: IDownloaderListener
|
||||
) {
|
||||
addQueueToDownloads(downloadQueue)
|
||||
if (isDownloadServiceRunning) {
|
||||
iDownloaderService?.updateQueue(downloadQueue)
|
||||
return
|
||||
}
|
||||
if (!listeners.contains(awaitingListener)) listeners.add(awaitingListener)
|
||||
val serviceIntent = Intent(context, DownloaderService::class.java)
|
||||
serviceIntent.putParcelableArrayListExtra("queue", downloadQueue)
|
||||
context.applicationContext.startService(serviceIntent)
|
||||
context.applicationContext.bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE)
|
||||
}
|
||||
|
||||
private fun addQueueToDownloads(downloadQueue: ArrayList<Video>) {
|
||||
try {
|
||||
val sharedPreferences = context.getSharedPreferences("root_preferences", MODE_PRIVATE)
|
||||
if (!sharedPreferences.getBoolean("incognito", false)) {
|
||||
val databaseManager = DatabaseManager(context)
|
||||
for (i in downloadQueue.indices.reversed()) {
|
||||
val v = downloadQueue[i]
|
||||
v.isQueuedDownload = true
|
||||
databaseManager.addToHistory(v)
|
||||
}
|
||||
databaseManager.close()
|
||||
downloadsFragment.setDownloading(true)
|
||||
downloadsFragment.initCards()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun stopDownloadService() {
|
||||
if (!isDownloadServiceRunning) return
|
||||
try {
|
||||
iDownloaderService!!.removeActivity(this)
|
||||
context.applicationContext.unbindService(serviceConnection)
|
||||
context.applicationContext.stopService(
|
||||
Intent(
|
||||
context.applicationContext,
|
||||
DownloaderService::class.java
|
||||
)
|
||||
)
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
isDownloadServiceRunning = false
|
||||
}
|
||||
|
||||
fun cancelDownloadService() {
|
||||
if (!isDownloadServiceRunning) return
|
||||
iDownloaderService!!.cancelDownload(true)
|
||||
stopDownloadService()
|
||||
}
|
||||
|
||||
fun removeItemFromDownloadQueue(video: Video?, type: String?) {
|
||||
iDownloaderService!!.removeItemFromDownloadQueue(video, type)
|
||||
}
|
||||
|
||||
fun isDownloadServiceRunning(): Boolean {
|
||||
val service = getService(DownloaderService::class.java)
|
||||
if (service != null) {
|
||||
if (service.foreground) {
|
||||
isDownloadServiceRunning = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun reconnectDownloadService() {
|
||||
val service = getService(DownloaderService::class.java)
|
||||
if (service != null) {
|
||||
val serviceIntent = Intent(context.applicationContext, DownloaderService::class.java)
|
||||
serviceIntent.putExtra("rebind", true)
|
||||
context.applicationContext.bindService(
|
||||
serviceIntent,
|
||||
serviceConnection,
|
||||
BIND_AUTO_CREATE
|
||||
)
|
||||
isDownloadServiceRunning = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun getService(className: Class<*>): ActivityManager.RunningServiceInfo? {
|
||||
val manager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
|
||||
for (service in manager.getRunningServices(Int.MAX_VALUE)) {
|
||||
if (className.name == service.service.className) {
|
||||
return service
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun checkUpdate() {
|
||||
val preferences = context.getSharedPreferences("root_preferences", MODE_PRIVATE)
|
||||
if (preferences.getBoolean("update_app", false)) {
|
||||
val updateUtil = UpdateUtil(this)
|
||||
updateUtil.updateApp()
|
||||
}
|
||||
}
|
||||
|
||||
private fun askPermissions() {
|
||||
if (!checkFilePermission()) {
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
|
||||
1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
Log.e(TAG, grantResults[0].toString())
|
||||
for (i in permissions.indices) {
|
||||
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
|
||||
createPermissionRequestDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun exit() {
|
||||
finishAffinity()
|
||||
exitProcess(0)
|
||||
}
|
||||
|
||||
private fun checkFilePermission(): Boolean {
|
||||
return (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
== PackageManager.PERMISSION_GRANTED)
|
||||
}
|
||||
|
||||
private fun createPermissionRequestDialog() {
|
||||
val dialog = MaterialAlertDialogBuilder(this)
|
||||
dialog.setTitle(getString(R.string.warning))
|
||||
dialog.setMessage(getString(R.string.request_permission_desc))
|
||||
dialog.setOnCancelListener { exit() }
|
||||
dialog.setNegativeButton(getString(R.string.exit_app)) { _: DialogInterface?, _: Int -> exit() }
|
||||
dialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
||||
val intent = Intent(
|
||||
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
|
||||
Uri.fromParts("package", packageName, null)
|
||||
)
|
||||
startActivity(intent)
|
||||
exitProcess(0)
|
||||
}
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainActivity"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.deniscerri.ytdlnis.database
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import com.deniscerri.ytdlnis.database.dao.HistoryDao
|
||||
import com.deniscerri.ytdlnis.database.dao.ResultDao
|
||||
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
|
||||
@Database(
|
||||
entities = [ResultItem::class, HistoryItem::class],
|
||||
version = 7,
|
||||
autoMigrations = []
|
||||
)
|
||||
abstract class DBManager : RoomDatabase(){
|
||||
abstract val resultDao : ResultDao
|
||||
abstract val historyDao : HistoryDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var instance : DBManager? = null
|
||||
|
||||
fun getInstance(context: Context) : DBManager {
|
||||
if (instance == null){
|
||||
synchronized(this){
|
||||
instance = buildDatabase(context)
|
||||
}
|
||||
}
|
||||
return instance!!
|
||||
}
|
||||
|
||||
private fun buildDatabase(context: Context) : DBManager {
|
||||
return Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
DBManager::class.java, "ytdlnis_db"
|
||||
)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package com.deniscerri.ytdlnis.database.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
|
||||
@Dao
|
||||
interface HistoryDao {
|
||||
|
||||
@Query("SELECT * FROM history WHERE title LIKE '%'||:query||'%' AND type LIKE '%'||:format||'%' AND website LIKE '%'||:site||'%' ORDER BY " +
|
||||
"CASE WHEN :sort = 'ASC' THEN id END ASC," +
|
||||
"CASE WHEN :sort = 'DESC' THEN id END DESC," +
|
||||
"CASE WHEN :sort = '' THEN id END DESC ")
|
||||
suspend fun getHistory(query : String, format : String, site : String, sort : String) : List<HistoryItem>
|
||||
|
||||
@Query("SELECT * FROM history WHERE url=:url AND type=:type LIMIT 1")
|
||||
suspend fun getHistoryItemByURLAndType(url: String, type: String) : HistoryItem
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun addToHistory(results: ArrayList<HistoryItem>)
|
||||
|
||||
@Query("DELETE FROM history")
|
||||
suspend fun clearHistory()
|
||||
|
||||
@Query("DELETE FROM history where id=:id")
|
||||
suspend fun deleteItem(id: Int)
|
||||
|
||||
@Transaction
|
||||
suspend fun clearDeletedHistory(){
|
||||
val fileUtil = FileUtil()
|
||||
val items : List<HistoryItem> = getHistory("","","","")
|
||||
items.forEach { item ->
|
||||
if (!fileUtil.exists(item.downloadPath)){
|
||||
clearHistoryItem(item, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transaction
|
||||
suspend fun clearDownloadingHistory(){
|
||||
val items : List<HistoryItem> = getHistory("","","","")
|
||||
items.forEach { item ->
|
||||
if (item.isQueuedDownload == 1){
|
||||
clearHistoryItem(item, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Query("DELETE FROM history WHERE id > (SELECT MIN(h.id) FROM history h WHERE h.url = history.url AND h.type = history.type)")
|
||||
suspend fun clearDuplicates()
|
||||
|
||||
@Query("UPDATE results SET downloadedAudio=0, downloadedVideo=0 WHERE downloadedAudio=1 OR downloadedVideo=1")
|
||||
suspend fun removeAllDownloadStatusesFromResults()
|
||||
|
||||
@Query("UPDATE results SET downloadedAudio=0 WHERE downloadedAudio=1 AND url=:url")
|
||||
suspend fun removeAudioDownloadStatusFromOneResult(url: String)
|
||||
|
||||
@Query("UPDATE results SET downloadedVideo=0 WHERE downloadedVideo=1 AND url=:url")
|
||||
suspend fun removeVideoDownloadStatusFromOneResult(url: String)
|
||||
|
||||
@Transaction
|
||||
suspend fun clearDuplicateHistory(){
|
||||
clearDuplicates()
|
||||
removeAllDownloadStatusesFromResults()
|
||||
}
|
||||
|
||||
|
||||
@Transaction
|
||||
suspend fun clearHistoryItem(video: HistoryItem, delete_file : Boolean){
|
||||
if (delete_file){
|
||||
val fileUtil = FileUtil()
|
||||
fileUtil.deleteFile(video.downloadPath)
|
||||
}
|
||||
deleteItem(video.id)
|
||||
when(video.type){
|
||||
"audio" -> removeAudioDownloadStatusFromOneResult(video.url)
|
||||
"video" -> removeVideoDownloadStatusFromOneResult(video.url)
|
||||
}
|
||||
}
|
||||
|
||||
@Update
|
||||
suspend fun updateHistoryItem(item: HistoryItem)
|
||||
|
||||
@Transaction
|
||||
suspend fun checkDownloaded(url: String, type: String) : Boolean {
|
||||
val historyItem = getHistoryItemByURLAndType(url, type)
|
||||
val fileUtil = FileUtil()
|
||||
return fileUtil.exists(historyItem.downloadPath)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.deniscerri.ytdlnis.database.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
|
||||
@Dao
|
||||
interface ResultDao {
|
||||
|
||||
@Query("SELECT * FROM results")
|
||||
suspend fun getResults() : List<ResultItem>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun addToResults(results: ArrayList<ResultItem>)
|
||||
|
||||
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun updateResult(item: ResultItem)
|
||||
|
||||
@Query("DELETE FROM results")
|
||||
suspend fun clearResults()
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.deniscerri.ytdlnis.database.models
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "history")
|
||||
data class HistoryItem(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Int,
|
||||
val url: String,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val duration: String,
|
||||
val thumb: String,
|
||||
val type: String,
|
||||
val time: String,
|
||||
val downloadPath: String,
|
||||
val website: String,
|
||||
val isQueuedDownload: Int
|
||||
)
|
||||
@ -0,0 +1,23 @@
|
||||
package com.deniscerri.ytdlnis.database.models
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "results")
|
||||
data class ResultItem(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Int,
|
||||
val videoId: String,
|
||||
val url: String,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val duration: String,
|
||||
val thumb: String,
|
||||
val downloadedAudio: Int,
|
||||
val downloadedVideo: Int,
|
||||
val isPlaylistItem: Int,
|
||||
val website: String,
|
||||
val downloadingAudio: Int,
|
||||
val downloadingVideo: Int,
|
||||
val playlistTitle: String
|
||||
)
|
||||
@ -0,0 +1,36 @@
|
||||
package com.deniscerri.ytdlnis.util;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.ForegroundInfo;
|
||||
import androidx.work.Worker;
|
||||
import androidx.work.WorkerParameters;
|
||||
|
||||
import com.deniscerri.ytdlnis.MainActivity;
|
||||
import com.deniscerri.ytdlnis.database.Video;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import kotlin.random.Random;
|
||||
|
||||
public class DownloadWorker extends Worker {
|
||||
private Context context;
|
||||
private WorkerParameters workerParams;
|
||||
public DownloadWorker(
|
||||
@NonNull Context appContext,
|
||||
@NonNull WorkerParameters workerParams) {
|
||||
super(appContext, workerParams);
|
||||
this.context = appContext;
|
||||
this.workerParams = workerParams;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Result doWork() {
|
||||
//TODO
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.deniscerri.ytdlnis.util
|
||||
|
||||
import java.io.File
|
||||
|
||||
class FileUtil {
|
||||
fun deleteFile(path: String){
|
||||
val file = File(path)
|
||||
if (file.exists()) {
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
|
||||
fun exists(path: String) : Boolean {
|
||||
val file = File(path)
|
||||
if (path.isEmpty()) return false
|
||||
return file.exists()
|
||||
}
|
||||
}
|
||||
@ -1,53 +1,44 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
|
||||
buildscript {
|
||||
|
||||
|
||||
def versionMajor = 1
|
||||
def versionMinor = 4
|
||||
def versionPatch = 6
|
||||
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
|
||||
|
||||
ext {
|
||||
versionCode = versionMajor * 100000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
|
||||
versionName = "${versionMajor}.${versionMinor}.${versionPatch}"
|
||||
// dependency versions
|
||||
appCompatVer = '1.5.1'
|
||||
junitVer = '4.13.2'
|
||||
androidJunitVer = '1.1.1'
|
||||
espressoVer = '3.2.0'
|
||||
jacksonVer = '2.9.8'
|
||||
// supports java 1.6
|
||||
commonsIoVer = '2.5'
|
||||
// supports java 1.6
|
||||
commonsCompressVer = '1.12'
|
||||
youtubedlAndroidVer = "master-SNAPSHOT"
|
||||
workVer = "2.7.1"
|
||||
composeVer = "1.3.2"
|
||||
kotlinVer = "1.7.20"
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
def versionMajor = 1
|
||||
def versionMinor = 4
|
||||
def versionPatch = 6
|
||||
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
|
||||
|
||||
ext {
|
||||
versionCode = versionMajor * 100000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
|
||||
versionName = "${versionMajor}.${versionMinor}.${versionPatch}"
|
||||
// dependency versions
|
||||
appCompatVer = '1.1.0'
|
||||
junitVer = '4.12'
|
||||
androidJunitVer = '1.1.1'
|
||||
espressoVer = '3.2.0'
|
||||
jacksonVer = '2.9.8'
|
||||
// supports java 1.6
|
||||
commonsIoVer = '2.5'
|
||||
// supports java 1.6
|
||||
commonsCompressVer = '1.12'
|
||||
youtubedlAndroidVer = "master-SNAPSHOT"
|
||||
workVer = "2.7.1"
|
||||
plugins {
|
||||
id 'com.android.application' version '7.3.1' apply false
|
||||
id 'com.android.library' version '7.3.1' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group = 'com.github.deniscerri'
|
||||
version = versionName
|
||||
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
#Wed Dec 07 20:51:43 CET 2022
|
||||
#Tue Jan 03 22:34:47 CET 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@ -1 +1,20 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
rootProject.name = "YTDLnis"
|
||||
|
||||
include ':common', ':app', ':library', ':ffmpeg'
|
||||
|
||||
Loading…
Reference in New Issue