Support SAF properly

This commit is contained in:
wb9688 2020-06-13 17:29:57 +02:00 committed by Stypox
parent 1e09a1768e
commit 0f75024e03
No known key found for this signature in database
GPG key ID: 4BDF1B40A49FDD23
23 changed files with 451 additions and 311 deletions

View file

@ -7,8 +7,8 @@ import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.Menu
@ -52,7 +52,6 @@ import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem
import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem.Companion.PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService.EXPORT_COMPLETE_ACTION
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService.KEY_FILE_PATH
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.IMPORT_COMPLETE_ACTION
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE
@ -62,7 +61,7 @@ import org.schabi.newpipe.util.FilePickerActivityHelper
import org.schabi.newpipe.util.NavigationHelper
import org.schabi.newpipe.util.OnClickGesture
import org.schabi.newpipe.util.ShareUtils
import java.io.File
import us.shandian.giga.io.StoredFileHelper
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@ -188,15 +187,14 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
}
private fun onImportPreviousSelected() {
startActivityForResult(FilePickerActivityHelper.chooseSingleFile(activity), REQUEST_IMPORT_CODE)
startActivityForResult(StoredFileHelper.getPicker(activity), REQUEST_IMPORT_CODE)
}
private fun onExportSelected() {
val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date())
val exportName = "newpipe_subscriptions_$date.json"
val exportFile = File(Environment.getExternalStorageDirectory(), exportName)
startActivityForResult(FilePickerActivityHelper.chooseFileToSave(activity, exportFile.absolutePath), REQUEST_EXPORT_CODE)
startActivityForResult(StoredFileHelper.getNewPicker(activity, null, exportName), REQUEST_EXPORT_CODE)
}
private fun openReorderDialog() {
@ -207,23 +205,20 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
super.onActivityResult(requestCode, resultCode, data)
if (data != null && data.data != null && resultCode == Activity.RESULT_OK) {
if (requestCode == REQUEST_EXPORT_CODE) {
val exportFile = Utils.getFileForUri(data.data!!)
val parentFile = exportFile.parentFile!!
if (!parentFile.canWrite() || !parentFile.canRead()) {
Toast.makeText(activity, R.string.invalid_directory, Toast.LENGTH_SHORT).show()
} else {
activity.startService(
Intent(activity, SubscriptionsExportService::class.java)
.putExtra(KEY_FILE_PATH, exportFile.absolutePath)
)
var uri = data.data!!
if (FilePickerActivityHelper.isOwnFileUri(activity, uri)) {
uri = Uri.fromFile(Utils.getFileForUri(uri))
}
activity.startService(
Intent(activity, SubscriptionsExportService::class.java)
.putExtra(SubscriptionsExportService.KEY_FILE_PATH, uri)
)
} else if (requestCode == REQUEST_IMPORT_CODE) {
val path = Utils.getFileForUri(data.data!!).absolutePath
ImportConfirmationDialog.show(
this,
Intent(activity, SubscriptionsImportService::class.java)
.putExtra(KEY_MODE, PREVIOUS_EXPORT_MODE)
.putExtra(KEY_VALUE, path)
.putExtra(KEY_VALUE, data.data)
)
}
}

View file

@ -18,8 +18,6 @@ import androidx.annotation.StringRes;
import androidx.appcompat.app.ActionBar;
import androidx.core.text.util.LinkifyCompat;
import com.nononsenseapps.filepicker.Utils;
import org.schabi.newpipe.BaseFragment;
import org.schabi.newpipe.R;
import org.schabi.newpipe.error.ErrorActivity;
@ -30,13 +28,13 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.FilePickerActivityHelper;
import org.schabi.newpipe.util.ServiceHelper;
import java.util.Collections;
import java.util.List;
import icepick.State;
import us.shandian.giga.io.StoredFileHelper;
import static org.schabi.newpipe.extractor.subscription.SubscriptionExtractor.ContentSource.CHANNEL_URL;
import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.CHANNEL_URL_MODE;
@ -175,8 +173,7 @@ public class SubscriptionsImportFragment extends BaseFragment {
}
public void onImportFile() {
startActivityForResult(FilePickerActivityHelper.chooseSingleFile(activity),
REQUEST_IMPORT_FILE_CODE);
startActivityForResult(StoredFileHelper.getPicker(activity), REQUEST_IMPORT_FILE_CODE);
}
@Override
@ -188,10 +185,10 @@ public class SubscriptionsImportFragment extends BaseFragment {
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_IMPORT_FILE_CODE
&& data.getData() != null) {
final String path = Utils.getFileForUri(data.getData()).getAbsolutePath();
ImportConfirmationDialog.show(this,
new Intent(activity, SubscriptionsImportService.class)
.putExtra(KEY_MODE, INPUT_STREAM_MODE).putExtra(KEY_VALUE, path)
.putExtra(KEY_MODE, INPUT_STREAM_MODE)
.putExtra(KEY_VALUE, data.getData())
.putExtra(Constants.KEY_SERVICE_ID, currentServiceId));
}
}

View file

@ -20,7 +20,7 @@
package org.schabi.newpipe.local.subscription.services;
import android.content.Intent;
import android.text.TextUtils;
import android.net.Uri;
import android.util.Log;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@ -31,16 +31,17 @@ import org.schabi.newpipe.App;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
import org.schabi.newpipe.streams.io.SharpOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.schedulers.Schedulers;
import us.shandian.giga.io.StoredFileHelper;
import static org.schabi.newpipe.MainActivity.DEBUG;
@ -55,8 +56,8 @@ public class SubscriptionsExportService extends BaseImportExportService {
+ ".services.SubscriptionsExportService.EXPORT_COMPLETE";
private Subscription subscription;
private File outFile;
private FileOutputStream outputStream;
private StoredFileHelper outFile;
private OutputStream outputStream;
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
@ -64,18 +65,18 @@ public class SubscriptionsExportService extends BaseImportExportService {
return START_NOT_STICKY;
}
final String path = intent.getStringExtra(KEY_FILE_PATH);
if (TextUtils.isEmpty(path)) {
final Uri path = intent.getParcelableExtra(KEY_FILE_PATH);
if (path == null) {
stopAndReportError(new IllegalStateException(
"Exporting to a file, but the path is empty or null"),
"Exporting to a file, but the path is null"),
"Exporting subscriptions");
return START_NOT_STICKY;
}
try {
outFile = new File(path);
outputStream = new FileOutputStream(outFile);
} catch (final FileNotFoundException e) {
outFile = new StoredFileHelper(this, path, "application/json");
outputStream = new SharpOutputStream(outFile.getStream());
} catch (final IOException e) {
handleError(e);
return START_NOT_STICKY;
}
@ -122,8 +123,8 @@ public class SubscriptionsExportService extends BaseImportExportService {
.subscribe(getSubscriber());
}
private Subscriber<File> getSubscriber() {
return new Subscriber<File>() {
private Subscriber<StoredFileHelper> getSubscriber() {
return new Subscriber<StoredFileHelper>() {
@Override
public void onSubscribe(final Subscription s) {
subscription = s;
@ -131,7 +132,7 @@ public class SubscriptionsExportService extends BaseImportExportService {
}
@Override
public void onNext(final File file) {
public void onNext(final StoredFileHelper file) {
if (DEBUG) {
Log.d(TAG, "startExport() success: file = " + file);
}
@ -153,7 +154,7 @@ public class SubscriptionsExportService extends BaseImportExportService {
};
}
private Function<List<SubscriptionItem>, File> exportToFile() {
private Function<List<SubscriptionItem>, StoredFileHelper> exportToFile() {
return subscriptionItems -> {
ImportExportJsonHelper.writeTo(subscriptionItems, outputStream, eventListener);
return outFile;

View file

@ -20,6 +20,7 @@
package org.schabi.newpipe.local.subscription.services;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
@ -36,12 +37,10 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.streams.io.SharpInputStream;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ExtractorHelper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@ -53,8 +52,10 @@ import io.reactivex.rxjava3.core.Notification;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.schedulers.Schedulers;
import us.shandian.giga.io.StoredFileHelper;
import static org.schabi.newpipe.MainActivity.DEBUG;
import static us.shandian.giga.io.StoredFileHelper.DEFAULT_MIME;
public class SubscriptionsImportService extends BaseImportExportService {
public static final int CHANNEL_URL_MODE = 0;
@ -101,17 +102,18 @@ public class SubscriptionsImportService extends BaseImportExportService {
if (currentMode == CHANNEL_URL_MODE) {
channelUrl = intent.getStringExtra(KEY_VALUE);
} else {
final String filePath = intent.getStringExtra(KEY_VALUE);
if (TextUtils.isEmpty(filePath)) {
final Uri uri = intent.getParcelableExtra(KEY_VALUE);
if (uri == null) {
stopAndReportError(new IllegalStateException(
"Importing from input stream, but file path is empty or null"),
"Importing from input stream, but file path is null"),
"Importing subscriptions");
return START_NOT_STICKY;
}
try {
inputStream = new FileInputStream(new File(filePath));
} catch (final FileNotFoundException e) {
inputStream = new SharpInputStream(
new StoredFileHelper(this, uri, DEFAULT_MIME).getStream());
} catch (final IOException e) {
handleError(e);
return START_NOT_STICKY;
}