Skip to content

Commit 309e113

Browse files
Merge pull request #13 from linhvovan29546/fix/prevent-multiple-click
fix: #11, #12 feat: Auto launch app when pressed notification, prevent click notification action
2 parents 2b97289 + a268373 commit 309e113

14 files changed

+222
-104
lines changed

README.md

+13-5
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,22 @@ In `AndroidManifest.xml`:
6161
<uses-permission android:name="android.permission.WAKE_LOCK" />
6262
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
6363
<application ....>
64-
<activity android:name="com.reactnativefullscreennotificationincomingcall.IncomingCallActivity"
65-
android:exported="true"
64+
<activity android:name="com.reactnativefullscreennotificationincomingcall.IncomingCallActivity"
6665
android:theme="@style/incomingCall"
67-
android:showOnLockScreen="true"
68-
android:taskAffinity=""
6966
android:launchMode="singleTask"
7067
android:excludeFromRecents="true"
71-
/>
68+
android:exported="true"
69+
android:showWhenLocked="true"
70+
android:turnScreenOn="true"
71+
/>
72+
<activity android:name="com.reactnativefullscreennotificationincomingcall.NotificationReceiverActivity"
73+
android:theme="@style/incomingCall"
74+
android:launchMode="singleTask"
75+
android:excludeFromRecents="true"
76+
android:exported="true"
77+
android:showWhenLocked="true"
78+
android:turnScreenOn="true"
79+
/>
7280
<service
7381
android:name="com.reactnativefullscreennotificationincomingcall.IncomingCallService"
7482
android:enabled="true"

android/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ repositories {
5656
dependencies {
5757
//noinspection GradleDynamicVersion
5858
implementation "com.facebook.react:react-native:+" // From node_modules
59-
implementation "com.airbnb.android:lottie:5.0.3" // create ui animation
59+
implementation "com.airbnb.android:lottie:5.1.1" // create ui animation
6060
implementation 'com.squareup.picasso:picasso:2.71828'
6161
}

android/src/main/java/com/reactnativefullscreennotificationincomingcall/Constants.java

+2
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ public class Constants {
1313
//event press answer/decline call
1414
public static final String RNNotificationAnswerAction="RNNotificationAnswerAction";
1515
public static final String RNNotificationEndCallAction="RNNotificationEndCallAction";
16+
public static final String onPressNotification="onPressNotification";
17+
1618

1719
}

android/src/main/java/com/reactnativefullscreennotificationincomingcall/IncomingCallActivity.java

+10-26
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.view.View;
1111
import android.view.WindowManager;
1212
import android.widget.ImageView;
13+
import android.widget.LinearLayout;
1314
import android.widget.TextView;
1415
import com.airbnb.lottie.LottieAnimationView;
1516
import androidx.appcompat.app.AppCompatActivity;
@@ -26,9 +27,13 @@ public class IncomingCallActivity extends AppCompatActivity {
2627
private TextView tvDecline;
2728
private TextView tvAccept;
2829
private ImageView ivAvatar;
30+
private LottieAnimationView acceptCallBtn;
31+
private LottieAnimationView rejectCallBtn;
32+
private LinearLayout lnDeclineCall;
33+
private LinearLayout lnAcceptCall;
34+
2935
private String uuid = "";
3036
static boolean active = false;
31-
private static Activity fa;
3237
static IncomingCallActivity instance;
3338

3439
public static IncomingCallActivity getInstance() {
@@ -57,7 +62,6 @@ public void onDestroy() {
5762
@Override
5863
protected void onCreate(Bundle savedInstanceState) {
5964
super.onCreate(savedInstanceState);
60-
fa = this;
6165
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
6266
setShowWhenLocked(true);
6367
setTurnScreenOn(true);
@@ -69,10 +73,6 @@ protected void onCreate(Bundle savedInstanceState) {
6973
}
7074
}
7175
setContentView(R.layout.activity_call_incoming);
72-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
73-
setShowWhenLocked(true);
74-
setTurnScreenOn(true);
75-
}
7676
getWindow().addFlags(
7777
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
7878
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
@@ -84,11 +84,12 @@ protected void onCreate(Bundle savedInstanceState) {
8484
ivAvatar = findViewById(R.id.ivAvatar);
8585
tvDecline=findViewById(R.id.tvDecline);
8686
tvAccept=findViewById(R.id.tvAccept);
87+
lnDeclineCall = findViewById(R.id.lnDeclineCall);
88+
lnAcceptCall = findViewById(R.id.lnAcceptCall);
8789
Bundle bundle = getIntent().getExtras();
8890
if (bundle != null) {
8991
if (bundle.containsKey("uuid")) {
9092
uuid = bundle.getString("uuid");
91-
9293
}
9394
if (bundle.containsKey("name")) {
9495
String name = bundle.getString("name");
@@ -114,8 +115,7 @@ protected void onCreate(Bundle savedInstanceState) {
114115
}
115116
}
116117

117-
LottieAnimationView acceptCallBtn = findViewById(R.id.ivAcceptCall);
118-
acceptCallBtn.setOnClickListener(new View.OnClickListener() {
118+
lnAcceptCall.setOnClickListener(new View.OnClickListener() {
119119
@Override
120120
public void onClick(View view) {
121121
try {
@@ -129,8 +129,7 @@ public void onClick(View view) {
129129
}
130130
});
131131

132-
LottieAnimationView rejectCallBtn = findViewById(R.id.ivDeclineCall);
133-
rejectCallBtn.setOnClickListener(new View.OnClickListener() {
132+
lnDeclineCall.setOnClickListener(new View.OnClickListener() {
134133
@Override
135134
public void onClick(View view) {
136135
dismissDialing(Constants.ACTION_REJECTED_CALL);
@@ -159,21 +158,7 @@ public void destroyActivity(Boolean isReject) {
159158
private void acceptDialing() {
160159
active=false;
161160
WritableMap params = Arguments.createMap();
162-
params.putBoolean("accept", true);
163161
params.putString("callUUID", uuid);
164-
KeyguardManager mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
165-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
166-
if (mKeyguardManager.isDeviceLocked()) {
167-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
168-
mKeyguardManager.requestDismissKeyguard(this, new KeyguardManager.KeyguardDismissCallback() {
169-
@Override
170-
public void onDismissSucceeded() {
171-
super.onDismissSucceeded();
172-
}
173-
});
174-
}
175-
}
176-
}
177162
FullScreenNotificationIncomingCallModule.sendEventToJs(Constants.RNNotificationAnswerAction, params);
178163
stopService(new Intent(this, IncomingCallService.class));
179164
if (Build.VERSION.SDK_INT >= 21) {
@@ -186,7 +171,6 @@ public void onDismissSucceeded() {
186171
private void dismissDialing(String action) {
187172
active=false;
188173
WritableMap params = Arguments.createMap();
189-
params.putBoolean("accept", false);
190174
params.putString("callUUID", uuid);
191175
params.putString("endAction",action);
192176
FullScreenNotificationIncomingCallModule.sendEventToJs(Constants.RNNotificationEndCallAction, params);

android/src/main/java/com/reactnativefullscreennotificationincomingcall/IncomingCallService.java

+24-59
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,19 @@
66
import android.app.NotificationManager;
77
import android.app.PendingIntent;
88
import android.app.Service;
9-
import android.content.BroadcastReceiver;
109
import android.content.Context;
1110
import android.content.Intent;
12-
import android.content.IntentFilter;
1311
import android.content.res.Resources;
1412
import android.graphics.Color;
1513
import android.media.AudioAttributes;
16-
import android.media.AudioManager;
17-
import android.media.Ringtone;
1814
import android.media.RingtoneManager;
1915
import android.os.Build;
2016
import android.os.Bundle;
2117
import android.os.Handler;
2218
import android.os.IBinder;
23-
import android.os.VibrationEffect;
24-
import android.os.Vibrator;
2519
import android.util.Log;
2620

21+
2722
import androidx.annotation.Nullable;
2823
import androidx.core.app.NotificationCompat;
2924
import androidx.core.content.ContextCompat;
@@ -37,15 +32,15 @@ public class IncomingCallService extends Service {
3732
public static Handler callhandle;
3833
private String uuid = "";
3934
private Integer timeoutNumber=0;
35+
private boolean isRegistered = false;
36+
// you can perform a click only once time
37+
private Bundle bundleData;
4038
private static final String TAG = "FullscreenSevice";
4139
public int onStartCommand(Intent intent, int flags, int startId) {
4240
String action = intent.getAction();
4341
if (action != null) {
4442
if (action.equals(Constants.ACTION_SHOW_INCOMING_CALL)) {
45-
IntentFilter filter = new IntentFilter();
46-
filter.addAction(Constants.ACTION_PRESS_ANSWER_CALL);
47-
filter.addAction(Constants.ACTION_PRESS_DECLINE_CALL);
48-
getApplicationContext().registerReceiver(mReceiver, filter);
43+
NotificationReceiverHandler.updateCanClick(true);
4944
Bundle bundle = intent.getExtras();
5045
uuid= bundle.getString("uuid");
5146
if(bundle.containsKey("timeout")){
@@ -78,24 +73,25 @@ public void onTaskRemoved(Intent rootIntent) {
7873
stopSelf();
7974
}
8075

81-
private PendingIntent onButtonNotificationClick(int id, String action) {
82-
Intent buttonIntent= new Intent();
83-
buttonIntent.setAction(action);
84-
return PendingIntent.getBroadcast(this,id , buttonIntent, PendingIntent.FLAG_IMMUTABLE);
76+
77+
private PendingIntent onButtonNotificationClick(int id, String action,String eventName) {
78+
Intent emptyScreenIntent = new Intent(this, NotificationReceiverActivity.class);
79+
emptyScreenIntent.setAction(action);
80+
emptyScreenIntent.putExtras(bundleData);
81+
emptyScreenIntent.putExtra("eventName",eventName);
82+
return PendingIntent.getActivity(this, 0, emptyScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
8583
}
8684

8785
private Notification buildNotification(Context context, Intent intent) {
88-
Intent fullScreenIntent = new Intent(context, IncomingCallActivity.class);
86+
87+
Intent emptyScreenIntent = new Intent(context, NotificationReceiverActivity.class);
8988
Bundle bundle = intent.getExtras();
90-
fullScreenIntent.putExtra("uuid", uuid);
91-
fullScreenIntent.putExtra("name", bundle.getString("name"));
92-
fullScreenIntent.putExtra("avatar", bundle.getString("avatar"));
93-
fullScreenIntent.putExtra("info", bundle.getString("info"));
94-
fullScreenIntent.putExtra("declineText", bundle.getString("declineText"));
95-
fullScreenIntent.putExtra("answerText", bundle.getString("answerText"));
89+
bundleData=bundle;
90+
emptyScreenIntent.putExtras(bundle);
91+
emptyScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
92+
emptyScreenIntent.setAction(Constants.onPressNotification);
9693
String channelId=bundle.getString("channelId");
97-
fullScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
98-
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(context, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
94+
PendingIntent emptyPendingIntent = PendingIntent.getActivity(context, 0, emptyScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
9995
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
10096
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
10197
NotificationChannel notificationChannel=new NotificationChannel(channelId, bundle.getString("channelName"), NotificationManager.IMPORTANCE_HIGH);
@@ -117,16 +113,16 @@ private Notification buildNotification(Context context, Intent intent) {
117113
.setContentText(bundle.getString("info"))
118114
.setPriority(NotificationCompat.PRIORITY_MAX)
119115
.setCategory(NotificationCompat.CATEGORY_CALL)
120-
.setContentIntent(fullScreenPendingIntent)
116+
.setContentIntent(emptyPendingIntent)
121117
.addAction(
122118
0,
123119
bundle.getString("declineText"),
124-
onButtonNotificationClick(0,Constants.ACTION_PRESS_DECLINE_CALL)
120+
onButtonNotificationClick(0,Constants.ACTION_PRESS_DECLINE_CALL,Constants.RNNotificationEndCallAction)
125121
)
126122
.addAction(
127123
0,
128124
bundle.getString("answerText"),
129-
onButtonNotificationClick(1,Constants.ACTION_PRESS_ANSWER_CALL)
125+
onButtonNotificationClick(1,Constants.ACTION_PRESS_ANSWER_CALL,Constants.RNNotificationAnswerAction)
130126
)
131127
.setAutoCancel(true)
132128
.setOngoing(true)
@@ -138,7 +134,7 @@ private Notification buildNotification(Context context, Intent intent) {
138134
// interacts with the notification. Also, if your app targets Android 10
139135
// or higher, you need to request the USE_FULL_SCREEN_INTENT permission in
140136
// order for the platform to invoke this notification.
141-
.setFullScreenIntent(fullScreenPendingIntent, true);
137+
.setFullScreenIntent(emptyPendingIntent, true);
142138
if(bundle.getString("notificationColor")!=null){
143139
notificationBuilder.setColor(getColorForResourceName(context,bundle.getString("notificationColor")));
144140
}
@@ -164,6 +160,7 @@ public void onDestroy() {
164160
cancelTimer();
165161
stopForeground(true);
166162
}
163+
167164
public void setTimeOutEndCall(String uuid) {
168165
callhandle=new Handler();
169166
handleTimeout=new Runnable() {
@@ -186,39 +183,7 @@ public void cancelTimer(){
186183
callhandle.removeCallbacks(handleTimeout);
187184
}
188185
}
189-
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
190-
@Override
191-
public void onReceive(Context context, Intent intent) {
192-
String action = intent.getAction();
193-
if (action != null) {
194-
if (action.equals(Constants.ACTION_PRESS_ANSWER_CALL)) {
195-
cancelTimer();
196186

197-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
198-
Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
199-
context.sendBroadcast(it);
200-
}
201-
if (IncomingCallActivity.active) {
202-
IncomingCallActivity.getInstance().destroyActivity(false);
203-
}
204-
WritableMap params = Arguments.createMap();
205-
params.putString("callUUID", uuid);
206-
FullScreenNotificationIncomingCallModule.sendEventToJs(Constants.RNNotificationAnswerAction,params);
207-
stopForeground(true);
208-
}else if(action.equals(Constants.ACTION_PRESS_DECLINE_CALL)){
209-
cancelTimer();
210-
if (IncomingCallActivity.active) {
211-
IncomingCallActivity.getInstance().destroyActivity(false);
212-
}
213-
WritableMap params = Arguments.createMap();
214-
params.putString("callUUID", uuid);
215-
params.putString("endAction", Constants.ACTION_REJECTED_CALL);
216-
FullScreenNotificationIncomingCallModule.sendEventToJs(Constants.RNNotificationEndCallAction,params);
217-
stopForeground(true);
218-
}
219-
}
220-
}
221-
};
222187
private int getResourceIdForResourceName(Context context, String resourceName) {
223188
int resourceId = context.getResources().getIdentifier(resourceName, "drawable", context.getPackageName());
224189
if (resourceId == 0) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.reactnativefullscreennotificationincomingcall;
2+
3+
import android.app.Activity;
4+
import android.content.Intent;
5+
import android.os.Bundle;
6+
7+
public class NotificationReceiverActivity extends Activity {
8+
@Override
9+
protected void onCreate(Bundle savedInstanceState) {
10+
super.onCreate(savedInstanceState);
11+
NotificationReceiverHandler.handleNotification(this, getIntent());
12+
finish();
13+
}
14+
15+
@Override
16+
protected void onNewIntent(Intent intent) {
17+
super.onNewIntent(intent);
18+
NotificationReceiverHandler.handleNotification(this, intent);
19+
finish();
20+
}
21+
}

0 commit comments

Comments
 (0)