From d43feffca8e7125cea54caa8dfdee317d238cb33 Mon Sep 17 00:00:00 2001 From: tom79 Date: Mon, 28 Aug 2017 15:01:45 +0200 Subject: [PATCH] Implements broadcasts --- .../activities/MainActivity.java | 39 +++++--- .../asynctasks/StreamingUserAsyncTask.java | 2 +- .../fr/gouv/etalab/mastodon/client/API.java | 2 +- .../client/Entities/Notification.java | 37 ++++++- .../gouv/etalab/mastodon/helper/Helper.java | 1 + .../etalab/mastodon/jobs/SteamingSyncJob.java | 97 +++++++++++++++---- .../activities/MainActivity.java | 81 +++++++++++++--- 7 files changed, 214 insertions(+), 45 deletions(-) diff --git a/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java b/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java index da5a9ae3e..470b2d400 100644 --- a/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java +++ b/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java @@ -119,7 +119,7 @@ public class MainActivity extends AppCompatActivity private DisplayStatusFragment homeFragment; private DisplayNotificationsFragment notificationsFragment; - + private BroadcastReceiver receive_data; public MainActivity() { } @@ -127,6 +127,8 @@ public class MainActivity extends AppCompatActivity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA)); final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); @@ -805,22 +807,22 @@ public class MainActivity extends AppCompatActivity @Override public void onResume(){ super.onResume(); - SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); - boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true); - if( bubbles){ - Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() {refreshData();} - }, 1000); - } //Proceeds to update of the authenticated account if(Helper.isLoggedIn(getApplicationContext())) new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + @Override + protected void onPause() { + super.onPause(); + MainActivity.activityPaused(); + } - + @Override + public void onDestroy(){ + super.onDestroy(); + LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data); + } @SuppressWarnings("StatementWithEmptyBody") @Override @@ -1062,6 +1064,7 @@ public class MainActivity extends AppCompatActivity } } + public void updateNotifCounter(int newNotifCount){ if(tabLayout.getTabAt(1) == null) return; @@ -1081,4 +1084,18 @@ public class MainActivity extends AppCompatActivity } } + public static boolean isActivityVisible() { + return activityVisible; + } + + private static void activityResumed() { + activityVisible = true; + } + + private static void activityPaused() { + activityVisible = false; + } + + private static boolean activityVisible; + } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/StreamingUserAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/StreamingUserAsyncTask.java index 919f42036..80730782f 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/StreamingUserAsyncTask.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/StreamingUserAsyncTask.java @@ -99,7 +99,7 @@ public class StreamingUserAsyncTask extends AsyncTask { eventStreaming = EventStreaming.NOTIFICATION; break; case "delete": - event = reader.readLine(); + event = "{\"id\":" + reader.readLine() + "}"; eventStreaming = EventStreaming.DELETE; break; default: diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java index 56822a2c3..312c42e4b 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java @@ -1253,7 +1253,7 @@ public class API { * @return Status */ @SuppressWarnings("InfiniteRecursion") - private static Status parseStatuses(Context context, JSONObject resobj){ + public static Status parseStatuses(Context context, JSONObject resobj){ Status status = new Status(); try { status.setId(resobj.get("id").toString()); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Notification.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Notification.java index a8cc8f74d..384ede022 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Notification.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Notification.java @@ -15,13 +15,16 @@ package fr.gouv.etalab.mastodon.client.Entities; +import android.os.Parcel; +import android.os.Parcelable; + import java.util.Date; /** * Created by Thomas on 23/04/2017. */ -public class Notification { +public class Notification implements Parcelable { private String id; private String type; @@ -29,6 +32,25 @@ public class Notification { private Account account; private Status status; + protected Notification(Parcel in) { + id = in.readString(); + type = in.readString(); + account = in.readParcelable(Account.class.getClassLoader()); + status = in.readParcelable(Status.class.getClassLoader()); + } + + public static final Creator CREATOR = new Creator() { + @Override + public Notification createFromParcel(Parcel in) { + return new Notification(in); + } + + @Override + public Notification[] newArray(int size) { + return new Notification[size]; + } + }; + public String getId() { return id; } @@ -68,4 +90,17 @@ public class Notification { public void setStatus(Status status) { this.status = status; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(id); + dest.writeString(type); + dest.writeParcelable(account, flags); + dest.writeParcelable(status, flags); + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java index 97d89f078..3419b1cdd 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java @@ -251,6 +251,7 @@ public class Helper { //Receiver public static final String SEARCH_VALIDATE_ACCOUNT = "search_validate_account"; public static final String HEADER_ACCOUNT = "header_account"; + public static final String RECEIVE_DATA = "receive_data"; //User agent public static final String USER_AGENT = "Mastalab/"+ BuildConfig.VERSION_NAME + " Android/"+ Build.VERSION.RELEASE; diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/SteamingSyncJob.java b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/SteamingSyncJob.java index b450bf0eb..98fed4230 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/SteamingSyncJob.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/SteamingSyncJob.java @@ -21,7 +21,9 @@ import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; +import android.os.Bundle; import android.support.annotation.NonNull; +import android.support.v4.content.LocalBroadcastManager; import android.view.View; import com.evernote.android.job.Job; @@ -35,6 +37,7 @@ import com.nostra13.universalimageloader.core.assist.FailReason; import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer; import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; +import org.json.JSONException; import org.json.JSONObject; import java.io.File; @@ -43,24 +46,22 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import fr.gouv.etalab.mastodon.activities.MainActivity; -import fr.gouv.etalab.mastodon.asynctasks.RetrieveNotificationsAsyncTask; import fr.gouv.etalab.mastodon.asynctasks.StreamingUserAsyncTask; import fr.gouv.etalab.mastodon.client.API; -import fr.gouv.etalab.mastodon.client.APIResponse; import fr.gouv.etalab.mastodon.client.Entities.Account; import fr.gouv.etalab.mastodon.client.Entities.Notification; +import fr.gouv.etalab.mastodon.client.Entities.Status; import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader; import fr.gouv.etalab.mastodon.helper.Helper; -import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveStreamingInterface; import fr.gouv.etalab.mastodon.sqlite.AccountDAO; import fr.gouv.etalab.mastodon.sqlite.Sqlite; import mastodon.etalab.gouv.fr.mastodon.R; +import static fr.gouv.etalab.mastodon.helper.Helper.HOME_TIMELINE_INTENT; import static fr.gouv.etalab.mastodon.helper.Helper.INTENT_ACTION; import static fr.gouv.etalab.mastodon.helper.Helper.NOTIFICATION_INTENT; import static fr.gouv.etalab.mastodon.helper.Helper.PREF_KEY_ID; -import static fr.gouv.etalab.mastodon.helper.Helper.canNotify; import static fr.gouv.etalab.mastodon.helper.Helper.notify_user; @@ -73,6 +74,8 @@ public class SteamingSyncJob extends Job implements OnRetrieveStreamingInterface static final String STREAMING = "job_streaming"; private String message; + private int notificationId; + private Intent intent; @NonNull @Override @@ -130,7 +133,6 @@ public class SteamingSyncJob extends Job implements OnRetrieveStreamingInterface return; //Retrieve users in db that owner has. for (Account account: accounts) { - String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId(), null); new StreamingUserAsyncTask(account.getInstance(), account.getToken(), account.getAcct(), account.getId(), SteamingSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } } @@ -141,23 +143,24 @@ public class SteamingSyncJob extends Job implements OnRetrieveStreamingInterface public void onRetrieveStreaming(StreamingUserAsyncTask.EventStreaming event, JSONObject response, String acct, String userId) { if( response == null ) return; - String new_max_id = null; + String max_id = null; final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true); boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true); boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true); boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true); - final String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + userId, null); - //No previous notifications in cache, so no notification will be sent boolean notify = false; String notificationUrl = null; String title = null; + Status status = null; + Notification notification = null; + String dataId = null; if( event == StreamingUserAsyncTask.EventStreaming.NOTIFICATION){ - Notification notification = API.parseNotificationResponse(getContext(), response); - new_max_id = notification.getId(); + notification = API.parseNotificationResponse(getContext(), response); + max_id = notification.getId(); switch (notification.getType()){ case "mention": if(notif_mention){ @@ -208,32 +211,86 @@ public class SteamingSyncJob extends Job implements OnRetrieveStreamingInterface message = notification.getStatus().getContent(); if( message!= null) { message = message.substring(0, 17); - message = message + "..."; + message = message + "…"; + }else{ + message = ""; } }else if ( event == StreamingUserAsyncTask.EventStreaming.UPDATE){ - + status = API.parseStatuses(getContext(), response); + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, status.getId()); + editor.apply(); + message = status.getContent(); + if( message!= null) { + message = message.substring(0, 17); + message = message + "…"; + }else{ + message = ""; + } }else if( event == StreamingUserAsyncTask.EventStreaming.DELETE){ + try { + dataId = response.getString("id"); + + } catch (JSONException e) { + e.printStackTrace(); + } } - if( new_max_id != null){ + if( max_id != null){ SharedPreferences.Editor editor = sharedpreferences.edit(); - editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, new_max_id); + editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, max_id); editor.apply(); return; } //Check which user is connected and if activity is to front - - - - if( notify){ - final Intent intent = new Intent(getContext(), MainActivity.class); + boolean activityVisible = false; + try{ + activityVisible = MainActivity.isActivityVisible(); + }catch (Exception ignored){} + String userconnected = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + SQLiteDatabase db = Sqlite.getInstance(getContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + Account account = new AccountDAO(getContext(), db).getAccountByID(userconnected); + //User receiving the notification is connected and application is to front, notification won't be pushed + //Instead, the interaction is done in the activity + if( activityVisible && account != null && account.getAcct().trim().equals(acct.trim()) && account.getId().trim().equals(userId.trim())){ + notify = false; + Intent intentBC = new Intent(Helper.RECEIVE_DATA); + intent.putExtra("eventStreaming", event); + Bundle b = new Bundle(); + if( event == StreamingUserAsyncTask.EventStreaming.UPDATE) + b.putParcelable("data", status); + else if(event == StreamingUserAsyncTask.EventStreaming.NOTIFICATION) + b.putParcelable("data", notification); + else if(event == StreamingUserAsyncTask.EventStreaming.DELETE) + b.putString("id", dataId); + intentBC.putExtras(b); + LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intentBC); + }else if(event == StreamingUserAsyncTask.EventStreaming.NOTIFICATION ){ + notify = true; + intent = new Intent(getContext(), MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK ); intent.putExtra(INTENT_ACTION, NOTIFICATION_INTENT); intent.putExtra(PREF_KEY_ID, userId); long notif_id = Long.parseLong(userId); - final int notificationId = ((notif_id + 1) > 2147483647) ? (int) (2147483647 - notif_id - 1) : (int) (notif_id + 1); + notificationId = ((notif_id + 1) > 2147483647) ? (int) (2147483647 - notif_id - 1) : (int) (notif_id + 1); + + }else if(event == StreamingUserAsyncTask.EventStreaming.UPDATE ){ + if(acct != null && status.getAccount().getAcct().trim().equals(acct.trim())){ + notify = false; + }else { + notify = true; + intent = new Intent(getContext(), MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(INTENT_ACTION, HOME_TIMELINE_INTENT); + intent.putExtra(PREF_KEY_ID, userId); + long notif_id = Long.parseLong(userId); + notificationId = ((notif_id + 2) > 2147483647) ? (int) (2147483647 - notif_id - 2) : (int) (notif_id + 2); + } + } + + if( notify){ if( notificationUrl != null){ ImageLoader imageLoaderNoty = ImageLoader.getInstance(); File cacheDir = new File(getContext().getCacheDir(), getContext().getString(R.string.app_name)); diff --git a/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java b/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java index fd9caf2b2..34ba724e8 100644 --- a/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java +++ b/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java @@ -15,9 +15,11 @@ package fr.gouv.etalab.mastodon.activities; import android.annotation.SuppressLint; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.graphics.PorterDuff; @@ -31,6 +33,7 @@ import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; +import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.ViewPager; import android.support.v7.app.AlertDialog; import android.support.v7.widget.SearchView; @@ -74,6 +77,8 @@ import java.util.concurrent.TimeUnit; import fr.gouv.etalab.mastodon.asynctasks.StreamingUserAsyncTask; import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoByIDAsyncTask; import fr.gouv.etalab.mastodon.client.Entities.Account; +import fr.gouv.etalab.mastodon.client.Entities.Notification; +import fr.gouv.etalab.mastodon.client.Entities.Status; import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader; import fr.gouv.etalab.mastodon.fragments.DisplayAccountsFragment; import fr.gouv.etalab.mastodon.fragments.DisplayFollowRequestSentFragment; @@ -125,6 +130,7 @@ public class MainActivity extends AppCompatActivity private DisplayStatusFragment homeFragment; private DisplayNotificationsFragment notificationsFragment; private static final int ERROR_DIALOG_REQUEST_CODE = 97; + private BroadcastReceiver receive_data; public MainActivity() { } @@ -132,6 +138,42 @@ public class MainActivity extends AppCompatActivity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA)); + + receive_data = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Bundle b = getIntent().getExtras(); + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true); + StreamingUserAsyncTask.EventStreaming eventStreaming = (StreamingUserAsyncTask.EventStreaming) intent.getSerializableExtra("eventStreaming"); + if( eventStreaming == StreamingUserAsyncTask.EventStreaming.NOTIFICATION){ + Notification notification = b.getParcelable("data"); + if( notificationsFragment.getUserVisibleHint() == true){ + + }else{ + + } + }else if(eventStreaming == StreamingUserAsyncTask.EventStreaming.UPDATE){ + Status status = b.getParcelable("data"); + if( notificationsFragment.getUserVisibleHint() == true){ + + }else{ + + } + }else if(eventStreaming == StreamingUserAsyncTask.EventStreaming.DELETE){ + String id = b.getString("id"); + if( notificationsFragment.getUserVisibleHint() == true){ + + }else{ + + } + } + } + }; + + + ProviderInstaller.installIfNeededAsync(this, this); final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); @@ -813,23 +855,23 @@ public class MainActivity extends AppCompatActivity @Override public void onResume(){ super.onResume(); - SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); - boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true); - if( bubbles){ - Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() {refreshData();} - }, 1000); - } - + MainActivity.activityResumed(); //Proceeds to update of the authenticated account if(Helper.isLoggedIn(getApplicationContext())) new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + @Override + protected void onPause() { + super.onPause(); + MainActivity.activityPaused(); + } - + @Override + public void onDestroy(){ + super.onDestroy(); + LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data); + } @SuppressWarnings("StatementWithEmptyBody") @Override @@ -1136,4 +1178,21 @@ public class MainActivity extends AppCompatActivity } } + + + + + public static boolean isActivityVisible() { + return activityVisible; + } + + private static void activityResumed() { + activityVisible = true; + } + + private static void activityPaused() { + activityVisible = false; + } + + private static boolean activityVisible; }