From f27ea32045d2f13e2785de9b20be09ad085cb0f6 Mon Sep 17 00:00:00 2001 From: Johnny Date: Thu, 20 Sep 2018 22:54:18 +0800 Subject: [PATCH 1/4] update gitignore --- .gitignore | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/.gitignore b/.gitignore index 0cb0875..ca9de37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,68 @@ +*.iml .gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store /build +/captures +.externalNativeBuild + +# Built application files +*.apk +*.ap_ + +# Files for the Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ +/*/build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Windows thumbnail db +Thumbs.db + +# Eclipse project files +.classpath +.project + +# Android Studio +.idea +*.iml + +# Old-style IDEA project files +*.ipr +*.iws + +# Local IDEA workspace +.idea/workspace.xml + +# Sandbox stuff +_sandbox + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +/*/out +/*/*/build +/*/*/production +*.iws +*.ipr *~ +*.swp +signingConfig.gradle From 170f3bd6872129280f78a1762596faf8c96d4768 Mon Sep 17 00:00:00 2001 From: Johnny Date: Thu, 20 Sep 2018 22:56:32 +0800 Subject: [PATCH 2/4] remove unused files --- .idea/compiler.xml | 23 ------ .idea/copyright/Apache2_0.xml | 9 --- .idea/copyright/profiles_settings.xml | 3 - .idea/encodings.xml | 5 -- .idea/gradle.xml | 19 ----- .idea/misc.xml | 26 ------- .idea/modules.xml | 11 --- .idea/scopes/scope_settings.xml | 5 -- .idea/vcs.xml | 7 -- AndroidRTC.iml | 19 ----- app/app.iml | 97 ------------------------- webrtc-client/app.iml | 96 ------------------------ webrtc-client/webrtc-client.iml | 101 -------------------------- 13 files changed, 421 deletions(-) delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/copyright/Apache2_0.xml delete mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/scopes/scope_settings.xml delete mode 100644 .idea/vcs.xml delete mode 100644 AndroidRTC.iml delete mode 100644 app/app.iml delete mode 100644 webrtc-client/app.iml delete mode 100644 webrtc-client/webrtc-client.iml diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 217af47..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/.idea/copyright/Apache2_0.xml b/.idea/copyright/Apache2_0.xml deleted file mode 100644 index a48441d..0000000 --- a/.idea/copyright/Apache2_0.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index d122754..0000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index e206d70..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index d89719d..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 8cd1ba2..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index e6172eb..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b..0000000 --- a/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 275077f..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/AndroidRTC.iml b/AndroidRTC.iml deleted file mode 100644 index 0bb6048..0000000 --- a/AndroidRTC.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/app/app.iml b/app/app.iml deleted file mode 100644 index 4662fbf..0000000 --- a/app/app.iml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/webrtc-client/app.iml b/webrtc-client/app.iml deleted file mode 100644 index f6c171e..0000000 --- a/webrtc-client/app.iml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/webrtc-client/webrtc-client.iml b/webrtc-client/webrtc-client.iml deleted file mode 100644 index 6d5bb03..0000000 --- a/webrtc-client/webrtc-client.iml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 467a504873ab4ca0c518114d4d44e4b5fde8dd02 Mon Sep 17 00:00:00 2001 From: Johnny Date: Thu, 20 Sep 2018 22:57:20 +0800 Subject: [PATCH 3/4] Update library --- app/build.gradle | 10 +- .../java/fr/pchab/androidrtc/RtcActivity.java | 20 ++-- build.gradle | 10 +- gradle/wrapper/gradle-wrapper.properties | 4 +- webrtc-client/build.gradle | 10 +- .../fr/pchab/webrtcclient/WebRtcClient.java | 104 +++++++++++------- 6 files changed, 94 insertions(+), 64 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6ef1cc2..1d60280 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 22 - buildToolsVersion "22.0.0" + compileSdkVersion 27 + buildToolsVersion '27.0.3' defaultConfig { applicationId "fr.pchab.androidrtc" minSdkVersion 15 - targetSdkVersion 22 + targetSdkVersion 27 versionCode 1 versionName "1.0" } @@ -20,6 +20,6 @@ android { } dependencies { - compile 'com.android.support:appcompat-v7:22.0.0' - compile project(':webrtc-client') + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation project(':webrtc-client') } diff --git a/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java b/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java index edf2721..6319264 100644 --- a/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java +++ b/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java @@ -8,15 +8,17 @@ import android.view.Window; import android.view.WindowManager.LayoutParams; import android.widget.Toast; + import org.json.JSONException; import org.webrtc.MediaStream; import org.webrtc.VideoRenderer; import org.webrtc.VideoRendererGui; -import fr.pchab.webrtcclient.WebRtcClient; -import fr.pchab.webrtcclient.PeerConnectionParameters; import java.util.List; +import fr.pchab.webrtcclient.PeerConnectionParameters; +import fr.pchab.webrtcclient.WebRtcClient; + public class RtcActivity extends Activity implements WebRtcClient.RtcListener { private final static int VIDEO_CALL_SENT = 666; private static final String VIDEO_CODEC_VP9 = "VP9"; @@ -98,7 +100,7 @@ private void init() { public void onPause() { super.onPause(); vsv.onPause(); - if(client != null) { + if (client != null) { client.onPause(); } } @@ -107,14 +109,14 @@ public void onPause() { public void onResume() { super.onResume(); vsv.onResume(); - if(client != null) { + if (client != null) { client.onResume(); } } @Override public void onDestroy() { - if(client != null) { + if (client != null) { client.onDestroy(); } super.onDestroy(); @@ -173,7 +175,7 @@ public void onLocalStream(MediaStream localStream) { VideoRendererGui.update(localRender, LOCAL_X_CONNECTING, LOCAL_Y_CONNECTING, LOCAL_WIDTH_CONNECTING, LOCAL_HEIGHT_CONNECTING, - scalingType); + scalingType, false); } @Override @@ -181,11 +183,11 @@ public void onAddRemoteStream(MediaStream remoteStream, int endPoint) { remoteStream.videoTracks.get(0).addRenderer(new VideoRenderer(remoteRender)); VideoRendererGui.update(remoteRender, REMOTE_X, REMOTE_Y, - REMOTE_WIDTH, REMOTE_HEIGHT, scalingType); + REMOTE_WIDTH, REMOTE_HEIGHT, scalingType, false); VideoRendererGui.update(localRender, LOCAL_X_CONNECTED, LOCAL_Y_CONNECTED, LOCAL_WIDTH_CONNECTED, LOCAL_HEIGHT_CONNECTED, - scalingType); + scalingType, false); } @Override @@ -193,6 +195,6 @@ public void onRemoveRemoteStream(int endPoint) { VideoRendererGui.update(localRender, LOCAL_X_CONNECTING, LOCAL_Y_CONNECTING, LOCAL_WIDTH_CONNECTING, LOCAL_HEIGHT_CONNECTING, - scalingType); + scalingType, false); } } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 0ed3de3..9608a88 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,13 @@ buildscript { repositories { jcenter() + maven { + url 'https://maven.google.com/' + name 'Google' + } } dependencies { - classpath 'com.android.tools.build:gradle:1.1.2' + classpath 'com.android.tools.build:gradle:3.1.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -14,5 +18,9 @@ buildscript { allprojects { repositories { jcenter() + maven { + url 'https://maven.google.com/' + name 'Google' + } } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0c71e76..ea726c0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 10 15:27:10 PDT 2013 +#Thu Sep 20 22:29:03 CST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/webrtc-client/build.gradle b/webrtc-client/build.gradle index 26ef5c1..11dba9b 100644 --- a/webrtc-client/build.gradle +++ b/webrtc-client/build.gradle @@ -2,12 +2,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 22 - buildToolsVersion "22.0.0" + compileSdkVersion 27 + buildToolsVersion '27.0.3' defaultConfig { minSdkVersion 15 - targetSdkVersion 22 + targetSdkVersion 27 versionCode 1 versionName "1.0" } @@ -20,6 +20,6 @@ android { } dependencies { - compile 'com.github.nkzawa:socket.io-client:0.4.2' - compile 'io.pristine:libjingle:8871@aar' + implementation 'com.github.nkzawa:socket.io-client:0.4.2' + api 'io.pristine:libjingle:9127@aar' } diff --git a/webrtc-client/src/main/java/fr/pchab/webrtcclient/WebRtcClient.java b/webrtc-client/src/main/java/fr/pchab/webrtcclient/WebRtcClient.java index 6bf58ff..1b17ec5 100644 --- a/webrtc-client/src/main/java/fr/pchab/webrtcclient/WebRtcClient.java +++ b/webrtc-client/src/main/java/fr/pchab/webrtcclient/WebRtcClient.java @@ -1,18 +1,30 @@ package fr.pchab.webrtcclient; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.LinkedList; +import android.opengl.EGLContext; +import android.util.Log; +import com.github.nkzawa.emitter.Emitter; import com.github.nkzawa.socketio.client.IO; import com.github.nkzawa.socketio.client.Socket; -import com.github.nkzawa.emitter.Emitter; + import org.json.JSONException; import org.json.JSONObject; +import org.webrtc.AudioSource; +import org.webrtc.DataChannel; +import org.webrtc.IceCandidate; +import org.webrtc.MediaConstraints; +import org.webrtc.MediaStream; +import org.webrtc.PeerConnection; +import org.webrtc.PeerConnectionFactory; +import org.webrtc.SdpObserver; +import org.webrtc.SessionDescription; +import org.webrtc.VideoCapturer; +import org.webrtc.VideoCapturerAndroid; +import org.webrtc.VideoSource; -import android.opengl.EGLContext; -import android.util.Log; -import org.webrtc.*; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.LinkedList; public class WebRtcClient { private final static String TAG = WebRtcClient.class.getCanonicalName(); @@ -31,7 +43,7 @@ public class WebRtcClient { /** * Implement this interface to be notified of events. */ - public interface RtcListener{ + public interface RtcListener { void onCallReady(String callId); void onStatusChanged(String newStatus); @@ -43,21 +55,21 @@ public interface RtcListener{ void onRemoveRemoteStream(int endPoint); } - private interface Command{ + private interface Command { void execute(String peerId, JSONObject payload) throws JSONException; } - private class CreateOfferCommand implements Command{ + private class CreateOfferCommand implements Command { public void execute(String peerId, JSONObject payload) throws JSONException { - Log.d(TAG,"CreateOfferCommand"); + Log.d(TAG, "CreateOfferCommand"); Peer peer = peers.get(peerId); peer.pc.createOffer(peer, pcConstraints); } } - private class CreateAnswerCommand implements Command{ + private class CreateAnswerCommand implements Command { public void execute(String peerId, JSONObject payload) throws JSONException { - Log.d(TAG,"CreateAnswerCommand"); + Log.d(TAG, "CreateAnswerCommand"); Peer peer = peers.get(peerId); SessionDescription sdp = new SessionDescription( SessionDescription.Type.fromCanonicalForm(payload.getString("type")), @@ -68,9 +80,9 @@ public void execute(String peerId, JSONObject payload) throws JSONException { } } - private class SetRemoteSDPCommand implements Command{ + private class SetRemoteSDPCommand implements Command { public void execute(String peerId, JSONObject payload) throws JSONException { - Log.d(TAG,"SetRemoteSDPCommand"); + Log.d(TAG, "SetRemoteSDPCommand"); Peer peer = peers.get(peerId); SessionDescription sdp = new SessionDescription( SessionDescription.Type.fromCanonicalForm(payload.getString("type")), @@ -80,9 +92,9 @@ public void execute(String peerId, JSONObject payload) throws JSONException { } } - private class AddIceCandidateCommand implements Command{ + private class AddIceCandidateCommand implements Command { public void execute(String peerId, JSONObject payload) throws JSONException { - Log.d(TAG,"AddIceCandidateCommand"); + Log.d(TAG, "AddIceCandidateCommand"); PeerConnection pc = peers.get(peerId).pc; if (pc.getRemoteDescription() != null) { IceCandidate candidate = new IceCandidate( @@ -98,8 +110,8 @@ public void execute(String peerId, JSONObject payload) throws JSONException { /** * Send a message through the signaling server * - * @param to id of recipient - * @param type type of message + * @param to id of recipient + * @param type type of message * @param payload payload of message * @throws JSONException */ @@ -130,14 +142,14 @@ public void call(Object... args) { String from = data.getString("from"); String type = data.getString("type"); JSONObject payload = null; - if(!type.equals("init")) { + if (!type.equals("init")) { payload = data.getJSONObject("payload"); } // if peer is unknown, try to add him - if(!peers.containsKey(from)) { + if (!peers.containsKey(from)) { // if MAX_PEER is reach, ignore the call int endPoint = findEndPoint(); - if(endPoint != MAX_PEER) { + if (endPoint != MAX_PEER) { Peer peer = addPeer(from, endPoint); peer.pc.addStream(localMS); commandMap.get(type).execute(from, payload); @@ -160,7 +172,7 @@ public void call(Object... args) { }; } - private class Peer implements SdpObserver, PeerConnection.Observer{ + private class Peer implements SdpObserver, PeerConnection.Observer { private PeerConnection pc; private String id; private int endPoint; @@ -180,27 +192,32 @@ public void onCreateSuccess(final SessionDescription sdp) { } @Override - public void onSetSuccess() {} + public void onSetSuccess() { + } @Override - public void onCreateFailure(String s) {} + public void onCreateFailure(String s) { + } @Override - public void onSetFailure(String s) {} + public void onSetFailure(String s) { + } @Override - public void onSignalingChange(PeerConnection.SignalingState signalingState) {} + public void onSignalingChange(PeerConnection.SignalingState signalingState) { + } @Override public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) { - if(iceConnectionState == PeerConnection.IceConnectionState.DISCONNECTED) { + if (iceConnectionState == PeerConnection.IceConnectionState.DISCONNECTED) { removePeer(id); mListener.onStatusChanged("DISCONNECTED"); } } @Override - public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {} + public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) { + } @Override public void onIceCandidate(final IceCandidate candidate) { @@ -217,19 +234,20 @@ public void onIceCandidate(final IceCandidate candidate) { @Override public void onAddStream(MediaStream mediaStream) { - Log.d(TAG,"onAddStream "+mediaStream.label()); + Log.d(TAG, "onAddStream " + mediaStream.label()); // remote streams are displayed from 1 to MAX_PEER (0 is localStream) - mListener.onAddRemoteStream(mediaStream, endPoint+1); + mListener.onAddRemoteStream(mediaStream, endPoint + 1); } @Override public void onRemoveStream(MediaStream mediaStream) { - Log.d(TAG,"onRemoveStream "+mediaStream.label()); + Log.d(TAG, "onRemoveStream " + mediaStream.label()); removePeer(id); } @Override - public void onDataChannel(DataChannel dataChannel) {} + public void onDataChannel(DataChannel dataChannel) { + } @Override public void onRenegotiationNeeded() { @@ -237,7 +255,7 @@ public void onRenegotiationNeeded() { } public Peer(String id, int endPoint) { - Log.d(TAG,"new Peer: "+id + " " + endPoint); + Log.d(TAG, "new Peer: " + id + " " + endPoint); this.pc = factory.createPeerConnection(iceServers, pcConstraints, this); this.id = id; this.endPoint = endPoint; @@ -293,14 +311,14 @@ public WebRtcClient(RtcListener listener, String host, PeerConnectionParameters * Call this method in Activity.onPause() */ public void onPause() { - if(videoSource != null) videoSource.stop(); + if (videoSource != null) videoSource.stop(); } /** * Call this method in Activity.onResume() */ public void onResume() { - if(videoSource != null) videoSource.restart(); + if (videoSource != null) videoSource.restart(); } /** @@ -310,26 +328,28 @@ public void onDestroy() { for (Peer peer : peers.values()) { peer.pc.dispose(); } - videoSource.dispose(); + if (videoSource != null) { + videoSource.dispose(); + } factory.dispose(); client.disconnect(); client.close(); } private int findEndPoint() { - for(int i = 0; i < MAX_PEER; i++) if (!endPoints[i]) return i; + for (int i = 0; i < MAX_PEER; i++) if (!endPoints[i]) return i; return MAX_PEER; } /** * Start the client. - * + *

* Set up the local stream and notify the signaling server. * Call this method after onCallReady. * * @param name client name */ - public void start(String name){ + public void start(String name) { setCamera(); try { JSONObject message = new JSONObject(); @@ -340,9 +360,9 @@ public void start(String name){ } } - private void setCamera(){ + private void setCamera() { localMS = factory.createLocalMediaStream("ARDAMS"); - if(pcParams.videoCallEnabled){ + if (pcParams.videoCallEnabled) { MediaConstraints videoConstraints = new MediaConstraints(); videoConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxHeight", Integer.toString(pcParams.videoHeight))); videoConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxWidth", Integer.toString(pcParams.videoWidth))); From 12b0185cddb2c43ee9f3bfe5b6b8c2c114006067 Mon Sep 17 00:00:00 2001 From: Johnny Date: Thu, 20 Sep 2018 23:49:00 +0800 Subject: [PATCH 4/4] Add permission request prompt for android 6.0+ --- .../pchab/androidrtc/PermissionChecker.java | 74 +++++++++++++++++++ .../java/fr/pchab/androidrtc/RtcActivity.java | 31 +++++++- 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/fr/pchab/androidrtc/PermissionChecker.java diff --git a/app/src/main/java/fr/pchab/androidrtc/PermissionChecker.java b/app/src/main/java/fr/pchab/androidrtc/PermissionChecker.java new file mode 100644 index 0000000..c7755ec --- /dev/null +++ b/app/src/main/java/fr/pchab/androidrtc/PermissionChecker.java @@ -0,0 +1,74 @@ +package fr.pchab.androidrtc; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; + +import java.util.ArrayList; + +public class PermissionChecker { + + private final int REQUEST_MULTIPLE_PERMISSION = 100; + private VerifyPermissionsCallback callbackMultiple; + + public void verifyPermissions(Activity activity, @NonNull String[] permissions, VerifyPermissionsCallback callback) { + String[] denyPermissions = getDenyPermissions(activity, permissions); + if (denyPermissions.length > 0) { + ActivityCompat.requestPermissions(activity, denyPermissions, REQUEST_MULTIPLE_PERMISSION); + this.callbackMultiple = callback; + } else { + if (callback != null) { + callback.onPermissionAllGranted(); + } + } + } + + private String[] getDenyPermissions(@NonNull Context context, @NonNull String[] permissions) { + ArrayList denyPermissions = new ArrayList<>(); + for (String permission : permissions) { + if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { + denyPermissions.add(permission); + } + } + return denyPermissions.toArray(new String[0]); + } + + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + switch (requestCode) { + case REQUEST_MULTIPLE_PERMISSION: + if (grantResults.length > 0 && callbackMultiple != null) { + ArrayList denyPermissions = new ArrayList<>(); + int i = 0; + for (String permission : permissions) { + if (grantResults[i] == PackageManager.PERMISSION_DENIED) { + denyPermissions.add(permission); + } + i++; + } + if (denyPermissions.size() == 0) { + callbackMultiple.onPermissionAllGranted(); + } else { + callbackMultiple.onPermissionDeny(denyPermissions.toArray(new String[0])); + } + } + break; + } + } + + public static boolean hasPermissions(@NonNull Context context, @NonNull String[] permissions) { + for (String permission : permissions) { + if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + return true; + } + + public interface VerifyPermissionsCallback { + void onPermissionAllGranted(); + + void onPermissionDeny(String[] permissions); + } +} diff --git a/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java b/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java index 6319264..2c04a7f 100644 --- a/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java +++ b/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java @@ -1,10 +1,12 @@ package fr.pchab.androidrtc; +import android.Manifest; import android.app.Activity; import android.content.Intent; import android.graphics.Point; import android.opengl.GLSurfaceView; import android.os.Bundle; +import android.support.annotation.NonNull; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.widget.Toast; @@ -46,6 +48,9 @@ public class RtcActivity extends Activity implements WebRtcClient.RtcListener { private String mSocketAddress; private String callerId; + private static final String[] RequiredPermissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}; + protected PermissionChecker permissionChecker = new PermissionChecker(); + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -85,6 +90,22 @@ public void run() { final List segments = intent.getData().getPathSegments(); callerId = segments.get(0); } + checkPermissions(); + } + + private void checkPermissions() { + permissionChecker.verifyPermissions(this, RequiredPermissions, new PermissionChecker.VerifyPermissionsCallback() { + + @Override + public void onPermissionAllGranted() { + + } + + @Override + public void onPermissionDeny(String[] permissions) { + Toast.makeText(RtcActivity.this, "Please grant required permissions.", Toast.LENGTH_LONG).show(); + } + }); } private void init() { @@ -156,7 +177,9 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { public void startCam() { // Camera settings - client.start("android_test"); + if (PermissionChecker.hasPermissions(this, RequiredPermissions)) { + client.start("android_test"); + } } @Override @@ -197,4 +220,10 @@ public void onRemoveRemoteStream(int endPoint) { LOCAL_WIDTH_CONNECTING, LOCAL_HEIGHT_CONNECTING, scalingType, false); } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + permissionChecker.onRequestPermissionsResult(requestCode, permissions, grantResults); + } } \ No newline at end of file