Started code to check DND policy on incoming call
Added dialog to ask user to grant us read permission on DND settings
This commit is contained in:
parent
b0b8284fc7
commit
4d58d71dbe
9 changed files with 198 additions and 2 deletions
|
@ -46,6 +46,8 @@
|
|||
<!-- Needed for kill application yourself -->
|
||||
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<!-- Needed to get the current Do Not Disturb policy -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
|
|
|
@ -35,6 +35,7 @@ import android.os.Bundle;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
@ -232,6 +233,11 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
|||
LinphoneManager.getInstance().isAccountWithAlias();
|
||||
}
|
||||
}
|
||||
|
||||
if (!Compatibility.isDoNotDisturbSettingsAccessGranted(
|
||||
MainActivity.this)) {
|
||||
displayDNDSettingsDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -667,6 +673,50 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
|||
dialog.show();
|
||||
}
|
||||
|
||||
private void displayDNDSettingsDialog() {
|
||||
if (!LinphonePreferences.instance().isDNDSettingsPopupEnabled()) return;
|
||||
|
||||
final Dialog dialog =
|
||||
displayDialog(getString(R.string.pref_grant_read_dnd_settings_permission_desc));
|
||||
dialog.findViewById(R.id.dialog_do_not_ask_again_layout).setVisibility(View.VISIBLE);
|
||||
final CheckBox doNotAskAgain = dialog.findViewById(R.id.doNotAskAgain);
|
||||
dialog.findViewById(R.id.doNotAskAgainLabel)
|
||||
.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
doNotAskAgain.setChecked(!doNotAskAgain.isChecked());
|
||||
}
|
||||
});
|
||||
Button cancel = dialog.findViewById(R.id.dialog_cancel_button);
|
||||
cancel.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (doNotAskAgain.isChecked()) {
|
||||
LinphonePreferences.instance().enableDNDSettingsPopup(false);
|
||||
}
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
Button ok = dialog.findViewById(R.id.dialog_ok_button);
|
||||
ok.setVisibility(View.VISIBLE);
|
||||
ok.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Log.w(
|
||||
"[Permission] Asking user to grant us permission to read DND settings");
|
||||
startActivity(
|
||||
new Intent("android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS"));
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
Button delete = dialog.findViewById(R.id.dialog_delete_button);
|
||||
delete.setVisibility(View.GONE);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
// Logs
|
||||
|
||||
private void shareUploadedLogsUrl(String info) {
|
||||
|
|
|
@ -20,8 +20,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
*/
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.PowerManager;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.tools.Log;
|
||||
|
||||
@TargetApi(23)
|
||||
class ApiTwentyThreePlus {
|
||||
|
@ -29,4 +34,82 @@ class ApiTwentyThreePlus {
|
|||
public static boolean isAppIdleMode(Context context) {
|
||||
return ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).isDeviceIdleMode();
|
||||
}
|
||||
|
||||
public static boolean isDoNotDisturbSettingsAccessGranted(Context context) {
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
boolean accessGranted = notificationManager.isNotificationPolicyAccessGranted();
|
||||
return accessGranted;
|
||||
}
|
||||
|
||||
public static boolean isDoNotDisturbPolicyAllowingRinging(
|
||||
Context context, Address remoteAddress) {
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
int filter = notificationManager.getCurrentInterruptionFilter();
|
||||
if (filter == NotificationManager.INTERRUPTION_FILTER_PRIORITY) {
|
||||
Log.w("[Audio Manager] Priority interruption filter detected");
|
||||
boolean accessGranted = notificationManager.isNotificationPolicyAccessGranted();
|
||||
if (!accessGranted) {
|
||||
Log.e(
|
||||
"[Audio Manager] Access to policy is denied, let's assume it is not safe for ringing");
|
||||
return false;
|
||||
}
|
||||
|
||||
NotificationManager.Policy policy = notificationManager.getNotificationPolicy();
|
||||
int callPolicy = policy.priorityCallSenders;
|
||||
if (callPolicy == NotificationManager.Policy.PRIORITY_SENDERS_ANY) {
|
||||
Log.i("[Audio Manager] Priority for calls is Any, we can ring");
|
||||
} else {
|
||||
if (remoteAddress == null) {
|
||||
Log.e(
|
||||
"[Audio Manager] Remote address is null, let's assume it is not safe for ringing");
|
||||
return false;
|
||||
}
|
||||
|
||||
LinphoneContact contact =
|
||||
ContactsManager.getInstance().findContactFromAddress(remoteAddress);
|
||||
if (callPolicy == NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS) {
|
||||
Log.i("[Audio Manager] Priority for calls is Contacts, let's check");
|
||||
if (contact == null) {
|
||||
Log.w(
|
||||
"[Audio Manager] Couldn't find a contact for address "
|
||||
+ remoteAddress.asStringUriOnly());
|
||||
return false;
|
||||
} else {
|
||||
Log.i(
|
||||
"[Audio Manager] Contact found for address "
|
||||
+ remoteAddress.asStringUriOnly()
|
||||
+ ", we can ring");
|
||||
}
|
||||
} else if (callPolicy == NotificationManager.Policy.PRIORITY_SENDERS_STARRED) {
|
||||
Log.i("[Audio Manager] Priority for calls is Starred Contacts, let's check");
|
||||
if (contact == null) {
|
||||
Log.w(
|
||||
"[Audio Manager] Couldn't find a contact for address "
|
||||
+ remoteAddress.asStringUriOnly());
|
||||
return false;
|
||||
} else if (!contact.isFavourite()) {
|
||||
Log.w(
|
||||
"[Audio Manager] Contact found for address "
|
||||
+ remoteAddress.asStringUriOnly()
|
||||
+ ", but it isn't starred");
|
||||
return false;
|
||||
} else {
|
||||
Log.i(
|
||||
"[Audio Manager] Starred contact found for address "
|
||||
+ remoteAddress.asStringUriOnly()
|
||||
+ ", we can ring");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (filter == NotificationManager.INTERRUPTION_FILTER_ALARMS) {
|
||||
Log.w("[Audio Manager] Alarms interruption filter detected");
|
||||
return false;
|
||||
} else {
|
||||
Log.i("[Audio Manager] Interruption filter is " + filter + ", we can ring");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import android.content.Intent;
|
|||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.mediastream.Version;
|
||||
import org.linphone.notifications.Notifiable;
|
||||
|
||||
|
@ -228,4 +229,19 @@ public class Compatibility {
|
|||
ApiTwentyOnePlus.setTurnScreenOn(activity, enable);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDoNotDisturbSettingsAccessGranted(Context context) {
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
return ApiTwentyThreePlus.isDoNotDisturbSettingsAccessGranted(context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isDoNotDisturbPolicyAllowingRinging(
|
||||
Context context, Address remoteAddress) {
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
return ApiTwentyThreePlus.isDoNotDisturbPolicyAllowingRinging(context, remoteAddress);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
*/
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
|
@ -34,6 +35,8 @@ import org.linphone.R;
|
|||
import org.linphone.core.Core;
|
||||
import org.linphone.core.MediaEncryption;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.mediastream.Version;
|
||||
import org.linphone.settings.widget.BasicSetting;
|
||||
import org.linphone.settings.widget.ListSetting;
|
||||
import org.linphone.settings.widget.SettingListenerBase;
|
||||
import org.linphone.settings.widget.SwitchSetting;
|
||||
|
@ -50,6 +53,7 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
mAutoAnswer;
|
||||
private ListSetting mMediaEncryption;
|
||||
private TextSetting mAutoAnswerTime, mIncomingCallTimeout, mVoiceMailUri;
|
||||
private BasicSetting mDndPermissionSettings;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
@ -93,6 +97,9 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
|
||||
mVoiceMailUri = mRootView.findViewById(R.id.pref_voice_mail);
|
||||
mAutoAnswerTime.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
||||
|
||||
mDndPermissionSettings =
|
||||
mRootView.findViewById(R.id.pref_grant_read_dnd_settings_permission);
|
||||
}
|
||||
|
||||
private void setListeners() {
|
||||
|
@ -196,6 +203,15 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
mPrefs.setVoiceMailUri(newValue);
|
||||
}
|
||||
});
|
||||
|
||||
mDndPermissionSettings.setListener(
|
||||
new SettingListenerBase() {
|
||||
@Override
|
||||
public void onClicked() {
|
||||
startActivity(
|
||||
new Intent("android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateValues() {
|
||||
|
@ -218,6 +234,9 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
|
||||
mVoiceMailUri.setValue(mPrefs.getVoiceMailUri());
|
||||
|
||||
mDndPermissionSettings.setVisibility(
|
||||
Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60) ? View.VISIBLE : View.GONE);
|
||||
|
||||
setListeners();
|
||||
}
|
||||
|
||||
|
|
|
@ -889,6 +889,14 @@ public class LinphonePreferences {
|
|||
getConfig().setBool("app", "link_popup_enabled", enable);
|
||||
}
|
||||
|
||||
public boolean isDNDSettingsPopupEnabled() {
|
||||
return getConfig().getBool("app", "dnd_settings_popup_enabled", true);
|
||||
}
|
||||
|
||||
public void enableDNDSettingsPopup(boolean enable) {
|
||||
getConfig().setBool("app", "dnd_settings_popup_enabled", enable);
|
||||
}
|
||||
|
||||
public boolean isLimeSecurityPopupEnabled() {
|
||||
return getConfig().getBool("app", "lime_security_popup_enabled", true);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ import java.io.FileInputStream;
|
|||
import java.io.IOException;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.compatibility.Compatibility;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.CoreListenerStub;
|
||||
|
@ -82,7 +84,7 @@ public class AndroidAudioManager {
|
|||
requestAudioFocus(STREAM_RING);
|
||||
|
||||
mRingingCall = call;
|
||||
startRinging();
|
||||
startRinging(call.getRemoteAddress());
|
||||
// otherwise there is the beep
|
||||
}
|
||||
} else if (call == mRingingCall && mIsRinging) {
|
||||
|
@ -281,13 +283,20 @@ public class AndroidAudioManager {
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized void startRinging() {
|
||||
private synchronized void startRinging(Address remoteAddress) {
|
||||
if (!LinphonePreferences.instance().isDeviceRingtoneEnabled()) {
|
||||
// Enable speaker audio route, linphone library will do the ringing itself automatically
|
||||
routeAudioToSpeaker();
|
||||
return;
|
||||
}
|
||||
|
||||
boolean doNotDisturbPolicyAllowsRinging =
|
||||
Compatibility.isDoNotDisturbPolicyAllowingRinging(mContext, remoteAddress);
|
||||
if (!doNotDisturbPolicyAllowsRinging) {
|
||||
Log.e("[Audio Manager] Do not ring as Android Do Not Disturb Policy forbids it");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mContext.getResources().getBoolean(R.bool.allow_ringing_while_early_media)) {
|
||||
routeAudioToSpeaker(); // Need to be able to ear the ringtone during the early media
|
||||
}
|
||||
|
|
|
@ -23,6 +23,13 @@
|
|||
android:layout_height="wrap_content"
|
||||
linphone:title="@string/pref_vibrate_on_incoming_calls" />
|
||||
|
||||
<org.linphone.settings.widget.BasicSetting
|
||||
android:id="@+id/pref_grant_read_dnd_settings_permission"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
linphone:title="@string/pref_grant_read_dnd_settings_permission_title"
|
||||
linphone:subtitle="@string/pref_grant_read_dnd_settings_permission_desc"/>
|
||||
|
||||
<org.linphone.settings.widget.ListSetting
|
||||
android:id="@+id/pref_media_encryption"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -441,6 +441,8 @@
|
|||
<string name="pref_voice_mail">Voice mail URI</string>
|
||||
<string name="pref_dialer_call">Use Linphone as default phone app</string>
|
||||
<string name="pref_accept_early_media">Accept early-media</string>
|
||||
<string name="pref_grant_read_dnd_settings_permission_title">Do Not Disturb settings</string>
|
||||
<string name="pref_grant_read_dnd_settings_permission_desc">We need you to grant use the access to the Do Not Disturb settings to correctly ring or not depending on the current policy</string>
|
||||
|
||||
<!-- Chat settings -->
|
||||
<string name="pref_chat_title">Chat</string>
|
||||
|
|
Loading…
Reference in a new issue