request recording permission when making or accepting audio calls

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 15 
src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java   | 51 
src/main/java/eu/siacs/conversations/utils/PermissionUtils.java   | 26 
3 files changed, 85 insertions(+), 7 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java πŸ”—

@@ -109,6 +109,7 @@ import eu.siacs.conversations.utils.GeoHelper;
 import eu.siacs.conversations.utils.MessageUtils;
 import eu.siacs.conversations.utils.NickValidityChecker;
 import eu.siacs.conversations.utils.Patterns;
+import eu.siacs.conversations.utils.PermissionUtils;
 import eu.siacs.conversations.utils.QuickLoader;
 import eu.siacs.conversations.utils.StylingHelper;
 import eu.siacs.conversations.utils.TimeframeUtils;
@@ -138,6 +139,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
     public static final int REQUEST_START_DOWNLOAD = 0x0210;
     public static final int REQUEST_ADD_EDITOR_CONTENT = 0x0211;
     public static final int REQUEST_COMMIT_ATTACHMENTS = 0x0212;
+    public static final int REQUEST_START_AUDIO_CALL = 0x213;
     public static final int ATTACHMENT_CHOICE_CHOOSE_IMAGE = 0x0301;
     public static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x0302;
     public static final int ATTACHMENT_CHOICE_CHOOSE_FILE = 0x0303;
@@ -1233,7 +1235,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
                 }
                 break;
             case R.id.action_call:
-                triggerRtpSession();
+                checkPermissionAndTriggerRtpSession();
                 break;
             default:
                 break;
@@ -1241,6 +1243,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
         return super.onOptionsItemSelected(item);
     }
 
+    private void checkPermissionAndTriggerRtpSession() {
+        if (hasPermissions(REQUEST_START_AUDIO_CALL, Manifest.permission.RECORD_AUDIO)) {
+            triggerRtpSession();
+        }
+    }
+
     private void triggerRtpSession() {
         final Contact contact = conversation.getContact();
         final Intent intent = new Intent(activity, RtpSessionActivity.class);
@@ -1383,7 +1391,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
     }
 
     @Override
-    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
         if (grantResults.length > 0) {
             if (allGranted(grantResults)) {
                 switch (requestCode) {
@@ -1400,6 +1408,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
                     case REQUEST_COMMIT_ATTACHMENTS:
                         commitAttachments();
                         break;
+                    case REQUEST_START_AUDIO_CALL:
+                        triggerRtpSession();
+                        break;
                     default:
                         attachFile(requestCode);
                         break;

src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java πŸ”—

@@ -1,14 +1,24 @@
 package eu.siacs.conversations.ui;
 
+import android.Manifest;
+import android.app.Activity;
 import android.content.Intent;
-import android.content.res.ColorStateList;
+import android.content.pm.PackageManager;
 import android.databinding.DataBindingUtil;
+import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
+import android.support.v4.app.ActivityCompat;
 import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
+import android.widget.Toast;
+
+import com.google.common.collect.ImmutableList;
 
 import java.lang.ref.WeakReference;
+import java.util.List;
 
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
@@ -16,17 +26,21 @@ import eu.siacs.conversations.databinding.ActivityRtpSessionBinding;
 import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Contact;
 import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.utils.PermissionUtils;
 import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
 import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
 import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
 import rocks.xmpp.addr.Jid;
 
+import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied;
 import static java.util.Arrays.asList;
 
 //TODO if last state was BUSY (or RETRY); we want to reset action to view or something so we don’t automatically call again on recreate
 
 public class RtpSessionActivity extends XmppActivity implements XmppConnectionService.OnJingleRtpConnectionUpdate {
 
+    private static final int REQUEST_ACCEPT_CALL = 0x1111;
+
     public static final String EXTRA_WITH = "with";
     public static final String EXTRA_SESSION_ID = "session_id";
     public static final String EXTRA_LAST_REPORTED_STATE = "last_reported_state";
@@ -75,7 +89,13 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
     }
 
     private void acceptCall(View view) {
-        requireRtpConnection().acceptCall();
+        requestPermissionsAndAcceptCall();
+    }
+
+    private void requestPermissionsAndAcceptCall() {
+        if (PermissionUtils.hasPermission(this, ImmutableList.of(Manifest.permission.RECORD_AUDIO), REQUEST_ACCEPT_CALL)) {
+            requireRtpConnection().acceptCall();
+        }
     }
 
     @Override
@@ -89,7 +109,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
         //TODO reinitialize
         if (ACTION_ACCEPT_CALL.equals(intent.getAction())) {
             Log.d(Config.LOGTAG, "accepting through onNewIntent()");
-            requireRtpConnection().acceptCall();
+            requestPermissionsAndAcceptCall();
         }
     }
 
@@ -103,7 +123,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
             initializeActivityWithRunningRapSession(account, with, sessionId);
             if (ACTION_ACCEPT_CALL.equals(intent.getAction())) {
                 Log.d(Config.LOGTAG, "intent action was accept");
-                requireRtpConnection().acceptCall();
+                requestPermissionsAndAcceptCall();
             }
         } else if (asList(ACTION_MAKE_VIDEO_CALL, ACTION_MAKE_VOICE_CALL).contains(intent.getAction())) {
             xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(account, with);
@@ -120,6 +140,27 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
         }
     }
 
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        if (PermissionUtils.allGranted(grantResults)) {
+            if (requestCode == REQUEST_ACCEPT_CALL) {
+                requireRtpConnection().acceptCall();
+            }
+        } else {
+            @StringRes int res;
+            final String firstDenied = getFirstDenied(grantResults, permissions);
+            if (Manifest.permission.RECORD_AUDIO.equals(firstDenied)) {
+                res = R.string.no_microphone_permission;
+            } else if (Manifest.permission.CAMERA.equals(firstDenied)) {
+                res = R.string.no_camera_permission;
+            } else {
+                throw new IllegalStateException("Invalid permission result request");
+            }
+            Toast.makeText(this, res, Toast.LENGTH_SHORT).show();
+        }
+    }
+
 
     private void initializeActivityWithRunningRapSession(final Account account, Jid with, String sessionId) {
         final WeakReference<JingleRtpConnection> reference = xmppConnectionService.getJingleConnectionManager()
@@ -226,7 +267,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
     }
 
     private void retry(View view) {
-        Log.d(Config.LOGTAG,"attempting retry");
+        Log.d(Config.LOGTAG, "attempting retry");
     }
 
     private void exit(View view) {

src/main/java/eu/siacs/conversations/utils/PermissionUtils.java πŸ”—

@@ -1,7 +1,14 @@
 package eu.siacs.conversations.utils;
 
 import android.Manifest;
+import android.app.Activity;
 import android.content.pm.PackageManager;
+import android.os.Build;
+import android.support.v4.app.ActivityCompat;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
 
 public class PermissionUtils {
 
@@ -31,4 +38,23 @@ public class PermissionUtils {
         }
         return null;
     }
+
+    public static boolean hasPermission(final Activity activity, final List<String> permissions, final int requestCode) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            final ImmutableList.Builder<String> missingPermissions = new ImmutableList.Builder<>();
+            for (final String permission : permissions) {
+                if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
+                    missingPermissions.add(permission);
+                }
+            }
+            final ImmutableList<String> missing = missingPermissions.build();
+            if (missing.size() == 0) {
+                return true;
+            }
+            ActivityCompat.requestPermissions(activity, missing.toArray(new String[0]), requestCode);
+            return false;
+        } else {
+            return true;
+        }
+    }
 }