Support SAF properly
This commit is contained in:
parent
1e09a1768e
commit
0f75024e03
23 changed files with 451 additions and 311 deletions
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue