Move downloads to Environment downloads folder

This commit is contained in:
Ammar Githam 2021-04-02 01:42:21 +09:00
parent 24b5b4801f
commit 91c70b778a
18 changed files with 426 additions and 294 deletions

View File

@ -12,13 +12,13 @@ def getGitHash = { ->
}
android {
compileSdkVersion 29
compileSdkVersion 30
defaultConfig {
applicationId 'me.austinhuang.instagrabber'
minSdkVersion 21
targetSdkVersion 29
targetSdkVersion 30
versionCode 60
versionName '19.1.0'

View File

@ -33,7 +33,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import awais.instagrabber.databinding.ActivityCameraBinding;
import awais.instagrabber.utils.DirectoryUtils;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.PermissionUtils;
import awais.instagrabber.utils.Utils;
@ -74,7 +74,7 @@ public class CameraActivity extends BaseLanguageActivity {
setContentView(binding.getRoot());
Utils.transparentStatusBar(this, true, false);
displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
outputDirectory = DirectoryUtils.getOutputMediaDirectory(this, "Camera");
outputDirectory = DownloadUtils.getCameraDir();
cameraExecutor = Executors.newSingleThreadExecutor();
displayManager.registerDisplayListener(displayListener, null);
binding.viewFinder.post(() -> {

View File

@ -2,8 +2,11 @@ package awais.instagrabber.dialogs;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
@ -14,27 +17,25 @@ import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentTransaction;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import awais.instagrabber.databinding.DialogCreateBackupBinding;
import awais.instagrabber.utils.DirectoryChooser;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.ExportImportUtils;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
import static awais.instagrabber.utils.DownloadUtils.PERMS;
import static android.app.Activity.RESULT_OK;
public class CreateBackupDialogFragment extends DialogFragment {
private static final String TAG = CreateBackupDialogFragment.class.getSimpleName();
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
private static final SimpleDateFormat BACKUP_FILE_DATE_TIME_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
private static final int CREATE_FILE_REQUEST_CODE = 1;
private final OnResultListener onResultListener;
private DialogCreateBackupBinding binding;
@ -113,60 +114,113 @@ public class CreateBackupDialogFragment extends DialogFragment {
imm.hideSoftInputFromWindow(binding.etPassword.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN);
});
binding.btnSaveTo.setOnClickListener(v -> {
if (ContextCompat.checkSelfPermission(context, PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
showChooser(context);
} else {
requestPermissions(PERMS, STORAGE_PERM_REQUEST_CODE);
}
createFile();
// if (ContextCompat.checkSelfPermission(context, PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
// showChooser(context);
// } else {
// requestPermissions(PERMS, STORAGE_PERM_REQUEST_CODE);
// }
});
}
@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == STORAGE_PERM_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
final Context context = getContext();
if (context == null) return;
showChooser(context);
}
// if (requestCode == STORAGE_PERM_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// final Context context = getContext();
// if (context == null) return;
// showChooser(context);
// }
}
private void showChooser(@NonNull final Context context) {
final String folderPath = Utils.settingsHelper.getString(FOLDER_PATH);
@Override
public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
if (data == null || data.getData() == null) return;
if (resultCode != RESULT_OK || requestCode != CREATE_FILE_REQUEST_CODE) return;
final Context context = getContext();
if (context == null) return;
final Editable passwordText = binding.etPassword.getText();
final String password = binding.cbPassword.isChecked()
&& passwordText != null
&& !TextUtils.isEmpty(passwordText.toString())
? passwordText.toString().trim()
: null;
final DirectoryChooser directoryChooser = new DirectoryChooser()
.setInitialDirectory(folderPath)
.setInteractionListener(path -> {
final Date now = new Date();
final File file = new File(path, String.format("barinsta_%s.backup", BACKUP_FILE_DATE_TIME_FORMAT.format(now)));
int flags = 0;
if (binding.cbExportFavorites.isChecked()) {
flags |= ExportImportUtils.FLAG_FAVORITES;
}
if (binding.cbExportSettings.isChecked()) {
flags |= ExportImportUtils.FLAG_SETTINGS;
}
if (binding.cbExportLogins.isChecked()) {
flags |= ExportImportUtils.FLAG_COOKIES;
}
ExportImportUtils.exportData(context, flags, file, password, result -> {
if (onResultListener != null) {
onResultListener.onResult(result);
}
dismiss();
});
});
directoryChooser.setEnterTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
directoryChooser.setExitTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
directoryChooser.show(getChildFragmentManager(), "directory_chooser");
int flags = 0;
if (binding.cbExportFavorites.isChecked()) {
flags |= ExportImportUtils.FLAG_FAVORITES;
}
if (binding.cbExportSettings.isChecked()) {
flags |= ExportImportUtils.FLAG_SETTINGS;
}
if (binding.cbExportLogins.isChecked()) {
flags |= ExportImportUtils.FLAG_COOKIES;
}
ExportImportUtils.exportData(context, flags, data.getData(), password, result -> {
if (onResultListener != null) {
onResultListener.onResult(result);
}
dismiss();
});
// try (final OutputStream stream = context.getContentResolver().openOutputStream(data.getData())) {
// } catch (Exception e) {
// Log.e(TAG, "onActivityResult: ", e);
// }
}
// private void showChooser(@NonNull final Context context) {
// final String folderPath = Utils.settingsHelper.getString(FOLDER_PATH);
// final Editable passwordText = binding.etPassword.getText();
// final String password = binding.cbPassword.isChecked()
// && passwordText != null
// && !TextUtils.isEmpty(passwordText.toString())
// ? passwordText.toString().trim()
// : null;
// final DirectoryChooser directoryChooser = new DirectoryChooser()
// .setInitialDirectory(folderPath)
// .setInteractionListener(path -> {
// final Date now = new Date();
// final File file = new File(path, String.format("barinsta_%s.backup", BACKUP_FILE_DATE_TIME_FORMAT.format(now)));
// int flags = 0;
// if (binding.cbExportFavorites.isChecked()) {
// flags |= ExportImportUtils.FLAG_FAVORITES;
// }
// if (binding.cbExportSettings.isChecked()) {
// flags |= ExportImportUtils.FLAG_SETTINGS;
// }
// if (binding.cbExportLogins.isChecked()) {
// flags |= ExportImportUtils.FLAG_COOKIES;
// }
// ExportImportUtils.exportData(context, flags, file, password, result -> {
// if (onResultListener != null) {
// onResultListener.onResult(result);
// }
// dismiss();
// });
//
// });
// directoryChooser.setEnterTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// directoryChooser.setExitTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// directoryChooser.show(getChildFragmentManager(), "directory_chooser");
// }
private void createFile() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/octet-stream");
final Date now = new Date();
final String fileName = String.format("barinsta_%s.backup", BACKUP_FILE_DATE_TIME_FORMAT.format(now));
intent.putExtra(Intent.EXTRA_TITLE, fileName);
// Optionally, specify a URI for the directory that should be opened in
// the system file picker when your app creates the document.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Uri.fromFile(DownloadUtils.getDownloadDir()));
}
startActivityForResult(intent, CREATE_FILE_REQUEST_CODE);
}
public interface OnResultListener {
void onResult(boolean result);
}

View File

@ -1,12 +1,18 @@
package awais.instagrabber.dialogs;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -15,30 +21,28 @@ import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentTransaction;
import java.io.File;
import awais.instagrabber.databinding.DialogRestoreBackupBinding;
import awais.instagrabber.utils.DirectoryChooser;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.ExportImportUtils;
import awais.instagrabber.utils.PasswordUtils.IncorrectPasswordException;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
import static awais.instagrabber.utils.DownloadUtils.PERMS;
import static android.app.Activity.RESULT_OK;
public class RestoreBackupDialogFragment extends DialogFragment {
private static final String TAG = RestoreBackupDialogFragment.class.getSimpleName();
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
private static final int OPEN_FILE_REQUEST_CODE = 1;
private OnResultListener onResultListener;
private DialogRestoreBackupBinding binding;
private File file;
// private File file;
private boolean isEncrypted;
private Uri uri;
public RestoreBackupDialogFragment() {}
@ -83,18 +87,62 @@ public class RestoreBackupDialogFragment extends DialogFragment {
@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == STORAGE_PERM_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showChooser();
// if (requestCode == STORAGE_PERM_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// showChooser();
// }
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
if (data == null || data.getData() == null) return;
if (resultCode != RESULT_OK || requestCode != OPEN_FILE_REQUEST_CODE) return;
final Context context = getContext();
if (context == null) return;
isEncrypted = ExportImportUtils.isEncrypted(context, data.getData());
if (isEncrypted) {
binding.passwordGroup.setVisibility(View.VISIBLE);
binding.passwordGroup.post(() -> {
binding.etPassword.requestFocus();
binding.etPassword.post(() -> {
final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null) return;
imm.showSoftInput(binding.etPassword, InputMethodManager.SHOW_IMPLICIT);
});
binding.btnRestore.setEnabled(!TextUtils.isEmpty(binding.etPassword.getText()));
});
} else {
binding.passwordGroup.setVisibility(View.GONE);
binding.btnRestore.setEnabled(true);
}
uri = data.getData();
AppExecutors.getInstance().mainThread().execute(() -> {
Cursor c = null;
try {
String[] projection = {MediaStore.Files.FileColumns.DISPLAY_NAME};
final ContentResolver contentResolver = context.getContentResolver();
c = contentResolver.query(uri, projection, null, null, null);
if (c != null) {
while (c.moveToNext()) {
final String displayName = c.getString(0);
binding.filePath.setText(displayName);
}
}
} catch (Exception e) {
Log.e(TAG, "onActivityResult: ", e);
} finally {
if (c != null) {
c.close();
}
}
});
}
private void init() {
final Context context = getContext();
if (context == null) {
return;
}
if (context == null) return;
binding.btnRestore.setEnabled(false);
binding.btnRestore.setOnClickListener(v -> new Handler().post(() -> {
binding.btnRestore.setOnClickListener(v -> new Handler(Looper.getMainLooper()).post(() -> {
if (uri == null) return;
int flags = 0;
if (binding.cbFavorites.isChecked()) {
flags |= ExportImportUtils.FLAG_FAVORITES;
@ -111,7 +159,7 @@ public class RestoreBackupDialogFragment extends DialogFragment {
ExportImportUtils.importData(
context,
flags,
file,
uri,
!isEncrypted ? null : text.toString(),
result -> {
if (onResultListener != null) {
@ -137,45 +185,55 @@ public class RestoreBackupDialogFragment extends DialogFragment {
@Override
public void afterTextChanged(final Editable s) {}
});
if (ContextCompat.checkSelfPermission(context, PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
showChooser();
return;
}
requestPermissions(PERMS, STORAGE_PERM_REQUEST_CODE);
// if (ContextCompat.checkSelfPermission(context, PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
// showChooser();
// return;
// }
// requestPermissions(PERMS, STORAGE_PERM_REQUEST_CODE);
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{
// "application/pdf", // .pdf
// "application/vnd.oasis.opendocument.text", // .odt
// "text/plain" // .txt
// });
startActivityForResult(intent, OPEN_FILE_REQUEST_CODE);
}
private void showChooser() {
final String folderPath = Utils.settingsHelper.getString(FOLDER_PATH);
final Context context = getContext();
if (context == null) return;
final DirectoryChooser directoryChooser = new DirectoryChooser()
.setInitialDirectory(folderPath)
.setShowBackupFiles(true)
.setInteractionListener(file -> {
isEncrypted = ExportImportUtils.isEncrypted(file);
if (isEncrypted) {
binding.passwordGroup.setVisibility(View.VISIBLE);
binding.passwordGroup.post(() -> {
binding.etPassword.requestFocus();
binding.etPassword.post(() -> {
final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null) return;
imm.showSoftInput(binding.etPassword, InputMethodManager.SHOW_IMPLICIT);
});
binding.btnRestore.setEnabled(!TextUtils.isEmpty(binding.etPassword.getText()));
});
} else {
binding.passwordGroup.setVisibility(View.GONE);
binding.btnRestore.setEnabled(true);
}
this.file = file;
binding.filePath.setText(file.getAbsolutePath());
});
directoryChooser.setEnterTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
directoryChooser.setExitTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
directoryChooser.setOnCancelListener(this::dismiss);
directoryChooser.show(getChildFragmentManager(), "directory_chooser");
}
// private void showChooser() {
// final String folderPath = Utils.settingsHelper.getString(FOLDER_PATH);
// final Context context = getContext();
// if (context == null) return;
// final DirectoryChooser directoryChooser = new DirectoryChooser()
// .setInitialDirectory(folderPath)
// .setShowBackupFiles(true)
// .setInteractionListener(file -> {
// isEncrypted = ExportImportUtils.isEncrypted(file);
// if (isEncrypted) {
// binding.passwordGroup.setVisibility(View.VISIBLE);
// binding.passwordGroup.post(() -> {
// binding.etPassword.requestFocus();
// binding.etPassword.post(() -> {
// final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
// if (imm == null) return;
// imm.showSoftInput(binding.etPassword, InputMethodManager.SHOW_IMPLICIT);
// });
// binding.btnRestore.setEnabled(!TextUtils.isEmpty(binding.etPassword.getText()));
// });
// } else {
// binding.passwordGroup.setVisibility(View.GONE);
// binding.btnRestore.setEnabled(true);
// }
// this.file = file;
// binding.filePath.setText(file.getAbsolutePath());
// });
// directoryChooser.setEnterTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// directoryChooser.setExitTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// directoryChooser.setOnCancelListener(this::dismiss);
// directoryChooser.show(getChildFragmentManager(), "directory_chooser");
// }
public interface OnResultListener {
void onResult(boolean result);

View File

@ -74,9 +74,6 @@ import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
import static awais.instagrabber.utils.Utils.settingsHelper;
//import awaisomereport.LogCollector;
//import static awais.instagrabber.utils.Utils.logCollector;
public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "HashTagFragment";
private static final int STORAGE_PERM_REQUEST_CODE = 8020;

View File

@ -1,26 +1,14 @@
package awais.instagrabber.fragments.settings;
import android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreferenceCompat;
import com.google.android.material.switchmaterial.SwitchMaterial;
import awais.instagrabber.R;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DirectoryChooser;
import awais.instagrabber.utils.TextUtils;
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
import static awais.instagrabber.utils.Utils.settingsHelper;
public class DownloadsPreferencesFragment extends BasePreferencesFragment {
@Override
@ -28,7 +16,7 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
final Context context = getContext();
if (context == null) return;
screen.addPreference(getDownloadUserFolderPreference(context));
screen.addPreference(getSaveToCustomFolderPreference(context));
// screen.addPreference(getSaveToCustomFolderPreference(context));
}
private Preference getDownloadUserFolderPreference(@NonNull final Context context) {
@ -39,63 +27,63 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
return preference;
}
private Preference getSaveToCustomFolderPreference(@NonNull final Context context) {
return new SaveToCustomFolderPreference(context, (resultCallback) -> new DirectoryChooser()
.setInitialDirectory(settingsHelper.getString(FOLDER_PATH))
.setInteractionListener(file -> {
settingsHelper.putString(FOLDER_PATH, file.getAbsolutePath());
resultCallback.onResult(file.getAbsolutePath());
})
.show(getParentFragmentManager(), null));
}
// private Preference getSaveToCustomFolderPreference(@NonNull final Context context) {
// return new SaveToCustomFolderPreference(context, (resultCallback) -> new DirectoryChooser()
// .setInitialDirectory(settingsHelper.getString(FOLDER_PATH))
// .setInteractionListener(file -> {
// settingsHelper.putString(FOLDER_PATH, file.getAbsolutePath());
// resultCallback.onResult(file.getAbsolutePath());
// })
// .show(getParentFragmentManager(), null));
// }
public static class SaveToCustomFolderPreference extends Preference {
private AppCompatTextView customPathTextView;
private final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener;
private final String key;
public SaveToCustomFolderPreference(final Context context, final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener) {
super(context);
this.onSelectFolderButtonClickListener = onSelectFolderButtonClickListener;
key = Constants.FOLDER_SAVE_TO;
setLayoutResource(R.layout.pref_custom_folder);
setKey(key);
setTitle(R.string.save_to_folder);
setIconSpaceReserved(false);
}
@Override
public void onBindViewHolder(final PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final SwitchMaterial cbSaveTo = (SwitchMaterial) holder.findViewById(R.id.cbSaveTo);
final View buttonContainer = holder.findViewById(R.id.button_container);
customPathTextView = (AppCompatTextView) holder.findViewById(R.id.custom_path);
cbSaveTo.setOnCheckedChangeListener((buttonView, isChecked) -> {
settingsHelper.putBoolean(FOLDER_SAVE_TO, isChecked);
buttonContainer.setVisibility(isChecked ? View.VISIBLE : View.GONE);
final String customPath = settingsHelper.getString(FOLDER_PATH);
customPathTextView.setText(customPath);
});
final boolean savedToEnabled = settingsHelper.getBoolean(key);
holder.itemView.setOnClickListener(v -> cbSaveTo.toggle());
cbSaveTo.setChecked(savedToEnabled);
buttonContainer.setVisibility(savedToEnabled ? View.VISIBLE : View.GONE);
final AppCompatButton btnSaveTo = (AppCompatButton) holder.findViewById(R.id.btnSaveTo);
btnSaveTo.setOnClickListener(v -> {
if (onSelectFolderButtonClickListener == null) return;
onSelectFolderButtonClickListener.onClick(result -> {
if (TextUtils.isEmpty(result)) return;
customPathTextView.setText(result);
});
});
}
public interface ResultCallback {
void onResult(String result);
}
public interface OnSelectFolderButtonClickListener {
void onClick(ResultCallback resultCallback);
}
}
// public static class SaveToCustomFolderPreference extends Preference {
// private AppCompatTextView customPathTextView;
// private final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener;
// private final String key;
//
// public SaveToCustomFolderPreference(final Context context, final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener) {
// super(context);
// this.onSelectFolderButtonClickListener = onSelectFolderButtonClickListener;
// key = Constants.FOLDER_SAVE_TO;
// setLayoutResource(R.layout.pref_custom_folder);
// setKey(key);
// setTitle(R.string.save_to_folder);
// setIconSpaceReserved(false);
// }
//
// @Override
// public void onBindViewHolder(final PreferenceViewHolder holder) {
// super.onBindViewHolder(holder);
// final SwitchMaterial cbSaveTo = (SwitchMaterial) holder.findViewById(R.id.cbSaveTo);
// final View buttonContainer = holder.findViewById(R.id.button_container);
// customPathTextView = (AppCompatTextView) holder.findViewById(R.id.custom_path);
// cbSaveTo.setOnCheckedChangeListener((buttonView, isChecked) -> {
// settingsHelper.putBoolean(FOLDER_SAVE_TO, isChecked);
// buttonContainer.setVisibility(isChecked ? View.VISIBLE : View.GONE);
// final String customPath = settingsHelper.getString(FOLDER_PATH);
// customPathTextView.setText(customPath);
// });
// final boolean savedToEnabled = settingsHelper.getBoolean(key);
// holder.itemView.setOnClickListener(v -> cbSaveTo.toggle());
// cbSaveTo.setChecked(savedToEnabled);
// buttonContainer.setVisibility(savedToEnabled ? View.VISIBLE : View.GONE);
// final AppCompatButton btnSaveTo = (AppCompatButton) holder.findViewById(R.id.btnSaveTo);
// btnSaveTo.setOnClickListener(v -> {
// if (onSelectFolderButtonClickListener == null) return;
// onSelectFolderButtonClickListener.onClick(result -> {
// if (TextUtils.isEmpty(result)) return;
// customPathTextView.setText(result);
// });
// });
// }
//
// public interface ResultCallback {
// void onResult(String result);
// }
//
// public interface OnSelectFolderButtonClickListener {
// void onClick(ResultCallback resultCallback);
// }
// }
}

View File

@ -991,7 +991,7 @@ public final class ThreadManager {
@NonNull final Uri uri) {
try {
final Pair<Integer, Integer> dimensions = BitmapUtils.decodeDimensions(contentResolver, uri);
if (dimensions == null) {
if (dimensions == null || dimensions.first == null || dimensions.second == null) {
data.postValue(Resource.error("Decoding dimensions failed", null));
return;
}

View File

@ -236,10 +236,15 @@ public final class BitmapUtils {
@NonNull final Uri uri) throws FileNotFoundException {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(contentResolver.openInputStream(uri), null, options);
return (options.outWidth == -1 || options.outHeight == -1)
? null
: new Pair<>(options.outWidth, options.outHeight);
try (final InputStream inputStream = contentResolver.openInputStream(uri)) {
BitmapFactory.decodeStream(inputStream, null, options);
return (options.outWidth == -1 || options.outHeight == -1)
? null
: new Pair<>(options.outWidth, options.outHeight);
} catch (IOException e) {
Log.e(TAG, "decodeDimensions: ", e);
}
return null;
}
public static File convertToJpegAndSaveToFile(@NonNull final Bitmap bitmap, @Nullable final File file) throws IOException {

View File

@ -1,7 +1,5 @@
package awais.instagrabber.utils;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import java.io.File;
@ -10,8 +8,6 @@ import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import awais.instagrabber.R;
public class DirectoryUtils {
private static final Pattern DIR_SEPORATOR = Pattern.compile("/");
@ -73,22 +69,22 @@ public class DirectoryUtils {
return rv;
}
public static File getOutputMediaDirectory(final Context context, final String... dirs) {
if (context == null) return null;
final File[] externalMediaDirs = context.getExternalMediaDirs();
if (externalMediaDirs == null || externalMediaDirs.length == 0) return context.getFilesDir();
final File externalMediaDir = externalMediaDirs[0];
File subDir = new File(externalMediaDir, context.getString(R.string.app_name));
if (dirs != null) {
for (final String dir : dirs) {
subDir = new File(subDir, dir);
//noinspection ResultOfMethodCallIgnored
subDir.mkdirs();
}
}
if (!subDir.exists()) {
return context.getFilesDir();
}
return subDir;
}
// public static File getOutputMediaDirectory(final Context context, final String... dirs) {
// if (context == null) return null;
// final File[] externalMediaDirs = context.getExternalMediaDirs();
// if (externalMediaDirs == null || externalMediaDirs.length == 0) return context.getFilesDir();
// final File externalMediaDir = externalMediaDirs[0];
// File subDir = new File(externalMediaDir, context.getString(R.string.app_name));
// if (dirs != null) {
// for (final String dir : dirs) {
// subDir = new File(subDir, dir);
// //noinspection ResultOfMethodCallIgnored
// subDir.mkdirs();
// }
// }
// if (!subDir.exists()) {
// return context.getFilesDir();
// }
// return subDir;
// }
}

View File

@ -41,26 +41,54 @@ import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.VideoVersion;
import awais.instagrabber.workers.DownloadWorker;
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
public final class DownloadUtils {
private static final String TAG = "DownloadUtils";
private static final String TAG = DownloadUtils.class.getSimpleName();
public static final String WRITE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE;
public static final String[] PERMS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
public static final String DIR_BARINSTA = "Barinsta";
public static final String DIR_DOWNLOADS = "Downloads";
public static final String DIR_CAMERA = "Camera";
public static final String DIR_EDIT = "Edit";
@NonNull
private static File getDownloadDir() {
File dir = new File(Environment.getExternalStorageDirectory(), "Download");
if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
final String customPath = Utils.settingsHelper.getString(FOLDER_PATH);
if (!TextUtils.isEmpty(customPath)) {
dir = new File(customPath);
public static File getDownloadDir(final String... dirs) {
final File parent = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS);
File subDir = new File(parent, DIR_BARINSTA);
if (dirs != null) {
for (final String dir : dirs) {
subDir = new File(subDir, dir);
//noinspection ResultOfMethodCallIgnored
subDir.mkdirs();
}
}
return dir;
return subDir;
}
@NonNull
public static File getDownloadDir() {
// final File parent = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS);
// final File dir = new File(new File(parent, "barinsta"), "downloads");
// if (!dir.exists()) {
// final boolean mkdirs = dir.mkdirs();
// if (!mkdirs) {
// Log.e(TAG, "getDownloadDir: failed to create dir");
// }
// }
// if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
// final String customPath = Utils.settingsHelper.getString(FOLDER_PATH);
// if (!TextUtils.isEmpty(customPath)) {
// dir = new File(customPath);
// }
// }
return getDownloadDir(DIR_DOWNLOADS);
}
public static File getCameraDir() {
return getDownloadDir(DIR_CAMERA);
}
public static File getImageEditDir(final String sessionId) {
return getDownloadDir(DIR_EDIT, sessionId);
}
@Nullable

View File

@ -2,6 +2,7 @@ package awais.instagrabber.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.util.Base64;
import android.util.Log;
import android.util.Pair;
@ -20,9 +21,8 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
@ -55,14 +55,15 @@ public final class ExportImportUtils {
public static void importData(@NonNull final Context context,
@ExportImportFlags final int flags,
@NonNull final File file,
@NonNull final Uri uri,
final String password,
final FetchListener<Boolean> fetchListener) throws IncorrectPasswordException {
try (final FileInputStream fis = new FileInputStream(file)) {
final int configType = fis.read();
try (final InputStream stream = context.getContentResolver().openInputStream(uri)) {
if (stream == null) return;
final int configType = stream.read();
final StringBuilder builder = new StringBuilder();
int c;
while ((c = fis.read()) != -1) {
while ((c = stream.read()) != -1) {
builder.append((char) c);
}
if (configType == 'A') {
@ -80,8 +81,8 @@ public final class ExportImportUtils {
throw e;
} catch (final Exception e) {
if (fetchListener != null) fetchListener.onResult(false);
// if (logCollector != null)
// logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import::pass");
// if (logCollector != null)
// logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import::pass");
if (BuildConfig.DEBUG) Log.e(TAG, "Error importing backup", e);
}
} else if (configType == 'Z') {
@ -99,7 +100,7 @@ public final class ExportImportUtils {
throw e;
} catch (final Exception e) {
if (fetchListener != null) fetchListener.onResult(false);
// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import");
// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import");
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
}
}
@ -122,7 +123,7 @@ public final class ExportImportUtils {
if (fetchListener != null) fetchListener.onResult(true);
} catch (final Exception e) {
if (fetchListener != null) fetchListener.onResult(false);
// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "importJson");
// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "importJson");
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
}
}
@ -212,9 +213,11 @@ public final class ExportImportUtils {
}
}
public static boolean isEncrypted(final File file) {
try (final FileInputStream fis = new FileInputStream(file)) {
final int configType = fis.read();
public static boolean isEncrypted(@NonNull final Context context,
@NonNull final Uri uri) {
try (final InputStream stream = context.getContentResolver().openInputStream(uri)) {
if (stream == null) return false;
final int configType = stream.read();
if (configType == 'A') {
return true;
}
@ -226,7 +229,7 @@ public final class ExportImportUtils {
public static void exportData(@NonNull final Context context,
@ExportImportFlags final int flags,
@NonNull final File filePath,
@NonNull final Uri uri,
final String password,
final FetchListener<Boolean> fetchListener) {
getExportString(flags, context, exportString -> {
@ -241,25 +244,30 @@ public final class ExportImportUtils {
exportBytes = PasswordUtils.enc(exportString, bytes);
} catch (final Exception e) {
if (fetchListener != null) fetchListener.onResult(false);
// if (logCollector != null)
// logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::isPass");
// if (logCollector != null)
// logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::isPass");
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
}
} else {
exportBytes = Base64.encode(exportString.getBytes(), Base64.DEFAULT | Base64.NO_WRAP | Base64.NO_PADDING);
}
if (exportBytes != null && exportBytes.length > 1) {
try (final FileOutputStream fos = new FileOutputStream(filePath)) {
fos.write(isPass ? 'A' : 'Z');
fos.write(exportBytes);
try (final OutputStream stream = context.getContentResolver().openOutputStream(uri)) {
if (stream == null) return;
stream.write(isPass ? 'A' : 'Z');
stream.write(exportBytes);
if (fetchListener != null) fetchListener.onResult(true);
} catch (final Exception e) {
} catch (Exception e) {
if (fetchListener != null) fetchListener.onResult(false);
// if (logCollector != null)
// logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::notPass");
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
// if (logCollector != null)
// logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::notPass");
Log.e(TAG, "exportData", e);
}
} else if (fetchListener != null) fetchListener.onResult(false);
return;
}
if (fetchListener != null) {
fetchListener.onResult(false);
}
});
}
@ -324,7 +332,7 @@ public final class ExportImportUtils {
}, AppExecutors.getInstance().tasksThread());
return;
} catch (final Exception e) {
// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getExportString");
// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getExportString");
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
}
callback.onCreated(null);
@ -373,9 +381,9 @@ public final class ExportImportUtils {
jsonArray.put(jsonObject);
}
} catch (Exception e) {
// if (logCollector != null) {
// logCollector.appendException(e, LogFile.UTILS_EXPORT, "getFavorites");
// }
// if (logCollector != null) {
// logCollector.appendException(e, LogFile.UTILS_EXPORT, "getFavorites");
// }
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error exporting favorites", e);
}
@ -409,9 +417,9 @@ public final class ExportImportUtils {
jsonArray.put(jsonObject);
}
} catch (Exception e) {
// if (logCollector != null) {
// logCollector.appendException(e, LogFile.UTILS_EXPORT, "getCookies");
// }
// if (logCollector != null) {
// logCollector.appendException(e, LogFile.UTILS_EXPORT, "getCookies");
// }
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error exporting accounts", e);
}

View File

@ -2,7 +2,6 @@ package awais.instagrabber.utils;
import android.net.Uri;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.Nullable;
@ -76,10 +75,10 @@ public final class ResponseBodyUtils {
if (lastIndexMain >= 0) return sources[lastIndexMain];
else if (lastIndexBase >= 0) return sources[lastIndexBase];
} catch (final Exception e) {
// if (Utils.logCollector != null)
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "getHighQualityPost",
// new Pair<>("resourcesNull", resources == null),
// new Pair<>("isVideo", isVideo));
// if (Utils.logCollector != null)
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "getHighQualityPost",
// new Pair<>("resourcesNull", resources == null),
// new Pair<>("isVideo", isVideo));
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
}
return null;
@ -94,9 +93,9 @@ public final class ResponseBodyUtils {
src = getHighQualityPost(resources.getJSONObject("image_versions2").getJSONArray("candidates"), false, true, false);
if (src == null) return resources.getString("display_url");
} catch (final Exception e) {
// if (Utils.logCollector != null)
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "getHighQualityImage",
// new Pair<>("resourcesNull", resources == null));
// if (Utils.logCollector != null)
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "getHighQualityImage",
// new Pair<>("resourcesNull", resources == null));
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
}
return src;
@ -732,8 +731,8 @@ public final class ResponseBodyUtils {
final List<MediaCandidate> candidates = new ArrayList<MediaCandidate>();
if (feedItem.has("display_resources") || feedItem.has("thumbnail_resources")) {
final JSONArray displayResources = feedItem.has("display_resources")
? feedItem.getJSONArray("display_resources")
: feedItem.getJSONArray("thumbnail_resources");
? feedItem.getJSONArray("display_resources")
: feedItem.getJSONArray("thumbnail_resources");
for (int i = 0; i < displayResources.length(); i++) {
final JSONObject displayResource = displayResources.getJSONObject(i);
candidates.add(new MediaCandidate(
@ -1090,9 +1089,10 @@ public final class ResponseBodyUtils {
if (imageVersions2 == null) return null;
final List<MediaCandidate> candidates = imageVersions2.getCandidates();
if (candidates == null || candidates.isEmpty()) return null;
final List<MediaCandidate> sortedCandidates = candidates.stream()
final List<MediaCandidate> sortedCandidates = candidates
.stream()
.sorted((c1, c2) -> Integer.compare(c2.getWidth(), c1.getWidth()))
.filter(c -> c.getWidth() < type.getValue())
// .filter(c -> c.getWidth() < type.getValue())
.collect(Collectors.toList());
final MediaCandidate candidate = sortedCandidates.get(0);
if (candidate == null) return null;

View File

@ -50,19 +50,15 @@ import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
//import javax.crypto.Mac;
//import javax.crypto.spec.SecretKeySpec;
import awais.instagrabber.R;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.enums.FavoriteType;
//import awaisomereport.LogCollector;
public final class Utils {
private static final String TAG = "Utils";
private static final int VIDEO_CACHE_MAX_BYTES = 10 * 1024 * 1024;
// public static LogCollector logCollector;
// public static LogCollector logCollector;
public static SettingsHelper settingsHelper;
public static boolean sessionVolumeFull = false;
public static final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
@ -93,34 +89,34 @@ public final class Utils {
}
public static Map<String, String> sign(final Map<String, Object> form) {
// final String signed = sign(Constants.SIGNATURE_KEY, new JSONObject(form).toString());
// if (signed == null) {
// return null;
// }
// final String signed = sign(Constants.SIGNATURE_KEY, new JSONObject(form).toString());
// if (signed == null) {
// return null;
// }
final Map<String, String> map = new HashMap<>();
// map.put("ig_sig_key_version", Constants.SIGNATURE_VERSION);
// map.put("signed_body", signed);
// map.put("ig_sig_key_version", Constants.SIGNATURE_VERSION);
// map.put("signed_body", signed);
map.put("signed_body", "SIGNATURE." + new JSONObject(form).toString());
return map;
}
// public static String sign(final String key, final String message) {
// try {
// final Mac hasher = Mac.getInstance("HmacSHA256");
// hasher.init(new SecretKeySpec(key.getBytes(), "HmacSHA256"));
// byte[] hash = hasher.doFinal(message.getBytes());
// final StringBuilder hexString = new StringBuilder();
// for (byte b : hash) {
// final String hex = Integer.toHexString(0xff & b);
// if (hex.length() == 1) hexString.append('0');
// hexString.append(hex);
// }
// return hexString.toString() + "." + message;
// } catch (Exception e) {
// Log.e(TAG, "Error signing", e);
// return null;
// }
// }
// public static String sign(final String key, final String message) {
// try {
// final Mac hasher = Mac.getInstance("HmacSHA256");
// hasher.init(new SecretKeySpec(key.getBytes(), "HmacSHA256"));
// byte[] hash = hasher.doFinal(message.getBytes());
// final StringBuilder hexString = new StringBuilder();
// for (byte b : hash) {
// final String hex = Integer.toHexString(0xff & b);
// if (hex.length() == 1) hexString.append('0');
// hexString.append(hex);
// }
// return hexString.toString() + "." + message;
// } catch (Exception e) {
// Log.e(TAG, "Error signing", e);
// return null;
// }
// }
public static String getMimeType(@NonNull final Uri uri, final ContentResolver contentResolver) {
String mimeType;

View File

@ -34,7 +34,7 @@ import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DirectoryUtils;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.MediaController;
import awais.instagrabber.utils.MediaUtils;
import awais.instagrabber.utils.TextUtils;
@ -72,7 +72,7 @@ public class DirectThreadViewModel extends AndroidViewModel {
throw new IllegalArgumentException("User is not logged in!");
}
contentResolver = application.getContentResolver();
recordingsDir = DirectoryUtils.getOutputMediaDirectory(application, "Recordings");
recordingsDir = DownloadUtils.getDownloadDir("Recordings");
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
threadManager = messagesManager.getThreadManager(threadId, pending, currentUser, contentResolver);
threadManager.fetchPendingRequests();

View File

@ -24,7 +24,7 @@ import awais.instagrabber.fragments.imageedit.filters.filters.Filter;
import awais.instagrabber.fragments.imageedit.filters.properties.Property;
import awais.instagrabber.models.SavedImageEditState;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.DirectoryUtils;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.SerializablePair;
import jp.co.cyberagent.android.gpuimage.GPUImage;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter;
@ -56,7 +56,7 @@ public class ImageEditViewModel extends AndroidViewModel {
public ImageEditViewModel(final Application application) {
super(application);
sessionId = SIMPLE_DATE_FORMAT.format(new Date());
outputDir = DirectoryUtils.getOutputMediaDirectory(application, "Edit", sessionId);
outputDir = DownloadUtils.getImageEditDir(sessionId);
destinationFile = new File(outputDir, RESULT + ".jpg");
destinationUri = Uri.fromFile(destinationFile);
cropDestinationUri = Uri.fromFile(new File(outputDir, CROP + ".jpg"));

View File

@ -69,5 +69,5 @@
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="16dp"
android:text="@string/create_backup" />
android:text="@string/backup" />
</LinearLayout>

View File

@ -127,7 +127,7 @@
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="16dp"
android:text="@string/restore_backup"
android:text="@string/restore"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/bottom_password_divider" />

View File

@ -477,4 +477,6 @@
<string name="crash_report_title">Select an email app to send crash logs</string>
<string name="copy_caption">Copy caption</string>
<string name="copy_reply">Copy reply</string>
<string name="restore">Restore</string>
<string name="backup">Backup</string>
</resources>