1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-16 11:47:29 +00:00

Remove read/write storage permissions.

Add an activity to select directory.
This commit is contained in:
Ammar Githam 2021-04-04 23:53:10 +09:00
parent 7577e82ac1
commit 9b691a453e
24 changed files with 649 additions and 337 deletions

View File

@ -4,8 +4,8 @@
package="awais.instagrabber">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-->
<!--<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />-->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<!--<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />-->
@ -133,6 +133,7 @@
<activity
android:name=".utils.ProcessPhoenix"
android:theme="@style/Theme.AppCompat.Translucent" />
<activity android:name=".activities.DirectorySelectActivity" />
<provider
android:name="androidx.core.content.FileProvider"

View File

@ -14,7 +14,6 @@ import java.text.SimpleDateFormat;
import java.util.UUID;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.LocaleUtils;
import awais.instagrabber.utils.SettingsHelper;
import awais.instagrabber.utils.TextUtils;
@ -27,8 +26,6 @@ import static awais.instagrabber.utils.Utils.clipboardManager;
import static awais.instagrabber.utils.Utils.datetimeParser;
import static awais.instagrabber.utils.Utils.settingsHelper;
//import awaisomereport.LogCollector;
//import static awais.instagrabber.utils.Utils.logCollector;
public final class InstaGrabberApplication extends Application {
private static final String TAG = "InstaGrabberApplication";
@ -90,6 +87,5 @@ public final class InstaGrabberApplication extends Application {
if (TextUtils.isEmpty(settingsHelper.getString(Constants.DEVICE_UUID))) {
settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString());
}
DownloadUtils.init(this);
}
}

View File

@ -1,6 +1,5 @@
package awais.instagrabber.activities;
import android.Manifest;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
@ -14,10 +13,8 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import awais.instagrabber.R;
import awais.instagrabber.asyncs.PostFetcher;
@ -74,11 +71,11 @@ public final class DirectDownload extends AppCompatActivity {
}
private synchronized void checkPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
doDownload();
return;
}
ActivityCompat.requestPermissions(this, DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// ActivityCompat.requestPermissions(this, DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override

View File

@ -0,0 +1,128 @@
package awais.instagrabber.activities;
import android.content.Intent;
import android.content.UriPermission;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import awais.instagrabber.databinding.ActivityDirectorySelectBinding;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.Utils;
public class DirectorySelectActivity extends BaseLanguageActivity {
private static final String TAG = DirectorySelectActivity.class.getSimpleName();
public static final int SELECT_DIR_REQUEST_CODE = 1090;
private Uri initialUri;
private ActivityDirectorySelectBinding binding;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityDirectorySelectBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.selectDir.setOnClickListener(v -> openDirectoryChooser());
setInitialUri();
}
private void setInitialUri() {
AppExecutors.getInstance().mainThread().execute(() -> {
final Intent intent = getIntent();
if (intent == null) {
setMessage();
return;
}
final Parcelable initialUriParcelable = intent.getParcelableExtra(Constants.EXTRA_INITIAL_URI);
if (!(initialUriParcelable instanceof Uri)) {
setMessage();
return;
}
initialUri = (Uri) initialUriParcelable;
setMessage();
});
}
private void setMessage() {
if (initialUri == null) {
// default message
binding.message.setText("Select a directory which Barinsta will use for downloads and temp files");
return;
}
if (!initialUri.toString().startsWith("content")) {
final String message = String.format("Android has changed the way apps can access files and directories on storage.\n\n" +
"Please re-select the directory '%s' after clicking the button below",
initialUri.toString());
binding.message.setText(message);
return;
}
final List<UriPermission> existingPermissions = getContentResolver().getPersistedUriPermissions();
final boolean anyMatch = existingPermissions.stream().anyMatch(uriPermission -> uriPermission.getUri().equals(initialUri));
if (!anyMatch) {
// permission revoked message
final String message = "Permissions for the previously selected directory '%s' were revoked by the system.\n\n" +
"Re-select the directory or select a new directory.";
final DocumentFile documentFile = DocumentFile.fromSingleUri(this, initialUri);
String path;
try {
path = URLDecoder.decode(initialUri.toString(), StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
path = initialUri.toString();
}
if (documentFile != null) {
try {
final File file = Utils.getDocumentFileRealPath(this, documentFile);
if (file != null) {
path = file.getAbsolutePath();
}
} catch (Exception e) {
Log.e(TAG, "setMessage: ", e);
}
}
binding.message.setText(String.format(message, path));
}
}
private void openDirectoryChooser() {
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && initialUri != null) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri);
}
startActivityForResult(intent, SELECT_DIR_REQUEST_CODE);
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != SELECT_DIR_REQUEST_CODE) return;
if (resultCode != RESULT_OK) {
// Show error
return;
}
if (data == null || data.getData() == null) {
// show error
return;
}
try {
Utils.setupSelectedDir(this, data);
} catch (Exception e) {
// show error
}
}
}

View File

@ -79,6 +79,7 @@ import awais.instagrabber.services.DMSyncAlarmReceiver;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.FlavorTown;
import awais.instagrabber.utils.IntentUtils;
import awais.instagrabber.utils.TextUtils;
@ -92,6 +93,7 @@ import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import static awais.instagrabber.utils.Constants.EXTRA_INITIAL_URI;
import static awais.instagrabber.utils.NavigationExtensions.setupWithNavController;
import static awais.instagrabber.utils.Utils.settingsHelper;
@ -134,6 +136,16 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
try {
DownloadUtils.init(this);
} catch (DownloadUtils.ReselectDocumentTreeException e) {
super.onCreate(savedInstanceState);
final Intent intent = new Intent(this, DirectorySelectActivity.class);
intent.putExtra(EXTRA_INITIAL_URI, e.getInitialUri());
startActivity(intent);
finish();
return;
}
RetrofitFactory.setup(this);
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
@ -221,7 +233,9 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
@Override
protected void onSaveInstanceState(@NonNull final Bundle outState) {
outState.putString(FIRST_FRAGMENT_GRAPH_INDEX_KEY, String.valueOf(firstFragmentGraphIndex));
if (binding != null) {
outState.putString(LAST_SELECT_NAV_MENU_ID, String.valueOf(binding.bottomNavView.getSelectedItemId()));
}
super.onSaveInstanceState(outState);
}
@ -265,7 +279,9 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
Log.e(TAG, "onDestroy: ", e);
}
unbindActivityCheckerService();
try {
RetrofitFactory.getInstance().destroy();
} catch (Exception ignored) {}
}
@Override

View File

@ -213,7 +213,7 @@ public class CreateBackupDialogFragment extends DialogFragment {
// 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, DownloadUtils.getDownloadDir().getUri());
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, DownloadUtils.getBackupsDir().getUri());
}
startActivityForResult(intent, CREATE_FILE_REQUEST_CODE);

View File

@ -15,7 +15,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.documentfile.provider.DocumentFile;
import androidx.fragment.app.DialogFragment;
@ -109,11 +108,11 @@ public class ProfilePicDialogFragment extends DialogFragment {
binding.download.setOnClickListener(v -> {
final Context context = getContext();
if (context == null) return;
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
// if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
downloadProfilePicture();
return;
}
requestPermissions(DownloadUtils.PERMS, 8020);
// return;
// }
// requestPermissions(DownloadUtils.PERMS, 8020);
});
}

View File

@ -27,7 +27,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
@ -65,9 +64,6 @@ import awais.instagrabber.utils.Utils;
import awais.instagrabber.webservices.CollectionService;
import awais.instagrabber.webservices.ServiceCallback;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
public class CollectionPostsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "CollectionPostsFragment";
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
@ -105,12 +101,12 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
if (CollectionPostsFragment.this.selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(CollectionPostsFragment.this.selectedFeedModels));
binding.posts.endSelection();
return true;
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
// return true;
// }
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
}
return false;
}
@ -140,13 +136,13 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext();
if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return;
}
downloadFeedModel = feedModel;
downloadChildPosition = -1;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// downloadFeedModel = feedModel;
// downloadChildPosition = -1;
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override
@ -288,8 +284,7 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
if (item.getItemId() == R.id.layout) {
showPostsLayoutPreferences();
return true;
}
else if (item.getItemId() == R.id.delete) {
} else if (item.getItemId() == R.id.delete) {
final Context context = getContext();
new AlertDialog.Builder(context)
.setTitle(R.string.delete_collection)
@ -309,15 +304,13 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
Log.e(TAG, "Error deleting collection", t);
try {
Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
}
catch(final Throwable e) {}
} catch (final Throwable e) {}
}
});
})
.setNegativeButton(R.string.cancel, null)
.show();
}
else if (item.getItemId() == R.id.edit) {
} else if (item.getItemId() == R.id.edit) {
final Context context = getContext();
final EditText input = new EditText(context);
new AlertDialog.Builder(context)
@ -339,8 +332,7 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
Log.e(TAG, "Error editing collection", t);
try {
Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
}
catch(final Throwable e) {}
} catch (final Throwable e) {}
}
});
})

View File

@ -24,7 +24,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
@ -70,8 +69,6 @@ import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService;
import awais.instagrabber.webservices.TagsService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
import static awais.instagrabber.utils.Utils.settingsHelper;
public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
@ -121,13 +118,13 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (HashTagFragment.this.selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(HashTagFragment.this.selectedFeedModels));
binding.posts.endSelection();
return true;
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
return true;
// }
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
// return true;
}
return false;
}
@ -157,13 +154,13 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext();
if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return;
}
downloadFeedModel = feedModel;
downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// downloadFeedModel = feedModel;
// downloadChildPosition = childPosition;
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override
@ -400,8 +397,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
try {
Toast.makeText(getContext(), R.string.error_loading_hashtag, Toast.LENGTH_SHORT).show();
binding.swipeRefreshLayout.setEnabled(false);
}
catch (Exception ignored) {}
} catch (Exception ignored) {}
return;
}
setTitle();
@ -438,7 +434,8 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
return;
}
hashtagDetailsBinding.btnFollowTag.setText(R.string.unfollow);
hashtagDetailsBinding.btnFollowTag.setChipIconResource(R.drawable.ic_outline_person_add_disabled_24);
hashtagDetailsBinding.btnFollowTag
.setChipIconResource(R.drawable.ic_outline_person_add_disabled_24);
}
@Override

View File

@ -22,7 +22,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
@ -66,13 +65,8 @@ import awais.instagrabber.webservices.LocationService;
import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService;
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 LocationFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "LocationFragment";
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
@ -118,12 +112,12 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
if (LocationFragment.this.selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(LocationFragment.this.selectedFeedModels));
binding.posts.endSelection();
return true;
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
// }
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
}
return false;
}
@ -153,13 +147,13 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext();
if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return;
}
downloadFeedModel = feedModel;
downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// downloadFeedModel = feedModel;
// downloadChildPosition = childPosition;
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override
@ -399,8 +393,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
try {
Toast.makeText(getContext(), R.string.error_loading_location, Toast.LENGTH_SHORT).show();
binding.swipeRefreshLayout.setEnabled(false);
}
catch (Exception ignored) {}
} catch (Exception ignored) {}
return;
}
setTitle();

View File

@ -43,7 +43,6 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.PermissionChecker;
import androidx.core.view.ViewCompat;
import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.DialogFragment;
@ -100,9 +99,7 @@ import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import awais.instagrabber.viewmodels.PostViewV2ViewModel;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
import static awais.instagrabber.utils.Utils.settingsHelper;
public class PostViewV2Fragment extends SharedElementTransitionDialogFragment implements EditTextDialogFragment.EditTextDialogFragmentCallback {
@ -622,11 +619,11 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
private void setupDownload() {
binding.download.setOnClickListener(v -> {
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, viewModel.getMedia(), sliderPosition);
return;
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
});
binding.download.setOnLongClickListener(v -> {
Utils.displayToastAboveView(context, v, getString(R.string.action_download));

View File

@ -18,7 +18,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
@ -45,8 +44,6 @@ import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
import static awais.instagrabber.utils.Utils.settingsHelper;
public final class SavedViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
@ -86,12 +83,12 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
if (SavedViewerFragment.this.selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(SavedViewerFragment.this.selectedFeedModels));
binding.posts.endSelection();
return true;
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
// return true;
// }
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
}
return false;
}
@ -121,13 +118,13 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext();
if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return;
}
downloadFeedModel = feedModel;
downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// downloadFeedModel = feedModel;
// downloadChildPosition = childPosition;
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override

View File

@ -29,8 +29,6 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.GestureDetectorCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModel;
@ -210,10 +208,10 @@ public class StoryViewerFragment extends Fragment {
if (context == null) return false;
int itemId = item.getItemId();
if (itemId == R.id.action_download) {
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED)
// if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED)
downloadStory();
else
ActivityCompat.requestPermissions(requireActivity(), DownloadUtils.PERMS, 8020);
// else
// ActivityCompat.requestPermissions(requireActivity(), DownloadUtils.PERMS, 8020);
return true;
}
if (itemId == R.id.action_dms) {

View File

@ -23,7 +23,6 @@ import androidx.activity.OnBackPressedDispatcher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
@ -51,17 +50,14 @@ import awais.instagrabber.databinding.FragmentTopicPostsBinding;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.fragments.main.DiscoverFragmentDirections;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.repositories.responses.discover.TopicCluster;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.discover.TopicCluster;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.Utils;
import awais.instagrabber.webservices.DiscoverService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
private static final int STORAGE_PERM_REQUEST_CODE_FOR_SELECTION = 8030;
@ -97,12 +93,12 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
if (TopicPostsFragment.this.selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(TopicPostsFragment.this.selectedFeedModels));
binding.posts.endSelection();
return true;
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
// }
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
}
return false;
}
@ -132,13 +128,13 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext();
if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return;
}
downloadFeedModel = feedModel;
downloadChildPosition = -1;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// downloadFeedModel = feedModel;
// downloadChildPosition = -1;
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override

View File

@ -30,7 +30,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
@ -1337,13 +1336,13 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
return;
}
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
// if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
DownloadUtils.download(context, media);
Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
return;
}
tempMedia = media;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// tempMedia = media;
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@NonNull

View File

@ -19,7 +19,6 @@ import androidx.activity.OnBackPressedDispatcher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
@ -55,9 +54,6 @@ import awais.instagrabber.viewmodels.FeedStoriesViewModel;
import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "FeedFragment";
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
@ -123,13 +119,13 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext();
if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return;
}
downloadFeedModel = feedModel;
downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// downloadFeedModel = feedModel;
// downloadChildPosition = childPosition;
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override
@ -204,13 +200,13 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
if (FeedFragment.this.selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(FeedFragment.this.selectedFeedModels));
binding.feedRecyclerView.endSelection();
return true;
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
return true;
// }
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
// return true;
}
return false;
}

View File

@ -28,7 +28,6 @@ import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
@ -98,9 +97,7 @@ import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService;
import awais.instagrabber.webservices.UserService;
import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG;
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "ProfileFragment";
@ -164,13 +161,13 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (ProfileFragment.this.selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.download(context, ImmutableList.copyOf(ProfileFragment.this.selectedFeedModels));
binding.postsRecyclerView.endSelection();
return true;
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
return true;
// }
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE_FOR_SELECTION);
// return true;
}
return false;
}
@ -200,13 +197,13 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
public void onDownloadClick(final Media feedModel, final int childPosition) {
final Context context = getContext();
if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
// if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
DownloadUtils.showDownloadDialog(context, feedModel, childPosition);
return;
}
downloadFeedModel = feedModel;
downloadChildPosition = childPosition;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
// return;
// }
// downloadFeedModel = feedModel;
// downloadChildPosition = childPosition;
// requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override

View File

@ -1,13 +1,11 @@
package awais.instagrabber.fragments.settings;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.documentfile.provider.DocumentFile;
@ -21,15 +19,14 @@ import com.google.android.material.switchmaterial.SwitchMaterial;
import awais.instagrabber.R;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import static android.app.Activity.RESULT_OK;
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 {
private static final String TAG = DownloadsPreferencesFragment.class.getSimpleName();
private static final int SELECT_DIR_REQUEST_CODE = 1;
private SaveToCustomFolderPreference.ResultCallback resultCallback;
@Override
@ -37,7 +34,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));
screen.addPreference(getPrependUsernameToFilenamePreference(context));
}
@ -49,41 +46,63 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
return preference;
}
private Preference getSaveToCustomFolderPreference(@NonNull final Context context) {
return new SaveToCustomFolderPreference(context, (resultCallback) -> {
// Choose a directory using the system's file picker.
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, SELECT_DIR_REQUEST_CODE);
this.resultCallback = resultCallback;
// private Preference getSaveToCustomFolderPreference(@NonNull final Context context) {
// return new SaveToCustomFolderPreference(context, checked -> {
// try {
// DownloadUtils.init(context);
// } catch (DownloadUtils.ReselectDocumentTreeException e) {
// if (!checked) return;
// startDocumentSelector(e.getInitialUri());
// } catch (Exception e) {
// Log.e(TAG, "getSaveToCustomFolderPreference: ", e);
// }
// }, (resultCallback) -> {
// // Choose a directory using the system's file picker.
// startDocumentSelector(null);
// this.resultCallback = resultCallback;
//
// // new DirectoryChooser()
// // .setInitialDirectory(settingsHelper.getString(FOLDER_PATH))
// // .setInteractionListener(file -> {
// // settingsHelper.putString(FOLDER_PATH, file.getAbsolutePath());
// // resultCallback.onResult(file.getAbsolutePath());
// // })
// // .show(getParentFragmentManager(), null);
// });
// }
// new DirectoryChooser()
// .setInitialDirectory(settingsHelper.getString(FOLDER_PATH))
// .setInteractionListener(file -> {
// settingsHelper.putString(FOLDER_PATH, file.getAbsolutePath());
// resultCallback.onResult(file.getAbsolutePath());
// })
// .show(getParentFragmentManager(), null);
});
}
// private void startDocumentSelector(final Uri initialUri) {
// final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && initialUri != null) {
// intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri);
// }
// startActivityForResult(intent, SELECT_DIR_REQUEST_CODE);
// }
@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 != SELECT_DIR_REQUEST_CODE) return;
final Context context = getContext();
if (context == null) return;
final Uri dirUri = data.getData();
Log.d(TAG, "onActivityResult: " + dirUri);
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
context.getContentResolver().takePersistableUriPermission(dirUri, takeFlags);
final DocumentFile root = DocumentFile.fromTreeUri(context, dirUri);
settingsHelper.putString(FOLDER_PATH, data.getData().toString());
if (resultCallback != null) {
resultCallback.onResult(root.getName());
resultCallback = null;
}
// Log.d(TAG, "onActivityResult: " + root);
}
// @Override
// public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
// if (requestCode != SELECT_DIR_REQUEST_CODE) return;
// final Context context = getContext();
// if (context == null) return;
// if (resultCode != RESULT_OK) {
// try {
// DownloadUtils.init(context, true);
// } catch (Exception ignored) {}
// return;
// }
// if (data == null || data.getData() == null) return;
// Utils.setupSelectedDir(context, data);
// if (resultCallback != null) {
// try {
// final DocumentFile root = DocumentFile.fromTreeUri(context, data.getData());
// resultCallback.onResult(Utils.getDocumentFileRealPath(context, root).getAbsolutePath());
// } catch (Exception e) {
// Log.e(TAG, "onActivityResult: ", e);
// }
// resultCallback = null;
// }
// // Log.d(TAG, "onActivityResult: " + root);
// }
private Preference getPrependUsernameToFilenamePreference(@NonNull final Context context) {
final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context);
@ -95,11 +114,15 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
public static class SaveToCustomFolderPreference extends Preference {
private AppCompatTextView customPathTextView;
private final OnSaveToChangeListener onSaveToChangeListener;
private final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener;
private final String key;
public SaveToCustomFolderPreference(final Context context, final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener) {
public SaveToCustomFolderPreference(final Context context,
final OnSaveToChangeListener onSaveToChangeListener,
final OnSelectFolderButtonClickListener onSelectFolderButtonClickListener) {
super(context);
this.onSaveToChangeListener = onSaveToChangeListener;
this.onSelectFolderButtonClickListener = onSelectFolderButtonClickListener;
key = FOLDER_SAVE_TO;
setLayoutResource(R.layout.pref_custom_folder);
@ -117,8 +140,21 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
cbSaveTo.setOnCheckedChangeListener((buttonView, isChecked) -> {
settingsHelper.putBoolean(FOLDER_SAVE_TO, isChecked);
buttonContainer.setVisibility(isChecked ? View.VISIBLE : View.GONE);
final String customPath = settingsHelper.getString(FOLDER_PATH);
final Context context = getContext();
String customPath = settingsHelper.getString(FOLDER_PATH);
if (!TextUtils.isEmpty(customPath) && customPath.startsWith("content") && context != null) {
final Uri uri = Uri.parse(customPath);
final DocumentFile documentFile = DocumentFile.fromSingleUri(context, uri);
try {
customPath = Utils.getDocumentFileRealPath(context, documentFile).getAbsolutePath();
} catch (Exception e) {
Log.e(TAG, "onBindViewHolder: ", e);
}
}
customPathTextView.setText(customPath);
if (onSaveToChangeListener != null) {
onSaveToChangeListener.onChange(isChecked);
}
});
final boolean savedToEnabled = settingsHelper.getBoolean(key);
holder.itemView.setOnClickListener(v -> cbSaveTo.toggle());
@ -141,5 +177,9 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
public interface OnSelectFolderButtonClickListener {
void onClick(ResultCallback resultCallback);
}
public interface OnSaveToChangeListener {
void onChange(boolean checked);
}
}
}

View File

@ -123,4 +123,6 @@ public final class Constants {
public static final String DM_THREAD_ACTION_EXTRA_THREAD_TITLE = "thread_title";
public static final String X_IG_APP_ID = "936619743392459";
public static final String EXTRA_INITIAL_URI = "initial_uri";
}

View File

@ -3,7 +3,6 @@ package awais.instagrabber.utils;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
@ -11,19 +10,14 @@ import android.os.FileObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
@ -95,15 +89,15 @@ public final class DirectoryChooser extends DialogFragment {
if (context == null) context = getContext();
if (context == null) context = getActivity();
if (context == null) return;
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) != PackageManager.PERMISSION_GRANTED) {
final String text = "Storage permissions denied!";
if (container == null) {
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
} else {
Snackbar.make(container, text, BaseTransientBottomBar.LENGTH_LONG).show();
}
dismiss();
}
// if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) != PackageManager.PERMISSION_GRANTED) {
// final String text = "Storage permissions denied!";
// if (container == null) {
// Toast.makeText(context, text, Toast.LENGTH_LONG).show();
// } else {
// Snackbar.make(container, text, BaseTransientBottomBar.LENGTH_LONG).show();
// }
// dismiss();
// }
final View.OnClickListener clickListener = v -> {
if (v == binding.btnConfirm) {
if (interactionListener != null && isValidFile(selectedDir))

View File

@ -1,9 +1,9 @@
package awais.instagrabber.utils;
import android.Manifest;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.UriPermission;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.util.Log;
@ -49,32 +49,65 @@ import static awais.instagrabber.utils.Constants.FOLDER_PATH;
public final class 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};
private static final String DIR_BARINSTA = "Barinsta";
// private static final String DIR_BARINSTA = "Barinsta";
private static final String DIR_DOWNLOADS = "Downloads";
private static final String DIR_CAMERA = "Camera";
private static final String DIR_EDIT = "Edit";
private static final String TEMP_DIR = "Temp";
private static final String DIR_RECORDINGS = "Recordings";
private static final String DIR_TEMP = "Temp";
private static final String DIR_BACKUPS = "Backups";
// public static final String WRITE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE;
// public static final String[] PERMS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
private static DocumentFile root;
// private static DocumentFile DOWNLOADS_DIR_FILE;
public static void init(@NonNull final Context context) {
// if (!Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) return;
public static void init(@NonNull final Context context) throws ReselectDocumentTreeException {
// if (DOWNLOADS_DIR_FILE == null) {
// final Uri uri = Utils.getSafUris(context, new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS))[0];
// DOWNLOADS_DIR_FILE = DocumentFile.fromTreeUri(context, uri);
// }
// if (!Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
// root = DOWNLOADS_DIR_FILE; // DocumentFile.fromFile(DOWNLOADS_DIR_FILE);
// return;
// }
final String customPath = Utils.settingsHelper.getString(FOLDER_PATH);
if (TextUtils.isEmpty(customPath)) return;
// dir = new File(customPath);
root = DocumentFile.fromTreeUri(context, Uri.parse(customPath));
if (TextUtils.isEmpty(customPath)) {
throw new ReselectDocumentTreeException();
// root = DOWNLOADS_DIR_FILE; // DocumentFile.fromFile(DOWNLOADS_DIR_FILE);
// return;
}
if (!customPath.startsWith("content")) {
// if (customPath.equals(DOWNLOADS_DIR_FILE.getAbsolutePath())) {
// throw new ReselectDocumentTreeException();
// }
// reselect the folder in selector view
throw new ReselectDocumentTreeException(Uri.parse(customPath));
}
final Uri uri = Uri.parse(customPath);
final List<UriPermission> existingPermissions = context.getContentResolver().getPersistedUriPermissions();
if (existingPermissions.isEmpty()) {
// reselect the folder in selector view
throw new ReselectDocumentTreeException(uri);
}
final boolean anyMatch = existingPermissions.stream().anyMatch(uriPermission -> uriPermission.getUri().equals(uri));
if (!anyMatch) {
// reselect the folder in selector view
throw new ReselectDocumentTreeException(uri);
}
root = DocumentFile.fromTreeUri(context, uri);
Log.d(TAG, "init: " + root);
// final File parent = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
// final DocumentFile documentFile = DocumentFile.fromFile(parent);
// Log.d(TAG, "init: " + documentFile);
}
@Nullable
public static DocumentFile getDownloadDir(final String... dirs) {
// final File parent = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS);
// File subDir = new File(parent, DIR_BARINSTA);
if (root == null) {
return null;
}
DocumentFile subDir = root;
if (dirs != null) {
for (final String dir : dirs) {
@ -87,7 +120,7 @@ public final class DownloadUtils {
return subDir;
}
@NonNull
@Nullable
public static DocumentFile getDownloadDir() {
// final File parent = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS);
// final File dir = new File(new File(parent, "barinsta"), "downloads");
@ -106,14 +139,26 @@ public final class DownloadUtils {
return getDownloadDir(DIR_DOWNLOADS);
}
@Nullable
public static DocumentFile getCameraDir() {
return getDownloadDir(DIR_CAMERA);
}
@Nullable
public static DocumentFile getImageEditDir(final String sessionId) {
return getDownloadDir(DIR_EDIT, sessionId);
}
@Nullable
public static DocumentFile getRecordingsDir() {
return getDownloadDir(DIR_RECORDINGS);
}
@Nullable
public static DocumentFile getBackupsDir() {
return getDownloadDir(DIR_BACKUPS);
}
// @Nullable
// private static DocumentFile getDownloadDir(@NonNull final Context context, @Nullable final String username) {
// return getDownloadDir(context, username, false);
@ -156,9 +201,9 @@ public final class DownloadUtils {
}
private static DocumentFile getTempDir() {
DocumentFile file = root.findFile(TEMP_DIR);
DocumentFile file = root.findFile(DIR_TEMP);
if (file == null) {
file = root.createDirectory(TEMP_DIR);
file = root.createDirectory(DIR_TEMP);
}
return file;
}
@ -202,7 +247,7 @@ public final class DownloadUtils {
return getDownloadSavePaths(paths, postId, "", displayUrl, username);
}
private static Pair<List<String>, String> getDownloadChildSaveFile(final List<String> paths,
private static Pair<List<String>, String> getDownloadChildSavePaths(final List<String> paths,
final String postId,
final int childPosition,
final String url,
@ -231,9 +276,9 @@ public final class DownloadUtils {
return new Pair<>(paths, mimeType);
}
public static DocumentFile getTempFile() {
return getTempFile(null, null);
}
// public static DocumentFile getTempFile() {
// return getTempFile(null, null);
// }
public static DocumentFile getTempFile(final String fileName, final String extension) {
final DocumentFile dir = getTempDir();
@ -317,8 +362,8 @@ public final class DownloadUtils {
final Media child = sliderItems.get(i);
if (child == null) continue;
final String url = ResponseBodyUtils.getImageUrl(child);
final Pair<List<String>, String> file = getDownloadChildSaveFile(userFolderPaths, media.getCode(), i + 1, url, "");
final Pair<List<String>, String> usernameFile = getDownloadChildSaveFile(userFolderPaths, media.getCode(), i + 1, url, username);
final Pair<List<String>, String> file = getDownloadChildSavePaths(userFolderPaths, media.getCode(), i + 1, url, "");
final Pair<List<String>, String> usernameFile = getDownloadChildSavePaths(userFolderPaths, media.getCode(), i + 1, url, username);
checkList.add(checkPathExists(context, file.first) || checkPathExists(context, usernameFile.first));
}
break;
@ -329,6 +374,7 @@ public final class DownloadUtils {
private static boolean checkPathExists(@NonNull final Context context,
@NonNull final List<String> paths) {
if (root == null) return false;
final String joined = android.text.TextUtils.join("/", paths);
final Uri userFolderUri = DocumentsContract.buildDocumentUriUsingTree(root.getUri(), joined);
final DocumentFile userFolder = DocumentFile.fromSingleUri(context, userFolderUri);
@ -455,7 +501,7 @@ public final class DownloadUtils {
final String usernamePrepend = Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_PREPEND_USER_NAME) && mediaUser != null
? mediaUser.getUsername()
: "";
final Pair<List<String>, String> pair = getDownloadChildSaveFile(userFolderPaths, media.getCode(), i + 1, url,
final Pair<List<String>, String> pair = getDownloadChildSavePaths(userFolderPaths, media.getCode(), i + 1, url,
usernamePrepend);
final DocumentFile file = createFile(pair);
if (file == null) continue;
@ -469,7 +515,9 @@ public final class DownloadUtils {
download(context, map);
}
@Nullable
private static DocumentFile createFile(@NonNull final Pair<List<String>, String> pair) {
if (root == null) return null;
if (pair.first == null || pair.second == null) return null;
DocumentFile dir = root;
final List<String> first = pair.first;
@ -558,4 +606,21 @@ public final class DownloadUtils {
WorkManager.getInstance(context)
.enqueue(downloadWorkRequest);
}
public static class ReselectDocumentTreeException extends Exception {
private final Uri initialUri;
public ReselectDocumentTreeException() {
initialUri = null;
}
public ReselectDocumentTreeException(final Uri initialUri) {
this.initialUri = initialUri;
}
public Uri getInitialUri() {
return initialUri;
}
}
}

View File

@ -36,6 +36,7 @@ import android.widget.Toast;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
@ -70,6 +71,8 @@ import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.Tab;
import awais.instagrabber.models.enums.FavoriteType;
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
public final class Utils {
private static final String TAG = "Utils";
private static final int VIDEO_CACHE_MAX_BYTES = 10 * 1024 * 1024;
@ -520,7 +523,8 @@ public final class Utils {
callback);
}
private static File getDocumentFileRealPath(Context context, DocumentFile documentFile)
public static File getDocumentFileRealPath(@NonNull final Context context,
@NonNull final DocumentFile documentFile)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
final String docId = DocumentsContract.getDocumentId(documentFile.getUri());
final String[] split = docId.split(":");
@ -530,18 +534,19 @@ public final class Utils {
return new File(Environment.getExternalStorageDirectory(), split[1]);
} else {
if (volumes == null) {
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method getVolumeListMethod = sm.getClass().getMethod("getVolumeList");
final StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
if (sm == null) return null;
final Method getVolumeListMethod = sm.getClass().getMethod("getVolumeList");
volumes = (Object[]) getVolumeListMethod.invoke(sm);
}
if (volumes == null) return null;
for (Object volume : volumes) {
Method getUuidMethod = volume.getClass().getMethod("getUuid");
String uuid = (String) getUuidMethod.invoke(volume);
final Method getUuidMethod = volume.getClass().getMethod("getUuid");
final String uuid = (String) getUuidMethod.invoke(volume);
if (uuid != null && uuid.equalsIgnoreCase(type)) {
Method getPathMethod = volume.getClass().getMethod("getPath");
String path = (String) getPathMethod.invoke(volume);
final Method getPathMethod = volume.getClass().getMethod("getPath");
final String path = (String) getPathMethod.invoke(volume);
return new File(path, split[1]);
}
}
@ -549,4 +554,72 @@ public final class Utils {
return null;
}
public static void setupSelectedDir(@NonNull final Context context,
@NonNull final Intent intent) throws DownloadUtils.ReselectDocumentTreeException {
final Uri dirUri = intent.getData();
Log.d(TAG, "onActivityResult: " + dirUri);
if (dirUri == null) return;
final int takeFlags = intent.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
context.getContentResolver().takePersistableUriPermission(dirUri, takeFlags);
settingsHelper.putString(FOLDER_PATH, dirUri.toString());
// re-init DownloadUtils
DownloadUtils.init(context);
}
/**
* Ing.N.Nyerges 2019 V2.0
* <p>
* Storage Access Framework(SAF) Uri's creator from File (java.IO),
* for removable external storages
*
* @param context Application Context
* @param file File path + file name
* @return Uri[]:
* uri[0] = SAF TREE Uri
* uri[1] = SAF DOCUMENT Uri
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static Uri[] getSafUris(Context context, File file) {
Uri[] uri = new Uri[2];
String scheme = "content";
String authority = "com.android.externalstorage.documents";
// Separate each element of the File path
// File format: "/storage/XXXX-XXXX/sub-folder1/sub-folder2..../filename"
// (XXXX-XXXX is external removable number
String[] ele = file.getPath().split(File.separator);
// ele[0] = not used (empty)
// ele[1] = not used (storage name)
// ele[2] = storage number
// ele[3 to (n-1)] = folders
// ele[n] = file name
// Construct folders strings using SAF format
StringBuilder folders = new StringBuilder();
if (ele.length > 4) {
folders.append(ele[3]);
for (int i = 4; i < ele.length - 1; ++i) folders.append("%2F").append(ele[i]);
}
String common = ele[2] + "%3A" + folders.toString();
// Construct TREE Uri
Uri.Builder builder = new Uri.Builder();
builder.scheme(scheme);
builder.authority(authority);
builder.encodedPath("/tree/" + common);
uri[0] = builder.build();
// Construct DOCUMENT Uri
builder = new Uri.Builder();
builder.scheme(scheme);
builder.authority(authority);
if (ele.length > 4) common = common + "%2F";
builder.encodedPath("/document/" + common + file.getName());
uri[1] = builder.build();
return uri;
}
}

View File

@ -72,7 +72,7 @@ public class DirectThreadViewModel extends AndroidViewModel {
throw new IllegalArgumentException("User is not logged in!");
}
contentResolver = application.getContentResolver();
recordingsDir = DownloadUtils.getDownloadDir("Recordings");
recordingsDir = DownloadUtils.getRecordingsDir();
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
threadManager = messagesManager.getThreadManager(threadId, pending, currentUser, contentResolver);
threadManager.fetchPendingRequests();

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title" />
<com.google.android.material.button.MaterialButton
android:id="@+id/select_dir"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Select Directory"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/message"
app:layout_constraintVertical_bias="1" />
</androidx.constraintlayout.widget.ConstraintLayout>