ytdlnis/app/src/main/java/com/deniscerri/ytdl/page/CustomCommandActivity.java
2022-09-19 17:21:11 +02:00

206 lines
8 KiB
Java

package com.deniscerri.ytdl.page;
import static com.deniscerri.ytdl.App.notificationUtil;
import android.Manifest;
import android.app.Activity;
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.media.MediaScannerConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.deniscerri.ytdl.BuildConfig;
import com.deniscerri.ytdl.DownloaderService;
import com.deniscerri.ytdl.R;
import com.deniscerri.ytdl.page.settings.SettingsFragment;
import com.deniscerri.ytdl.util.NotificationUtil;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.yausername.youtubedl_android.DownloadProgressCallback;
import com.yausername.youtubedl_android.YoutubeDL;
import com.yausername.youtubedl_android.YoutubeDLRequest;
import java.io.File;
import java.util.Collections;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class CustomCommandActivity extends AppCompatActivity {
private static final String TAG = "CustomCommandActivity";
private MaterialToolbar topAppBar;
private boolean running = false;
private boolean isDownloadServiceRunning = false;
public DownloaderService downloaderService;
private CompositeDisposable compositeDisposable = new CompositeDisposable();
private TextView output;
private EditText input;
private ExtendedFloatingActionButton fab;
private ExtendedFloatingActionButton cancelFab;
Context context;
private final DownloadProgressCallback callback = (progress, etaInSeconds, line) -> CustomCommandActivity.this.runOnUiThread(() -> {
output.append("\n"+line);
notificationUtil.updateDownloadNotification(NotificationUtil.COMMAND_DOWNLOAD_NOTIFICATION_ID,
line, (int) progress, 0, getString(R.string.running_ytdlp_command));
});
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
downloaderService = ((DownloaderService.LocalBinder) service).getService();
isDownloadServiceRunning = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
downloaderService = null;
isDownloadServiceRunning = false;
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_command);
context = getBaseContext();
topAppBar = findViewById(R.id.custom_command_toolbar);
topAppBar.setNavigationOnClickListener(view -> onBackPressed());
output = findViewById(R.id.custom_command_output);
output.setMovementMethod(new ScrollingMovementMethod());
input = findViewById(R.id.command_edittext);
input.requestFocus();
fab = findViewById(R.id.command_fab);
fab.setOnClickListener(view -> {
if (isStoragePermissionGranted()){
runCommand(input.getText().toString());
}
});
cancelFab = findViewById(R.id.cancel_command_fab);
cancelFab.setOnClickListener(view -> {
compositeDisposable.clear();
stopDownloadService();
swapFabs();
running = false;
input.setEnabled(true);
});
}
private void swapFabs(){
int cancel = cancelFab.getVisibility();
int start = fab.getVisibility();
cancelFab.setVisibility(start);
fab.setVisibility(cancel);
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
private void runCommand(String text){
if (running) {
Toast.makeText(this, "Cannot start command! A command is already in progress", Toast.LENGTH_LONG).show();
return;
}
if(!text.startsWith("yt-dlp ")){
Toast.makeText(context, "Wrong input! Try Again!", Toast.LENGTH_SHORT).show();
return;
}
input.setEnabled(false);
output.setText("");
startDownloadService(getString(R.string.running_ytdlp_command), NotificationUtil.COMMAND_DOWNLOAD_NOTIFICATION_ID);
text = text.substring(6).trim();
YoutubeDLRequest request = new YoutubeDLRequest(Collections.emptyList());
String commandRegex = "\"([^\"]*)\"|(\\S+)";
Matcher m = Pattern.compile(commandRegex).matcher(text);
while (m.find()) {
if (m.group(1) != null) {
request.addOption(m.group(1));
} else {
request.addOption(m.group(2));
}
}
SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
String downloadsDir = sharedPreferences.getString("command_path", getString(R.string.command_path));
File youtubeDLDir = new File(downloadsDir);
if (!youtubeDLDir.exists()) {
boolean isDirCreated = youtubeDLDir.mkdir();
if (!isDirCreated) {
Toast.makeText(context, R.string.failed_making_directory, Toast.LENGTH_LONG).show();
}
}
request.addOption("-o", youtubeDLDir.getAbsolutePath() + "/%(title)s.%(ext)s");
running = true;
swapFabs();
Disposable disposable = Observable.fromCallable(() -> YoutubeDL.getInstance().execute(request, callback))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(youtubeDLResponse -> {
output.append(youtubeDLResponse.getOut());
running = false;
stopDownloadService();
// MEDIA SCAN
MediaScannerConnection.scanFile(context, new String[]{"/storage"}, null, null);
input.setEnabled(true);
swapFabs();
}, e -> {
if (BuildConfig.DEBUG) Log.e(TAG, getString(R.string.failed_download), e);
output.append(e.getMessage());
running = false;
stopDownloadService();
swapFabs();
input.setEnabled(true);
});
compositeDisposable.add(disposable);
}
public void startDownloadService(String title, int id){
if(isDownloadServiceRunning) return;
Intent serviceIntent = new Intent(context, DownloaderService.class);
serviceIntent.putExtra("title", title);
serviceIntent.putExtra("id", id);
context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
public void stopDownloadService(){
if(!isDownloadServiceRunning) return;
context.getApplicationContext().unbindService(serviceConnection);
isDownloadServiceRunning = false;
}
public boolean isStoragePermissionGranted() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
return true;
}else{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
}