Browse Source

Fix direct downloading and delete action when there are multiple image notifications

renovate/org.robolectric-robolectric-4.x
Ammar Githam 4 years ago
parent
commit
450dbba6de
  1. 27
      app/src/main/AndroidManifest.xml
  2. 149
      app/src/main/java/awais/instagrabber/activities/DirectDownload.java
  3. 149
      app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java
  4. 117
      app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java
  5. 7
      app/src/main/java/awais/instagrabber/services/DeleteImageIntentService.java
  6. 4
      app/src/main/res/layout/activity_direct.xml
  7. 21
      app/src/main/res/layout/dialog_direct.xml
  8. 15
      app/src/main/res/values/styles.xml

27
app/src/main/AndroidManifest.xml

@ -71,22 +71,7 @@
android:taskAffinity="awais.instagrabber.errorreport" android:taskAffinity="awais.instagrabber.errorreport"
android:theme="@android:style/Theme.DeviceDefault.Dialog" /> android:theme="@android:style/Theme.DeviceDefault.Dialog" />
<activity <activity
android:name=".directdownload.MultiDirectDialog"
android:allowEmbedded="false"
android:allowTaskReparenting="false"
android:autoRemoveFromRecents="true"
android:clearTaskOnLaunch="true"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:documentLaunchMode="never"
android:excludeFromRecents="true"
android:finishOnTaskLaunch="true"
android:launchMode="singleTask"
android:lockTaskMode="never"
android:noHistory="false"
android:taskAffinity="awais.instagrabber.multidialog"
android:theme="@style/FlyingGayDialog" />
<activity
android:name=".directdownload.DirectDownload"
android:name=".activities.DirectDownload"
android:allowEmbedded="false" android:allowEmbedded="false"
android:allowTaskReparenting="false" android:allowTaskReparenting="false"
android:autoRemoveFromRecents="true" android:autoRemoveFromRecents="true"
@ -100,7 +85,7 @@
android:launchMode="singleTask" android:launchMode="singleTask"
android:lockTaskMode="never" android:lockTaskMode="never"
android:noHistory="false" android:noHistory="false"
android:theme="@style/CompletelyTransparent">
android:theme="@style/Theme.AppCompat.Translucent">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEARCH" /> <action android:name="android.intent.action.SEARCH" />
@ -139,7 +124,11 @@
android:resource="@xml/provider_paths" /> android:resource="@xml/provider_paths" />
</provider> </provider>
<service android:name=".services.ActivityCheckerService" />
<service android:name=".services.DeleteImageIntentService" />
<service
android:name=".services.ActivityCheckerService"
android:exported="false" />
<service
android:name=".services.DeleteImageIntentService"
android:exported="false" />
</application> </application>
</manifest> </manifest>

149
app/src/main/java/awais/instagrabber/activities/DirectDownload.java

@ -0,0 +1,149 @@
package awais.instagrabber.activities;
import android.Manifest;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
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;
import awais.instagrabber.interfaces.FetchListener;
import awais.instagrabber.models.FeedModel;
import awais.instagrabber.models.IntentModel;
import awais.instagrabber.models.enums.IntentModelType;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.IntentUtils;
import awais.instagrabber.utils.TextUtils;
public final class DirectDownload extends AppCompatActivity {
private static final int NOTIFICATION_ID = 1900000000;
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
private boolean contextFound = false;
private Intent intent;
private Context context;
private NotificationManagerCompat notificationManager;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_direct);
}
@Override
public void onWindowAttributesChanged(final WindowManager.LayoutParams params) {
super.onWindowAttributesChanged(params);
if (!contextFound) {
intent = getIntent();
context = getApplicationContext();
if (intent != null && context != null) {
contextFound = true;
checkPermissions();
}
}
}
@Override
public Resources getResources() {
if (!contextFound) {
intent = getIntent();
context = getApplicationContext();
if (intent != null && context != null) {
contextFound = true;
checkPermissions();
}
}
return super.getResources();
}
private synchronized void checkPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
doDownload();
return;
}
ActivityCompat.requestPermissions(this, DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
final boolean granted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (requestCode == STORAGE_PERM_REQUEST_CODE && granted) {
doDownload();
}
}
private synchronized void doDownload() {
notificationManager = NotificationManagerCompat.from(getApplicationContext());
final Intent intent = getIntent();
final String action = intent.getAction();
if (TextUtils.isEmpty(action) || Intent.ACTION_MAIN.equals(action)) {
finish();
return;
}
boolean error = true;
String data = null;
final Bundle extras = intent.getExtras();
if (extras != null) {
final Object extraData = extras.get(Intent.EXTRA_TEXT);
if (extraData != null) {
error = false;
data = extraData.toString();
}
}
if (error) {
final Uri intentData = intent.getData();
if (intentData != null) data = intentData.toString();
}
if (data == null || TextUtils.isEmpty(data)) {
finish();
return;
}
final IntentModel model = IntentUtils.parseUrl(data);
if (model == null || model.getType() != IntentModelType.POST) {
finish();
return;
}
final String text = model.getText();
new PostFetcher(text, new FetchListener<FeedModel>() {
@Override
public void doBefore() {
if (notificationManager == null) return;
final Notification fetchingPostNotification = new NotificationCompat.Builder(getApplicationContext(), Constants.DOWNLOAD_CHANNEL_ID)
.setCategory(NotificationCompat.CATEGORY_STATUS)
.setSmallIcon(R.drawable.ic_download)
.setAutoCancel(false)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setContentText(getString(R.string.direct_download_loading))
.build();
notificationManager.notify(NOTIFICATION_ID, fetchingPostNotification);
}
@Override
public void onResult(final FeedModel result) {
if (notificationManager != null) notificationManager.cancel(NOTIFICATION_ID);
if (result == null) {
finish();
return;
}
DownloadUtils.download(getApplicationContext(), result);
finish();
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}

149
app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java

@ -1,149 +0,0 @@
package awais.instagrabber.directdownload;
import android.Manifest;
import android.app.Activity;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.WindowManager;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import java.util.Collections;
import awais.instagrabber.R;
import awais.instagrabber.asyncs.PostFetcher;
import awais.instagrabber.interfaces.FetchListener;
import awais.instagrabber.models.FeedModel;
import awais.instagrabber.models.IntentModel;
import awais.instagrabber.models.enums.DownloadMethod;
import awais.instagrabber.models.enums.IntentModelType;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.IntentUtils;
import awais.instagrabber.utils.TextUtils;
public final class DirectDownload extends Activity {
private boolean isFound = false;
private Intent intent;
private Context context;
private NotificationManagerCompat notificationManager;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
notificationManager = NotificationManagerCompat.from(getApplicationContext());
}
@Override
public void onWindowAttributesChanged(final WindowManager.LayoutParams params) {
super.onWindowAttributesChanged(params);
if (!isFound) {
intent = getIntent();
context = getApplicationContext();
if (intent != null && context != null) {
isFound = true;
checkIntent();
}
}
}
@Override
public Resources getResources() {
if (!isFound) {
intent = getIntent();
context = getApplicationContext();
if (intent != null && context != null) {
isFound = true;
checkIntent();
}
}
return super.getResources();
}
private synchronized void checkIntent() {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
doDownload();
else {
final Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, R.string.direct_download_perms_ask, Toast.LENGTH_LONG).show();
handler.removeCallbacks(this);
}
});
ActivityCompat.requestPermissions(this, DownloadUtils.PERMS, 8020);
}
finish();
}
private synchronized void doDownload() {
final String action = intent.getAction();
if (TextUtils.isEmpty(action) || Intent.ACTION_MAIN.equals(action)) return;
boolean error = true;
String data = null;
final Bundle extras = intent.getExtras();
if (extras != null) {
final Object extraData = extras.get(Intent.EXTRA_TEXT);
if (extraData != null) {
error = false;
data = extraData.toString();
}
}
if (error) {
final Uri intentData = intent.getData();
if (intentData != null) data = intentData.toString();
}
if (data != null && !TextUtils.isEmpty(data)) {
final IntentModel model = IntentUtils.parseUrl(data);
if (model != null && model.getType() == IntentModelType.POST) {
final String text = model.getText();
new PostFetcher(text, new FetchListener<FeedModel>() {
@Override
public void doBefore() {
final Notification fetchingPostNotif = new NotificationCompat.Builder(context, Constants.DOWNLOAD_CHANNEL_ID)
.setCategory(NotificationCompat.CATEGORY_STATUS).setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(false).setPriority(NotificationCompat.PRIORITY_MIN)
.setContentText(context.getString(R.string.direct_download_loading)).build();
notificationManager.notify(1900000000, fetchingPostNotif);
}
@Override
public void onResult(final FeedModel result) {
if (notificationManager != null) notificationManager.cancel(1900000000);
if (result != null) {
if (result.getItemType() != MediaItemType.MEDIA_TYPE_SLIDER) {
DownloadUtils.batchDownload(context,
result.getProfileModel().getUsername(),
DownloadMethod.DOWNLOAD_DIRECT,
Collections.singletonList(result));
} else {
context.startActivity(new Intent(context, MultiDirectDialog.class)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
.putExtra(Constants.EXTRAS_POST, result));
}
}
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
}
}

117
app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java

@ -1,117 +0,0 @@
package awais.instagrabber.directdownload;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import awais.instagrabber.R;
import awais.instagrabber.activities.BaseLanguageActivity;
import awais.instagrabber.adapters.PostsAdapter;
import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager;
import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration;
import awais.instagrabber.models.BasePostModel;
import awais.instagrabber.models.FeedModel;
import awais.instagrabber.models.PostModel;
import awais.instagrabber.models.enums.DownloadMethod;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.Utils;
public final class MultiDirectDialog extends BaseLanguageActivity {
public final ArrayList<BasePostModel> selectedItems = new ArrayList<>();
private PostsAdapter postsAdapter;
private MenuItem btnDownload;
private String username = null;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_direct);
final Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final FeedModel feedModel;
final Intent intent = getIntent();
if (intent == null || !intent.hasExtra(Constants.EXTRAS_POST)
|| (feedModel = (FeedModel) intent.getSerializableExtra(Constants.EXTRAS_POST)) == null) {
Utils.errorFinish(this);
return;
}
username = feedModel.getProfileModel().getUsername();
toolbar.setTitle(username);
toolbar.setSubtitle(feedModel.getShortCode());
final RecyclerView recyclerView = findViewById(R.id.mainPosts);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setLayoutManager(new GridAutofitLayoutManager(this, Utils.convertDpToPx(130)));
recyclerView.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4)));
// final ArrayList<PostModel> models = new ArrayList<>(feedModel.length - 1);
// for (final ViewerPostModel postModel : feedModel)
// models.add(new PostModel(postModel.getItemType(), postModel.getPostId(), postModel.getDisplayUrl(),
// postModel.getDisplayUrl(), postModel.getShortCode(), postModel.getPostCaption(), postModel.getTimestamp(),
// postModel.getLike(), postModel.isSaved(), postModel.getLikes()));
// postsAdapter = new PostsAdapter(v -> {
// final Object tag = v.getTag();
// if (tag instanceof PostModel) {
// final PostModel postModel = (PostModel) tag;
// if (postsAdapter.isSelecting) toggleSelection(postModel);
// else {
// Utils.batchDownload(this, username, DownloadMethod.DOWNLOAD_DIRECT, Collections.singletonList(postModel));
// finish();
// }
// }
// }, v -> {
// final Object tag = v.getTag();
// if (tag instanceof PostModel) {
// postsAdapter.isSelecting = true;
// toggleSelection((PostModel) tag);
// }
// return true;
// });
//
// recyclerView.setAdapter(postsAdapter);
}
@Override
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
DownloadUtils.batchDownload(this, username, DownloadMethod.DOWNLOAD_DIRECT, selectedItems);
finish();
return true;
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
btnDownload = menu.findItem(R.id.action_download);
menu.findItem(R.id.action_search).setVisible(false);
return true;
}
private void toggleSelection(final PostModel postModel) {
if (postModel != null && postsAdapter != null) {
if (postModel.isSelected()) selectedItems.remove(postModel);
else selectedItems.add(postModel);
postModel.setSelected(!postModel.isSelected());
notifyAdapter(postModel);
}
}
private void notifyAdapter(final PostModel postModel) {
// if (selectedItems.size() < 1) postsAdapter.isSelecting = false;
// if (postModel.getPosition() < 0) postsAdapter.notifyDataSetChanged();
// else postsAdapter.notifyItemChanged(postModel.getPosition(), postModel);
//
// if (btnDownload != null) btnDownload.setVisible(postsAdapter.isSelecting);
}
}

7
app/src/main/java/awais/instagrabber/services/DeleteImageIntentService.java

@ -11,10 +11,14 @@ import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import java.io.File; import java.io.File;
import java.util.Random;
import awais.instagrabber.utils.TextUtils;
public class DeleteImageIntentService extends IntentService { public class DeleteImageIntentService extends IntentService {
private final static String TAG = "DeleteImageIntent"; private final static String TAG = "DeleteImageIntent";
private static final int DELETE_IMAGE_SERVICE_REQUEST_CODE = 9010; private static final int DELETE_IMAGE_SERVICE_REQUEST_CODE = 9010;
private static final Random random = new Random();
public static final String EXTRA_IMAGE_PATH = "extra_image_path"; public static final String EXTRA_IMAGE_PATH = "extra_image_path";
public static final String EXTRA_NOTIFICATION_ID = "extra_notification_id"; public static final String EXTRA_NOTIFICATION_ID = "extra_notification_id";
@ -34,6 +38,7 @@ public class DeleteImageIntentService extends IntentService {
protected void onHandleIntent(@Nullable Intent intent) { protected void onHandleIntent(@Nullable Intent intent) {
if (intent != null && Intent.ACTION_DELETE.equals(intent.getAction()) && intent.hasExtra(EXTRA_IMAGE_PATH)) { if (intent != null && Intent.ACTION_DELETE.equals(intent.getAction()) && intent.hasExtra(EXTRA_IMAGE_PATH)) {
final String path = intent.getStringExtra(EXTRA_IMAGE_PATH); final String path = intent.getStringExtra(EXTRA_IMAGE_PATH);
if (TextUtils.isEmpty(path)) return;
final File file = new File(path); final File file = new File(path);
boolean deleted; boolean deleted;
if (file.exists()) { if (file.exists()) {
@ -59,6 +64,6 @@ public class DeleteImageIntentService extends IntentService {
intent.setAction(Intent.ACTION_DELETE); intent.setAction(Intent.ACTION_DELETE);
intent.putExtra(EXTRA_IMAGE_PATH, imagePath); intent.putExtra(EXTRA_IMAGE_PATH, imagePath);
intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId); intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
return PendingIntent.getService(context, DELETE_IMAGE_SERVICE_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return PendingIntent.getService(context, random.nextInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
} }
} }

4
app/src/main/res/layout/activity_direct.xml

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" />

21
app/src/main/res/layout/dialog_direct.xml

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:viewBindingIgnore="true">
<include layout="@layout/layout_include_toolbar" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mainPosts"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingStart="8dp"
android:paddingLeft="8dp"
android:paddingEnd="8dp"
android:paddingRight="8dp"
tools:listitem="@layout/item_post" />
</LinearLayout>

15
app/src/main/res/values/styles.xml

@ -1,19 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="CompletelyTransparent" parent="Theme.AppCompat.NoActionBar">
<item name="android:background">@null</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item> <item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowDisablePreview">true</item>
<item name="android:windowBackground">@null</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoDisplay">true</item>
<!--<item name="android:windowIsFloating">true</item>-->
<item name="android:windowAnimationStyle">@android:style/Animation</item>
</style> </style>
<style name="PlayButtonCard" parent="CardView.Dark" /> <style name="PlayButtonCard" parent="CardView.Dark" />

Loading…
Cancel
Save