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 -->
|
<!-- Needed for kill application yourself -->
|
||||||
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
|
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<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
|
<supports-screens
|
||||||
android:anyDensity="true"
|
android:anyDensity="true"
|
||||||
|
|
|
@ -35,6 +35,7 @@ import android.os.Bundle;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
@ -232,6 +233,11 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
||||||
LinphoneManager.getInstance().isAccountWithAlias();
|
LinphoneManager.getInstance().isAccountWithAlias();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Compatibility.isDoNotDisturbSettingsAccessGranted(
|
||||||
|
MainActivity.this)) {
|
||||||
|
displayDNDSettingsDialog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,6 +673,50 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
||||||
dialog.show();
|
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
|
// Logs
|
||||||
|
|
||||||
private void shareUploadedLogsUrl(String info) {
|
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.annotation.TargetApi;
|
||||||
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.PowerManager;
|
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)
|
@TargetApi(23)
|
||||||
class ApiTwentyThreePlus {
|
class ApiTwentyThreePlus {
|
||||||
|
@ -29,4 +34,82 @@ class ApiTwentyThreePlus {
|
||||||
public static boolean isAppIdleMode(Context context) {
|
public static boolean isAppIdleMode(Context context) {
|
||||||
return ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).isDeviceIdleMode();
|
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.graphics.Bitmap;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import org.linphone.core.Address;
|
||||||
import org.linphone.mediastream.Version;
|
import org.linphone.mediastream.Version;
|
||||||
import org.linphone.notifications.Notifiable;
|
import org.linphone.notifications.Notifiable;
|
||||||
|
|
||||||
|
@ -228,4 +229,19 @@ public class Compatibility {
|
||||||
ApiTwentyOnePlus.setTurnScreenOn(activity, enable);
|
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.Manifest;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
|
@ -34,6 +35,8 @@ import org.linphone.R;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.MediaEncryption;
|
import org.linphone.core.MediaEncryption;
|
||||||
import org.linphone.core.tools.Log;
|
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.ListSetting;
|
||||||
import org.linphone.settings.widget.SettingListenerBase;
|
import org.linphone.settings.widget.SettingListenerBase;
|
||||||
import org.linphone.settings.widget.SwitchSetting;
|
import org.linphone.settings.widget.SwitchSetting;
|
||||||
|
@ -50,6 +53,7 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
mAutoAnswer;
|
mAutoAnswer;
|
||||||
private ListSetting mMediaEncryption;
|
private ListSetting mMediaEncryption;
|
||||||
private TextSetting mAutoAnswerTime, mIncomingCallTimeout, mVoiceMailUri;
|
private TextSetting mAutoAnswerTime, mIncomingCallTimeout, mVoiceMailUri;
|
||||||
|
private BasicSetting mDndPermissionSettings;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,6 +97,9 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
|
|
||||||
mVoiceMailUri = mRootView.findViewById(R.id.pref_voice_mail);
|
mVoiceMailUri = mRootView.findViewById(R.id.pref_voice_mail);
|
||||||
mAutoAnswerTime.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
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() {
|
private void setListeners() {
|
||||||
|
@ -196,6 +203,15 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
mPrefs.setVoiceMailUri(newValue);
|
mPrefs.setVoiceMailUri(newValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mDndPermissionSettings.setListener(
|
||||||
|
new SettingListenerBase() {
|
||||||
|
@Override
|
||||||
|
public void onClicked() {
|
||||||
|
startActivity(
|
||||||
|
new Intent("android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS"));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateValues() {
|
private void updateValues() {
|
||||||
|
@ -218,6 +234,9 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
|
|
||||||
mVoiceMailUri.setValue(mPrefs.getVoiceMailUri());
|
mVoiceMailUri.setValue(mPrefs.getVoiceMailUri());
|
||||||
|
|
||||||
|
mDndPermissionSettings.setVisibility(
|
||||||
|
Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60) ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
setListeners();
|
setListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -889,6 +889,14 @@ public class LinphonePreferences {
|
||||||
getConfig().setBool("app", "link_popup_enabled", enable);
|
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() {
|
public boolean isLimeSecurityPopupEnabled() {
|
||||||
return getConfig().getBool("app", "lime_security_popup_enabled", true);
|
return getConfig().getBool("app", "lime_security_popup_enabled", true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.compatibility.Compatibility;
|
||||||
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.CoreListenerStub;
|
import org.linphone.core.CoreListenerStub;
|
||||||
|
@ -82,7 +84,7 @@ public class AndroidAudioManager {
|
||||||
requestAudioFocus(STREAM_RING);
|
requestAudioFocus(STREAM_RING);
|
||||||
|
|
||||||
mRingingCall = call;
|
mRingingCall = call;
|
||||||
startRinging();
|
startRinging(call.getRemoteAddress());
|
||||||
// otherwise there is the beep
|
// otherwise there is the beep
|
||||||
}
|
}
|
||||||
} else if (call == mRingingCall && mIsRinging) {
|
} 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()) {
|
if (!LinphonePreferences.instance().isDeviceRingtoneEnabled()) {
|
||||||
// Enable speaker audio route, linphone library will do the ringing itself automatically
|
// Enable speaker audio route, linphone library will do the ringing itself automatically
|
||||||
routeAudioToSpeaker();
|
routeAudioToSpeaker();
|
||||||
return;
|
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)) {
|
if (mContext.getResources().getBoolean(R.bool.allow_ringing_while_early_media)) {
|
||||||
routeAudioToSpeaker(); // Need to be able to ear the ringtone during the early media
|
routeAudioToSpeaker(); // Need to be able to ear the ringtone during the early media
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,13 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
linphone:title="@string/pref_vibrate_on_incoming_calls" />
|
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
|
<org.linphone.settings.widget.ListSetting
|
||||||
android:id="@+id/pref_media_encryption"
|
android:id="@+id/pref_media_encryption"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -441,6 +441,8 @@
|
||||||
<string name="pref_voice_mail">Voice mail URI</string>
|
<string name="pref_voice_mail">Voice mail URI</string>
|
||||||
<string name="pref_dialer_call">Use Linphone as default phone app</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_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 -->
|
<!-- Chat settings -->
|
||||||
<string name="pref_chat_title">Chat</string>
|
<string name="pref_chat_title">Chat</string>
|
||||||
|
|
Loading…
Reference in a new issue