Use new Activity Result APIs
This commit is contained in:
29 files changed
+224
-281
No files matched your search
@@ -33,7 +33,7 @@ import java.util.List;
|
||||
|
||||
public abstract class RecordingApplication extends SceneApplication {
|
||||
|
||||
private List<WeakReference<Activity>> list = new LinkedList<>();
|
||||
private final List<WeakReference<Activity>> list = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
|
||||
@@ -48,7 +48,7 @@ public class MSQLiteBuilder {
|
||||
|
||||
private int version = 0;
|
||||
private List<String> statements;
|
||||
private SparseArray<List<String>> statementsMap = new SparseArray<>();
|
||||
private final SparseArray<List<String>> statementsMap = new SparseArray<>();
|
||||
|
||||
private static String javaTypeToSQLiteType(Class clazz) {
|
||||
String type = JAVA_TYPE_TO_SQLITE_TYPE.get(clazz);
|
||||
|
||||
@@ -34,7 +34,7 @@ public class FavouriteStatusRouter {
|
||||
@SuppressLint("UseSparseArrays")
|
||||
private final HashMap<Integer, Map<Long, GalleryInfo>> maps = new HashMap<>();
|
||||
|
||||
private List<Listener> listeners = new ArrayList<>();
|
||||
private final List<Listener> listeners = new ArrayList<>();
|
||||
|
||||
public int saveDataMap(Map<Long, GalleryInfo> map) {
|
||||
int id = idGenerator.nextId();
|
||||
|
||||
@@ -124,7 +124,7 @@ public class Hosts {
|
||||
if (ip_list == null) {
|
||||
return false;
|
||||
}
|
||||
for (String ip: ip_list.split("\\+")) {
|
||||
for (String ip : ip_list.split("\\+")) {
|
||||
if (parseV4(ip) == null && parseV6(ip) == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class EhDns implements Dns {
|
||||
private static void put(Map<String, List<InetAddress>> map, String host, String ips) {
|
||||
String[] ipList = ips.split("\\+");
|
||||
InetAddress[] addresses = new InetAddress[ipList.length];
|
||||
for (int i = 0;i < ipList.length;i++) {
|
||||
for (int i = 0; i < ipList.length; i++) {
|
||||
addresses[i] = Hosts.toInetAddress(host, ipList[i]);
|
||||
}
|
||||
map.put(host, Arrays.asList(addresses));
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.hippo.ehviewer.client.exception;
|
||||
|
||||
public class ParseException extends EhException {
|
||||
|
||||
private String mBody;
|
||||
private final String mBody;
|
||||
|
||||
public ParseException(String detailMessage, String body) {
|
||||
super(detailMessage);
|
||||
|
||||
@@ -264,7 +264,7 @@ public class GalleryDetailParser {
|
||||
dates.add(matcher.group(1));
|
||||
}
|
||||
Elements elements = gnd.select("a");
|
||||
for (int i = 0; i< elements.size(); i++) {
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
Element element = elements.get(i);
|
||||
GalleryInfo gi = new GalleryInfo();
|
||||
GalleryDetailUrlParser.Result result = GalleryDetailUrlParser.parse(element.attr("href"));
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.util.List;
|
||||
|
||||
class A7ZipArchive implements Closeable {
|
||||
|
||||
private InArchive archive;
|
||||
private final InArchive archive;
|
||||
|
||||
private A7ZipArchive(InArchive archive) {
|
||||
this.archive = archive;
|
||||
@@ -84,9 +84,9 @@ class A7ZipArchive implements Closeable {
|
||||
|
||||
static class A7ZipArchiveEntry {
|
||||
|
||||
private InArchive archive;
|
||||
private int index;
|
||||
private String path;
|
||||
private final InArchive archive;
|
||||
private final int index;
|
||||
private final String path;
|
||||
|
||||
private A7ZipArchiveEntry(InArchive archive, int index, String path) {
|
||||
this.archive = archive;
|
||||
@@ -106,7 +106,7 @@ class A7ZipArchive implements Closeable {
|
||||
private static class UniRandomAccessFileInStream extends SeekableInputStream {
|
||||
|
||||
private final byte[] scratch = new byte[8];
|
||||
private UniRandomAccessFile file;
|
||||
private final UniRandomAccessFile file;
|
||||
|
||||
public UniRandomAccessFileInStream(UniRandomAccessFile file) {
|
||||
this.file = file;
|
||||
@@ -150,7 +150,7 @@ class A7ZipArchive implements Closeable {
|
||||
|
||||
private static class OutputStreamSequentialOutStream extends OutputStream {
|
||||
|
||||
private OutputStream stream;
|
||||
private final OutputStream stream;
|
||||
|
||||
public OutputStreamSequentialOutStream(OutputStream stream) {
|
||||
this.stream = stream;
|
||||
|
||||
@@ -47,8 +47,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
|
||||
private static final AtomicInteger sIdGenerator = new AtomicInteger();
|
||||
private static Comparator<A7ZipArchive.A7ZipArchiveEntry> naturalComparator = new Comparator<A7ZipArchive.A7ZipArchiveEntry>() {
|
||||
private NaturalComparator comparator = new NaturalComparator();
|
||||
private static final Comparator<A7ZipArchive.A7ZipArchiveEntry> naturalComparator = new Comparator<A7ZipArchive.A7ZipArchiveEntry>() {
|
||||
private final NaturalComparator comparator = new NaturalComparator();
|
||||
|
||||
@Override
|
||||
public int compare(A7ZipArchive.A7ZipArchiveEntry o1, A7ZipArchive.A7ZipArchiveEntry o2) {
|
||||
|
||||
@@ -47,10 +47,10 @@ public class DirGalleryProvider extends GalleryProvider2 implements Runnable {
|
||||
|
||||
private static final String TAG = DirGalleryProvider.class.getSimpleName();
|
||||
private static final AtomicInteger sIdGenerator = new AtomicInteger();
|
||||
private static FilenameFilter imageFilter =
|
||||
private static final FilenameFilter imageFilter =
|
||||
(dir, name) -> StringUtils.endsWith(name.toLowerCase(), SUPPORT_IMAGE_EXTENSIONS);
|
||||
private static Comparator<UniFile> naturalComparator = new Comparator<UniFile>() {
|
||||
private NaturalComparator comparator = new NaturalComparator();
|
||||
private static final Comparator<UniFile> naturalComparator = new Comparator<UniFile>() {
|
||||
private final NaturalComparator comparator = new NaturalComparator();
|
||||
|
||||
@Override
|
||||
public int compare(UniFile o1, UniFile o2) {
|
||||
|
||||
@@ -34,7 +34,7 @@ class Pipe {
|
||||
private boolean inClosed = false;
|
||||
private boolean outClosed = false;
|
||||
|
||||
private InputStream inputStream = new InputStream() {
|
||||
private final InputStream inputStream = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
synchronized (Pipe.this) {
|
||||
@@ -94,7 +94,7 @@ class Pipe {
|
||||
}
|
||||
};
|
||||
|
||||
private OutputStream outputStream = new OutputStream() {
|
||||
private final OutputStream outputStream = new OutputStream() {
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
synchronized (Pipe.this) {
|
||||
|
||||
@@ -152,7 +152,7 @@ public final class SpiderQueen implements Runnable {
|
||||
private volatile int[] mPageStateArray;
|
||||
// For download, when it go to mPageStateArray.size(), done
|
||||
private volatile int mDownloadPage = -1;
|
||||
private AtomicReference<String> showKey = new AtomicReference<>();
|
||||
private final AtomicReference<String> showKey = new AtomicReference<>();
|
||||
|
||||
private SpiderQueen(EhApplication application, @NonNull GalleryInfo galleryInfo) {
|
||||
mHttpClient = EhApplication.getOkHttpClient(application);
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
@@ -49,12 +48,13 @@ import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
@@ -78,6 +78,7 @@ import com.hippo.glgallery.SimpleAdapter;
|
||||
import com.hippo.glview.view.GLRootView;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.IoThreadPoolExecutor;
|
||||
import com.hippo.util.SystemUiHelper;
|
||||
import com.hippo.widget.ColorView;
|
||||
import com.hippo.yorozuya.AnimationUtils;
|
||||
@@ -112,8 +113,6 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
private static final long SLIDER_ANIMATION_DURING = 150;
|
||||
private static final long HIDE_SLIDER_DELAY = 3000;
|
||||
|
||||
private static final int WRITE_REQUEST_CODE = 43;
|
||||
private static final int REQUEST_WRITE_STORAGE = 1;
|
||||
private final ConcurrentPool<NotifyTask> mNotifyTaskPool = new ConcurrentPool<>(3);
|
||||
private String mAction;
|
||||
private String mFilename;
|
||||
@@ -186,6 +185,54 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
|
||||
private int mSavingPage = -1;
|
||||
|
||||
ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
result -> {
|
||||
if (result && mSavingPage != -1) {
|
||||
saveImage(mSavingPage);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mSavingPage = -1;
|
||||
});
|
||||
ActivityResultLauncher<String> saveImageToLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.CreateDocument(),
|
||||
uri -> {
|
||||
if (uri != null) {
|
||||
try {
|
||||
// grantUriPermission might throw RemoteException on MIUI
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
String filepath = getCacheDir() + "/" + mCacheFileName;
|
||||
File cachefile = new File(filepath);
|
||||
|
||||
ContentResolver resolver = getContentResolver();
|
||||
|
||||
IoThreadPoolExecutor.getInstance().execute(() -> {
|
||||
InputStream is = null;
|
||||
OutputStream os = null;
|
||||
try {
|
||||
is = new FileInputStream(cachefile);
|
||||
os = resolver.openOutputStream(uri);
|
||||
IOUtils.copy(is, os);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
IOUtils.closeQuietly(os);
|
||||
runOnUiThread(() -> Toast.makeText(GalleryActivity.this, getString(R.string.image_saved, uri.getPath()), Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
cachefile.delete();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
private void buildProvider() {
|
||||
if (mGalleryProvider != null) {
|
||||
return;
|
||||
@@ -779,7 +826,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
mSavingPage = page;
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE);
|
||||
requestStoragePermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -827,19 +874,6 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
Toast.makeText(this, getString(R.string.image_saved, realPath + File.separator + filename), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == REQUEST_WRITE_STORAGE) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && mSavingPage != -1) {
|
||||
saveImage(mSavingPage);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mSavingPage = -1;
|
||||
}
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
private void saveImageTo(int page) {
|
||||
if (null == mGalleryProvider) {
|
||||
return;
|
||||
@@ -856,60 +890,14 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
return;
|
||||
}
|
||||
mCacheFileName = filename;
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("image/*");
|
||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
intent.putExtra(Intent.EXTRA_TITLE, filename);
|
||||
try {
|
||||
startActivityForResult(intent, WRITE_REQUEST_CODE);
|
||||
saveImageToLauncher.launch(filename);
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
Toast.makeText(this, R.string.error_cant_find_activity, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
|
||||
super.onActivityResult(requestCode, resultCode, resultData);
|
||||
if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||
if (resultData != null) {
|
||||
Uri uri = resultData.getData();
|
||||
if (uri != null) {
|
||||
try {
|
||||
// grantUriPermission might throw RemoteException on MIUI
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
String filepath = getCacheDir() + "/" + mCacheFileName;
|
||||
File cachefile = new File(filepath);
|
||||
|
||||
InputStream is = null;
|
||||
OutputStream os = null;
|
||||
ContentResolver resolver = getContentResolver();
|
||||
|
||||
try {
|
||||
is = new FileInputStream(cachefile);
|
||||
os = resolver.openOutputStream(uri);
|
||||
IOUtils.copy(is, os);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
IOUtils.closeQuietly(os);
|
||||
}
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
cachefile.delete();
|
||||
|
||||
Toast.makeText(this, getString(R.string.image_saved, uri.getPath()), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showPageDialog(final int page) {
|
||||
Resources resources = GalleryActivity.this.getResources();
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(GalleryActivity.this);
|
||||
|
||||
@@ -320,7 +320,8 @@ public final class MainActivity extends StageActivity
|
||||
((EhApplication) getApplication()).recreate();
|
||||
Settings.putTheme(theme);
|
||||
});
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
||||
|
||||
updateProfile();
|
||||
|
||||
|
||||
@@ -30,11 +30,11 @@ import com.hippo.ehviewer.R;
|
||||
|
||||
public class SelectItemWithIconAdapter extends BaseAdapter {
|
||||
|
||||
private Context context;
|
||||
private LayoutInflater inflater;
|
||||
private final Context context;
|
||||
private final LayoutInflater inflater;
|
||||
|
||||
private CharSequence[] texts;
|
||||
private int[] icons;
|
||||
private final CharSequence[] texts;
|
||||
private final int[] icons;
|
||||
|
||||
public SelectItemWithIconAdapter(Context context, CharSequence[] texts, int[] icons) {
|
||||
int count = texts.length;
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
|
||||
package com.hippo.ehviewer.ui.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
@@ -35,6 +34,7 @@ import com.hippo.ehviewer.GetText;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.ui.scene.BaseScene;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.IoThreadPoolExecutor;
|
||||
import com.hippo.util.LogCat;
|
||||
import com.hippo.util.ReadableTime;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
@@ -51,91 +51,15 @@ import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class AdvancedFragment extends BasePreferenceFragment {
|
||||
|
||||
private static final int REQUEST_CODE_EXPORT = 1;
|
||||
private static final int REQUEST_CODE_IMPORT = 2;
|
||||
private static final int REQUEST_DUMP_LOGCAT = 3;
|
||||
|
||||
private static final String KEY_DUMP_LOGCAT = "dump_logcat";
|
||||
private static final String KEY_CLEAR_MEMORY_CACHE = "clear_memory_cache";
|
||||
private static final String KEY_APP_LANGUAGE = "app_language";
|
||||
private static final String KEY_IMPORT_DATA = "import_data";
|
||||
private static final String KEY_EXPORT_DATA = "export_data";
|
||||
|
||||
@Override
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.advanced_settings);
|
||||
|
||||
Preference dumpLogcat = findPreference(KEY_DUMP_LOGCAT);
|
||||
Preference clearMemoryCache = findPreference(KEY_CLEAR_MEMORY_CACHE);
|
||||
Preference appLanguage = findPreference(KEY_APP_LANGUAGE);
|
||||
Preference importData = findPreference(KEY_IMPORT_DATA);
|
||||
Preference exportData = findPreference(KEY_EXPORT_DATA);
|
||||
|
||||
dumpLogcat.setOnPreferenceClickListener(this);
|
||||
clearMemoryCache.setOnPreferenceClickListener(this);
|
||||
importData.setOnPreferenceClickListener(this);
|
||||
exportData.setOnPreferenceClickListener(this);
|
||||
|
||||
appLanguage.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
String key = preference.getKey();
|
||||
if (KEY_DUMP_LOGCAT.equals(key)) {
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("application/zip");
|
||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
intent.putExtra(Intent.EXTRA_TITLE, "log-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".zip");
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_DUMP_LOGCAT);
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
} else if (KEY_CLEAR_MEMORY_CACHE.equals(key)) {
|
||||
((EhApplication) getActivity().getApplication()).clearMemoryCache();
|
||||
Runtime.getRuntime().gc();
|
||||
showTip(R.string.settings_advanced_clear_memory_cache_done, BaseScene.LENGTH_SHORT);
|
||||
} else if (KEY_IMPORT_DATA.equals(key)) {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_CODE_IMPORT);
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
} else if (KEY_EXPORT_DATA.equals(key)) {
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("application/x-sqlite3");
|
||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
intent.putExtra(Intent.EXTRA_TITLE, ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".db");
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_CODE_EXPORT);
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(PreferenceGroup group, int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
if (requestCode == REQUEST_CODE_EXPORT) {
|
||||
if (data != null) {
|
||||
Uri uri = data.getData();
|
||||
ActivityResultLauncher<String> exportLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.CreateDocument(),
|
||||
uri -> {
|
||||
if (uri != null) {
|
||||
try {
|
||||
// grantUriPermission might throw RemoteException on MIUI
|
||||
@@ -149,7 +73,7 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
.setCancelable(false)
|
||||
.setView(R.layout.preference_dialog_task)
|
||||
.show();
|
||||
new Thread(() -> {
|
||||
IoThreadPoolExecutor.getInstance().execute(() -> {
|
||||
boolean success = EhDB.exportDB(requireActivity(), uri);
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
if (alertDialog.isShowing()) {
|
||||
@@ -161,49 +85,15 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
: GetText.getString(R.string.settings_advanced_export_data_failed),
|
||||
BaseScene.LENGTH_SHORT);
|
||||
});
|
||||
}).start();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
showTip(R.string.settings_advanced_export_data_failed, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (requestCode == REQUEST_CODE_IMPORT) {
|
||||
if (data != null) {
|
||||
Uri uri = data.getData();
|
||||
if (uri != null) {
|
||||
try {
|
||||
// grantUriPermission might throw RemoteException on MIUI
|
||||
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
AlertDialog alertDialog = new MaterialAlertDialogBuilder(requireActivity())
|
||||
.setCancelable(false)
|
||||
.setView(R.layout.preference_dialog_task)
|
||||
.show();
|
||||
new Thread(() -> {
|
||||
final String error = EhDB.importDB(requireActivity(), uri);
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
if (alertDialog.isShowing()) {
|
||||
alertDialog.dismiss();
|
||||
}
|
||||
if (null == error) {
|
||||
showTip(getString(R.string.settings_advanced_import_data_successfully), BaseScene.LENGTH_SHORT);
|
||||
} else {
|
||||
showTip(error, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
});
|
||||
}).start();
|
||||
} catch (Exception e) {
|
||||
showTip(e.getLocalizedMessage(), BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (requestCode == REQUEST_DUMP_LOGCAT) {
|
||||
if (data != null) {
|
||||
Uri uri = data.getData();
|
||||
});
|
||||
ActivityResultLauncher<String> dumpLogcatLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.CreateDocument(),
|
||||
uri -> {
|
||||
if (uri != null) {
|
||||
try {
|
||||
// grantUriPermission might throw RemoteException on MIUI
|
||||
@@ -246,10 +136,8 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
while ((count = origin.read(bytes, 0, bytes.length)) != -1) {
|
||||
out.write(bytes, 0, count);
|
||||
}
|
||||
if (origin != null) {
|
||||
origin.close();
|
||||
origin = null;
|
||||
}
|
||||
origin.close();
|
||||
origin = null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -282,9 +170,93 @@ public class AdvancedFragment extends BasePreferenceFragment {
|
||||
showTip(getString(R.string.settings_advanced_dump_logcat_failed), BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
});
|
||||
ActivityResultLauncher<String[]> importDataLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.OpenDocument(),
|
||||
uri -> {
|
||||
if (uri != null) {
|
||||
try {
|
||||
// grantUriPermission might throw RemoteException on MIUI
|
||||
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
AlertDialog alertDialog = new MaterialAlertDialogBuilder(requireActivity())
|
||||
.setCancelable(false)
|
||||
.setView(R.layout.preference_dialog_task)
|
||||
.show();
|
||||
IoThreadPoolExecutor.getInstance().execute(() -> {
|
||||
final String error = EhDB.importDB(requireActivity(), uri);
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
if (alertDialog.isShowing()) {
|
||||
alertDialog.dismiss();
|
||||
}
|
||||
if (null == error) {
|
||||
showTip(getString(R.string.settings_advanced_import_data_successfully), BaseScene.LENGTH_SHORT);
|
||||
} else {
|
||||
showTip(error, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (Exception e) {
|
||||
showTip(e.getLocalizedMessage(), BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.advanced_settings);
|
||||
|
||||
Preference dumpLogcat = findPreference(KEY_DUMP_LOGCAT);
|
||||
Preference clearMemoryCache = findPreference(KEY_CLEAR_MEMORY_CACHE);
|
||||
Preference appLanguage = findPreference(KEY_APP_LANGUAGE);
|
||||
Preference importData = findPreference(KEY_IMPORT_DATA);
|
||||
Preference exportData = findPreference(KEY_EXPORT_DATA);
|
||||
|
||||
dumpLogcat.setOnPreferenceClickListener(this);
|
||||
clearMemoryCache.setOnPreferenceClickListener(this);
|
||||
importData.setOnPreferenceClickListener(this);
|
||||
exportData.setOnPreferenceClickListener(this);
|
||||
|
||||
appLanguage.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
String key = preference.getKey();
|
||||
if (KEY_DUMP_LOGCAT.equals(key)) {
|
||||
try {
|
||||
dumpLogcatLauncher.launch("log-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".zip");
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
} else if (KEY_CLEAR_MEMORY_CACHE.equals(key)) {
|
||||
((EhApplication) requireContext().getApplicationContext()).clearMemoryCache();
|
||||
Runtime.getRuntime().gc();
|
||||
showTip(R.string.settings_advanced_clear_memory_cache_done, BaseScene.LENGTH_SHORT);
|
||||
} else if (KEY_IMPORT_DATA.equals(key)) {
|
||||
try {
|
||||
importDataLauncher.launch(new String[]{"*/*"});
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
} else if (KEY_EXPORT_DATA.equals(key)) {
|
||||
try {
|
||||
exportLauncher.launch(ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".db");
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
super.onActivityResult(group, requestCode, resultCode, data);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
package com.hippo.ehviewer.ui.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
@@ -40,6 +41,22 @@ public class DownloadFragment extends BasePreferenceFragment {
|
||||
@Nullable
|
||||
private Preference mDownloadLocation;
|
||||
|
||||
ActivityResultLauncher<Uri> pickImageDirLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.OpenDocumentTree(),
|
||||
treeUri -> {
|
||||
if (treeUri != null) {
|
||||
requireActivity().getContentResolver().takePersistableUriPermission(
|
||||
treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
UniFile uniFile = UniFile.fromTreeUri(getActivity(), treeUri);
|
||||
if (uniFile != null) {
|
||||
Settings.putDownloadLocation(uniFile);
|
||||
onUpdateDownloadLocation();
|
||||
} else {
|
||||
showTip(R.string.settings_download_cant_get_download_location,
|
||||
BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
@@ -87,44 +104,14 @@ public class DownloadFragment extends BasePreferenceFragment {
|
||||
}
|
||||
|
||||
private void openDirPickerL() {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE_DIR_L);
|
||||
pickImageDirLauncher.launch(null);
|
||||
} catch (Throwable e) {
|
||||
ExceptionUtils.throwIfFatal(e);
|
||||
showTip(R.string.error_cant_find_activity, BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_PICK_IMAGE_DIR_L: {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Uri treeUri = data.getData();
|
||||
if (treeUri != null) {
|
||||
requireActivity().getContentResolver().takePersistableUriPermission(
|
||||
treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
UniFile uniFile = UniFile.fromTreeUri(getActivity(), treeUri);
|
||||
if (uniFile != null) {
|
||||
Settings.putDownloadLocation(uniFile);
|
||||
onUpdateDownloadLocation();
|
||||
} else {
|
||||
showTip(R.string.settings_download_cant_get_download_location,
|
||||
BaseScene.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
String key = preference.getKey();
|
||||
|
||||
@@ -17,14 +17,12 @@
|
||||
package com.hippo.ehviewer.ui.scene;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
@@ -50,7 +50,6 @@ import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||
@@ -114,7 +113,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -48,7 +50,6 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
@@ -224,6 +225,10 @@ public final class GalleryListScene extends BaseScene
|
||||
private FavouriteStatusRouter.Listener mFavouriteStatusRouterListener;
|
||||
private boolean mIsTopList = false;
|
||||
|
||||
ActivityResultLauncher<String[]> selectImageLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.OpenDocument(),
|
||||
result -> mSearchLayout.setImageUri(result));
|
||||
|
||||
@Nullable
|
||||
private static String getSuitableTitleForUrlBuilder(
|
||||
Resources resources, ListUrlBuilder urlBuilder, boolean appName) {
|
||||
@@ -1421,11 +1426,7 @@ public final class GalleryListScene extends BaseScene
|
||||
|
||||
@Override
|
||||
public void onSelectImage() {
|
||||
Intent intent = new Intent();
|
||||
intent.setType("image/*");
|
||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
startActivityForResult(Intent.createChooser(intent,
|
||||
getString(R.string.select_image)), REQUEST_CODE_SELECT_IMAGE);
|
||||
selectImageLauncher.launch(new String[]{"image/*"});
|
||||
}
|
||||
|
||||
// SearchBarMover.Helper
|
||||
|
||||
@@ -31,7 +31,7 @@ import com.hippo.ehviewer.R;
|
||||
|
||||
public class DialogWebChromeClient extends WebChromeClient {
|
||||
|
||||
private Context context;
|
||||
private final Context context;
|
||||
|
||||
public DialogWebChromeClient(Context context) {
|
||||
this.context = context;
|
||||
|
||||
@@ -38,11 +38,11 @@ public class GalleryHeader extends ViewGroup {
|
||||
private View progress;
|
||||
private View clock;
|
||||
|
||||
private Rect batteryRect = new Rect();
|
||||
private Rect progressRect = new Rect();
|
||||
private Rect clockRect = new Rect();
|
||||
private final Rect batteryRect = new Rect();
|
||||
private final Rect progressRect = new Rect();
|
||||
private final Rect clockRect = new Rect();
|
||||
|
||||
private int[] location = new int[2];
|
||||
private final int[] location = new int[2];
|
||||
|
||||
private int lastX = 0;
|
||||
private int lastY = 0;
|
||||
|
||||
@@ -36,7 +36,7 @@ public abstract class GalleryInfoContentHelper extends ContentLayout.ContentHelp
|
||||
|
||||
@SuppressLint("UseSparseArrays")
|
||||
private Map<Long, GalleryInfo> map = new HashMap<>();
|
||||
private FavouriteStatusRouter.Listener listener;
|
||||
private final FavouriteStatusRouter.Listener listener;
|
||||
|
||||
public GalleryInfoContentHelper() {
|
||||
listener = (gid, slot) -> {
|
||||
|
||||
@@ -48,8 +48,8 @@ public class CookieRepository implements CookieJar {
|
||||
* verification).
|
||||
*/
|
||||
private static final Pattern VERIFY_AS_IP_ADDRESS = Pattern.compile("([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)");
|
||||
private CookieDatabase db;
|
||||
private Map<String, CookieSet> map;
|
||||
private final CookieDatabase db;
|
||||
private final Map<String, CookieSet> map;
|
||||
|
||||
public CookieRepository(Context context, String name) {
|
||||
db = new CookieDatabase(context, name);
|
||||
|
||||
@@ -33,7 +33,7 @@ import okhttp3.HttpUrl;
|
||||
|
||||
class CookieSet {
|
||||
|
||||
private Map<Key, Cookie> map = new HashMap<>();
|
||||
private final Map<Key, Cookie> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Adds a cookie to this {@code CookieSet}.
|
||||
@@ -72,9 +72,9 @@ class CookieSet {
|
||||
|
||||
static class Key {
|
||||
|
||||
private String name;
|
||||
private String domain;
|
||||
private String path;
|
||||
private final String name;
|
||||
private final String domain;
|
||||
private final String path;
|
||||
|
||||
public Key(Cookie cookie) {
|
||||
this.name = cookie.name();
|
||||
|
||||
@@ -591,11 +591,11 @@ class HtmlToSpannedConverter implements ContentHandler {
|
||||
sColorNameMap.put("yellowgreen", 0xFF9ACD32);
|
||||
}
|
||||
|
||||
private String mSource;
|
||||
private XMLReader mReader;
|
||||
private SpannableStringBuilder mSpannableStringBuilder;
|
||||
private Html.ImageGetter mImageGetter;
|
||||
private Html.TagHandler mTagHandler;
|
||||
private final String mSource;
|
||||
private final XMLReader mReader;
|
||||
private final SpannableStringBuilder mSpannableStringBuilder;
|
||||
private final Html.ImageGetter mImageGetter;
|
||||
private final Html.TagHandler mTagHandler;
|
||||
|
||||
public HtmlToSpannedConverter(
|
||||
String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler,
|
||||
@@ -1101,7 +1101,7 @@ class HtmlToSpannedConverter implements ContentHandler {
|
||||
}
|
||||
|
||||
private static class Header {
|
||||
private int mLevel;
|
||||
private final int mLevel;
|
||||
|
||||
public Header(int level) {
|
||||
mLevel = level;
|
||||
|
||||
@@ -14,7 +14,7 @@ public class PathNaturalComparator implements Comparator<String> {
|
||||
private static final boolean TYPE_SEPARATOR = false;
|
||||
private static final boolean TYPE_NORMAL = true;
|
||||
|
||||
private Comparator<String> naturalComparator = new NaturalComparator();
|
||||
private final Comparator<String> naturalComparator = new NaturalComparator();
|
||||
|
||||
private static int nextSegmentStart(String str, int index) {
|
||||
if (index >= str.length()) {
|
||||
|
||||
@@ -40,7 +40,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
|
||||
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator;
|
||||
|
||||
import com.hippo.android.resource.AttrResources;
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
Reference in new issue
Block a user