.
This commit is contained in:
15
.idea/deploymentTargetDropDown.xml
generated
15
.idea/deploymentTargetDropDown.xml
generated
@@ -3,7 +3,20 @@
|
||||
<component name="deploymentTargetDropDown">
|
||||
<value>
|
||||
<entry key="app">
|
||||
<State />
|
||||
<State>
|
||||
<targetSelectedWithDropDown>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="$USER_HOME$/.android/avd/Pixel_7_Pro_API_33.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2024-03-15T09:47:16.525599Z" />
|
||||
</State>
|
||||
</entry>
|
||||
</value>
|
||||
</component>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- permissions for app blocking -->
|
||||
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.telephony"
|
||||
@@ -265,7 +266,9 @@
|
||||
<receiver android:name=".patient_dashboard.foodreminders.FoodReminderYesReceiver"/>
|
||||
<service android:name=".patient_dashboard.foodreminders.FoodReminderNotifyingService"/>
|
||||
|
||||
<receiver android:name=".patient_dashboard.CallReceiver" android:enabled="true" android:exported="true">
|
||||
<receiver android:name=".patient_dashboard.CallReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PHONE_STATE" />
|
||||
</intent-filter>
|
||||
|
||||
@@ -1,18 +1,197 @@
|
||||
package com.app.simplitend.patient_dashboard;
|
||||
|
||||
import static com.app.simplitend.callwhitelisting.CallUnBlockingWorker.CALL_BLOCKING_WORk;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
import androidx.work.WorkRequest;
|
||||
|
||||
import com.app.simplitend.apputils.AppUtil;
|
||||
import com.app.simplitend.callwhitelisting.CallUnBlockingWorker;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.i18n.phonenumbers.Phonenumber;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CallReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = "CallReceiver";
|
||||
|
||||
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
|
||||
private static Date callStartTime;
|
||||
private static boolean isIncoming;
|
||||
private static String savedNumber; //because the passed incoming is only valid in ringing
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
TelecomManager telecomManager = (TelecomManager) context.getApplicationContext().getSystemService(TelecomManager.class);
|
||||
if (intent.getExtras() == null) {
|
||||
Log.d(TAG, "onReceive: EXTRAS ARE NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
// logBundle(intent.getExtras());
|
||||
|
||||
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
|
||||
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
|
||||
|
||||
int state = 0;
|
||||
if (TelephonyManager.EXTRA_STATE_IDLE.equals(stateStr)) {
|
||||
state = TelephonyManager.CALL_STATE_IDLE;
|
||||
} else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(stateStr)) {
|
||||
state = TelephonyManager.CALL_STATE_OFFHOOK;
|
||||
} else if (TelephonyManager.EXTRA_STATE_RINGING.equals(stateStr)) {
|
||||
state = TelephonyManager.CALL_STATE_RINGING;
|
||||
}
|
||||
|
||||
onCallStateChanged(context, state, number);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
protected void logBundle(Bundle bundle) {
|
||||
if (bundle != null) {
|
||||
for (String key : bundle.keySet()) {
|
||||
Log.e(TAG, key + " : " + (bundle.get(key) != null ? bundle.get(key) : "NULL"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Derived classes should override these to respond to specific events of interest
|
||||
protected void onIncomingCallStarted(Context ctx, String number, Date start) {
|
||||
Log.d(TAG, "onIncomingCallStarted: " + number);
|
||||
if (!AppUtil.isCallBlockingEnabled(ctx)) {
|
||||
// senior has deactivated the call blocking feature
|
||||
Log.d(TAG, "onIncomingCallStarted: CALL BLOCKING IS DEACTIVATED");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Phonenumber.PhoneNumber parsed_phone = PhoneNumberUtil.getInstance().parse(number, "US");
|
||||
number = "+" + parsed_phone.getCountryCode() + parsed_phone.getNationalNumber();
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
Log.d(TAG, "AFTER FORMATTING PHONE NUMBER -> " + number);
|
||||
|
||||
Set<String> white_contacts = AppUtil.getWhiteListedContacts(ctx);
|
||||
Log.d(TAG, "WHITE LISTED CONTACTS -> " + white_contacts);
|
||||
|
||||
if (AppUtil.isUserSubscribed(ctx) && white_contacts != null && !white_contacts.contains(number)) {
|
||||
disconnectCall();
|
||||
Log.d(TAG, "CALL ENDED");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void disconnectCall(){
|
||||
try {
|
||||
String serviceManagerName = "android.os.ServiceManager";
|
||||
String serviceManagerNativeName = "android.os.ServiceManagerNative";
|
||||
String telephonyName = "com.android.internal.telephony.ITelephony";
|
||||
Class<?> telephonyClass;
|
||||
Class<?> telephonyStubClass;
|
||||
Class<?> serviceManagerClass;
|
||||
Class<?> serviceManagerNativeClass;
|
||||
Method telephonyEndCall;
|
||||
Object telephonyObject;
|
||||
Object serviceManagerObject;
|
||||
telephonyClass = Class.forName(telephonyName);
|
||||
telephonyStubClass = telephonyClass.getClasses()[0];
|
||||
serviceManagerClass = Class.forName(serviceManagerName);
|
||||
serviceManagerNativeClass = Class.forName(serviceManagerNativeName);
|
||||
Method getService = // getDefaults[29];
|
||||
serviceManagerClass.getMethod("getService", String.class);
|
||||
Method tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder.class);
|
||||
Binder tmpBinder = new Binder();
|
||||
tmpBinder.attachInterface(null, "fake");
|
||||
serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder);
|
||||
IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone");
|
||||
Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class);
|
||||
telephonyObject = serviceMethod.invoke(null, retbinder);
|
||||
telephonyEndCall = telephonyClass.getMethod("endCall");
|
||||
telephonyEndCall.invoke(telephonyObject);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG,
|
||||
"FATAL ERROR: could not connect to telephony subsystem");
|
||||
Log.e(TAG, "Exception object: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
|
||||
Log.d(TAG, "onOutgoingCallStarted: " + number);
|
||||
if ("911".equals(number)){
|
||||
Log.d(TAG, "CALLED 911");
|
||||
WorkManager.getInstance(ctx).cancelAllWorkByTag(TAG);
|
||||
WorkRequest workRequest = new OneTimeWorkRequest.Builder(CallUnBlockingWorker.class)
|
||||
.setInitialDelay(30, TimeUnit.MINUTES)
|
||||
.addTag(CALL_BLOCKING_WORk)
|
||||
.build();
|
||||
|
||||
WorkManager.getInstance(ctx).enqueue(workRequest);
|
||||
|
||||
AppUtil.setIsCallBlockingEnabled(ctx, false);
|
||||
Log.d(TAG, "CALL BLOCKING DISABLED");
|
||||
}
|
||||
}
|
||||
|
||||
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
|
||||
}
|
||||
|
||||
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
|
||||
}
|
||||
|
||||
protected void onMissedCall(Context ctx, String number, Date start) {
|
||||
}
|
||||
|
||||
//Deals with actual events
|
||||
|
||||
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
|
||||
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
|
||||
public void onCallStateChanged(Context context, int state, String number) {
|
||||
if (lastState == state) {
|
||||
//No change, debounce extras
|
||||
return;
|
||||
}
|
||||
switch (state) {
|
||||
case TelephonyManager.CALL_STATE_RINGING:
|
||||
isIncoming = true;
|
||||
callStartTime = new Date();
|
||||
savedNumber = number;
|
||||
onIncomingCallStarted(context, number, callStartTime);
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
||||
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
|
||||
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
|
||||
isIncoming = false;
|
||||
callStartTime = new Date();
|
||||
onOutgoingCallStarted(context, number, callStartTime);
|
||||
}
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_IDLE:
|
||||
//Went to idle- this is the end of a call. What type depends on previous state(s)
|
||||
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
|
||||
//Ring but no pickup- a miss
|
||||
onMissedCall(context, savedNumber, callStartTime);
|
||||
} else if (isIncoming) {
|
||||
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
|
||||
} else {
|
||||
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
|
||||
}
|
||||
break;
|
||||
}
|
||||
lastState = state;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,6 @@ public class DashBoardActivity extends AppCompatActivity implements CgHomeContra
|
||||
}), null, null);
|
||||
}
|
||||
|
||||
requestPermissions(new String[]{Manifest.permission.CALL_PHONE}, 1212);
|
||||
});
|
||||
|
||||
registerForActivityResult(new ActivityResultContracts.RequestPermission(),
|
||||
@@ -94,6 +93,8 @@ public class DashBoardActivity extends AppCompatActivity implements CgHomeContra
|
||||
RoleManager roleManager = getSystemService(RoleManager.class);
|
||||
Intent i = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
|
||||
startActivityForResult(i, 1214, null);
|
||||
}else{
|
||||
requestPermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.READ_PHONE_STATE, Manifest.permission.ANSWER_PHONE_CALLS}, 1212);
|
||||
}
|
||||
}
|
||||
}).launch(Manifest.permission.READ_CONTACTS);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.app.simplitend.patient_dashboard;
|
||||
|
||||
import static com.app.simplitend.callwhitelisting.CallUnBlockingWorker.CALL_BLOCKING_WORk;
|
||||
import static com.app.simplitend.caregiverdashboard.activities.deactivateacc.DeActivateAccountActivity.IS_PATIENT_KEY;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.work.WorkManager;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
@@ -74,6 +76,9 @@ public class PatSettingsActivity extends AppCompatActivity implements CgHomeCont
|
||||
binding.callBlockCheck.setOnCheckedChangeListener(null);
|
||||
binding.callBlockCheck.setChecked(true);
|
||||
binding.callBlockCheck.setOnCheckedChangeListener(this);
|
||||
|
||||
WorkManager.getInstance(PatSettingsActivity.this)
|
||||
.cancelAllWorkByTag(CALL_BLOCKING_WORk);
|
||||
}),
|
||||
"Turn off", ((dialogInterface, i) -> {
|
||||
AppUtil.setIsCallBlockingEnabled(PatSettingsActivity.this, false);
|
||||
|
||||
Reference in New Issue
Block a user