From 3bbd3927d95c68083f4716ddb4a348955e7904b4 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Mon, 30 Jan 2023 00:34:55 -0500 Subject: [PATCH] Offer to setup dialler integration when relevant Rather than wait for the user to find the setting. --- .../conversations/ui/WelcomeActivity.java | 2 + .../ui/ConversationsActivity.java | 73 ++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/cheogram/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/cheogram/java/eu/siacs/conversations/ui/WelcomeActivity.java index 118bef03bf1a1755ca2a0ef1f359b9a8c2208192..9f91e0b687c8299ba15b8ab8e9573e0d74337e2c 100644 --- a/src/cheogram/java/eu/siacs/conversations/ui/WelcomeActivity.java +++ b/src/cheogram/java/eu/siacs/conversations/ui/WelcomeActivity.java @@ -19,6 +19,7 @@ import androidx.databinding.DataBindingUtil; import java.util.Arrays; import java.util.List; +import java.util.HashSet; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; @@ -118,6 +119,7 @@ public class WelcomeActivity extends XmppActivity implements XmppConnectionServi setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } super.onCreate(savedInstanceState); + getPreferences().edit().putStringSet("pstn_gateways", new HashSet<>()).apply(); ActivityWelcomeBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_welcome); setSupportActionBar(binding.toolbar); configureActionBar(getSupportActionBar(), false); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java index eebec59891c9624f5a7780a077f5a69cf874ef47..a78152ba4633e78344bfc943a2adbd439cc95e1c 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java @@ -32,16 +32,19 @@ package eu.siacs.conversations.ui; import static eu.siacs.conversations.ui.ConversationFragment.REQUEST_DECRYPT_PGP; +import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.ActivityNotFoundException; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.util.Log; @@ -60,6 +63,8 @@ import org.openintents.openpgp.util.OpenPgpApi; import java.util.Arrays; import java.util.List; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import eu.siacs.conversations.Config; @@ -110,6 +115,8 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio public static final int REQUEST_OPEN_MESSAGE = 0x9876; public static final int REQUEST_PLAY_PAUSE = 0x5432; + public static final int REQUEST_MICROPHONE = 0x5432f; + public static final int DIALLER_INTEGRATION = 0x5432ff; //secondary fragment (when holding the conversation, must be initialized before refreshing the overview fragment @@ -121,6 +128,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio private boolean mActivityPaused = true; private final AtomicBoolean mRedirectInProcess = new AtomicBoolean(false); private boolean refreshForNewCaps = false; + private int mRequestCode = -1; private static boolean isViewOrShareIntent(Intent i) { Log.d(Config.LOGTAG, "action: " + (i == null ? null : i.getAction())); @@ -211,7 +219,9 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio if (ExceptionHelper.checkForCrash(this)) { return; } - openBatteryOptimizationDialogIfNeeded(); + if (!offerToSetupDiallerIntegration()) { + openBatteryOptimizationDialogIfNeeded(); + } } } @@ -248,6 +258,54 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio } } + private boolean offerToSetupDiallerIntegration() { + if (mRequestCode == DIALLER_INTEGRATION) { + mRequestCode = -1; + return true; + } + if (Build.VERSION.SDK_INT < 23) return false; + if (Build.VERSION.SDK_INT >= 33) { + if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELECOM)) return false; + } else { + if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE)) return false; + } + + Set pstnGateways = new HashSet<>(); + for (Account account : xmppConnectionService.getAccounts()) { + for (Contact contact : account.getRoster().getContacts()) { + if (contact.getPresences().anyIdentity("gateway", "pstn")) { + pstnGateways.add(contact.getJid().asBareJid().toEscapedString()); + } + } + } + + if (pstnGateways.size() < 1) return false; + Set fromPrefs = getPreferences().getStringSet("pstn_gateways", Set.of("UPGRADE")); + getPreferences().edit().putStringSet("pstn_gateways", pstnGateways).apply(); + pstnGateways.removeAll(fromPrefs); + if (pstnGateways.size() < 1) return false; + + if (fromPrefs.contains("UPGRADE")) return false; + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("Dialler Integration"); + builder.setMessage("Cheogram Android is able to integrate with your system's dialler app to allow dialling calls via your configured gateway " + String.join(", ", pstnGateways) + ".\n\nEnabling this integration will require granting microphone permission to the app. Would you like to enable it now?"); + builder.setPositiveButton(R.string.yes, (dialog, which) -> { + final String[] permissions; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + permissions = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.BLUETOOTH_CONNECT}; + } else { + permissions = new String[]{Manifest.permission.RECORD_AUDIO}; + } + requestPermissions(permissions, REQUEST_MICROPHONE); + }); + builder.setNegativeButton(R.string.no, (dialog, which) -> { }); + final AlertDialog dialog = builder.create(); + dialog.setCanceledOnTouchOutside(false); + dialog.show(); + return true; + } + private void notifyFragmentOfBackendConnected(@IdRes int id) { final Fragment fragment = getFragmentManager().findFragmentById(id); if (fragment instanceof OnBackendConnected) { @@ -288,6 +346,12 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio case REQUEST_PLAY_PAUSE: ConversationFragment.startStopPending(this); break; + case REQUEST_MICROPHONE: + Intent intent = new Intent(); + intent.setComponent(new ComponentName("com.android.server.telecom", + "com.android.server.telecom.settings.EnableAccountPreferenceActivity")); + startActivityForResult(intent, DIALLER_INTEGRATION); + break; } } } @@ -296,6 +360,13 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio @Override public void onActivityResult(int requestCode, int resultCode, final Intent data) { super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == DIALLER_INTEGRATION) { + mRequestCode = requestCode; + startActivity(new Intent(android.telecom.TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS)); + return; + } + ActivityResult activityResult = ActivityResult.of(requestCode, resultCode, data); if (xmppConnectionService != null) { handleActivityResult(activityResult);