mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 11:39:42 +01:00
proof of concept to share Android Screen
note that this is very dirty and will break many things! basically video from camera was replaced by screen stream Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
1137d13d3a
commit
7e9fe266e1
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.activities
|
package com.nextcloud.talk.activities
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -82,6 +83,7 @@ class MagicCallActivity : BaseActivity() {
|
|||||||
RouterTransaction.with(CallController(intent.extras))
|
RouterTransaction.with(CallController(intent.extras))
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
.tag("callController")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,6 +118,13 @@ class MagicCallActivity : BaseActivity() {
|
|||||||
eventBus.post(ConfigurationChangeEvent())
|
eventBus.post(ConfigurationChangeEvent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
if (requestCode != CallController.CAPTURE_PERMISSION_REQUEST_CODE) return
|
||||||
|
val callController : CallController = router!!.getControllerWithTag("callController") as CallController
|
||||||
|
callController.initScreenShare(resultCode, data);
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = "MagicCallActivity"
|
private val TAG = "MagicCallActivity"
|
||||||
|
|
||||||
|
@ -24,10 +24,15 @@ import android.Manifest;
|
|||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.media.AudioAttributes;
|
import android.media.AudioAttributes;
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
|
import android.media.projection.MediaProjection;
|
||||||
|
import android.media.projection.MediaProjectionManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -48,6 +53,7 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare;
|
import com.bluelinelabs.logansquare.LoganSquare;
|
||||||
import com.facebook.drawee.view.SimpleDraweeView;
|
import com.facebook.drawee.view.SimpleDraweeView;
|
||||||
@ -120,6 +126,7 @@ import org.webrtc.MediaStream;
|
|||||||
import org.webrtc.PeerConnection;
|
import org.webrtc.PeerConnection;
|
||||||
import org.webrtc.PeerConnectionFactory;
|
import org.webrtc.PeerConnectionFactory;
|
||||||
import org.webrtc.RendererCommon;
|
import org.webrtc.RendererCommon;
|
||||||
|
import org.webrtc.ScreenCapturerAndroid;
|
||||||
import org.webrtc.SessionDescription;
|
import org.webrtc.SessionDescription;
|
||||||
import org.webrtc.SurfaceTextureHelper;
|
import org.webrtc.SurfaceTextureHelper;
|
||||||
import org.webrtc.SurfaceViewRenderer;
|
import org.webrtc.SurfaceViewRenderer;
|
||||||
@ -175,6 +182,7 @@ public class CallController extends BaseController {
|
|||||||
private static final String[] PERMISSIONS_MICROPHONE = {
|
private static final String[] PERMISSIONS_MICROPHONE = {
|
||||||
Manifest.permission.RECORD_AUDIO
|
Manifest.permission.RECORD_AUDIO
|
||||||
};
|
};
|
||||||
|
public static final int CAPTURE_PERMISSION_REQUEST_CODE = 1;
|
||||||
|
|
||||||
@BindView(R.id.callControlEnableSpeaker)
|
@BindView(R.id.callControlEnableSpeaker)
|
||||||
SimpleDraweeView callControlEnableSpeaker;
|
SimpleDraweeView callControlEnableSpeaker;
|
||||||
@ -194,6 +202,8 @@ public class CallController extends BaseController {
|
|||||||
SimpleDraweeView cameraControlButton;
|
SimpleDraweeView cameraControlButton;
|
||||||
@BindView(R.id.call_control_switch_camera)
|
@BindView(R.id.call_control_switch_camera)
|
||||||
SimpleDraweeView cameraSwitchButton;
|
SimpleDraweeView cameraSwitchButton;
|
||||||
|
@BindView(R.id.callControlShareScreen)
|
||||||
|
SimpleDraweeView callControlShareScreen;
|
||||||
@BindView(R.id.callStateTextView)
|
@BindView(R.id.callStateTextView)
|
||||||
TextView callStateTextView;
|
TextView callStateTextView;
|
||||||
|
|
||||||
@ -429,7 +439,9 @@ public class CallController extends BaseController {
|
|||||||
sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
|
sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
|
||||||
|
|
||||||
if (!isVoiceOnlyCall) {
|
if (!isVoiceOnlyCall) {
|
||||||
cameraInitialization();
|
checkPermissions();
|
||||||
|
// TODO change back to cameraInitialization (just changed this for androidScreensharing Proof of concept)
|
||||||
|
// cameraInitialization();
|
||||||
}
|
}
|
||||||
|
|
||||||
microphoneInitialization();
|
microphoneInitialization();
|
||||||
@ -472,7 +484,6 @@ public class CallController extends BaseController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private void initViews() {
|
private void initViews() {
|
||||||
participantDisplayItems = new HashMap<>();
|
participantDisplayItems = new HashMap<>();
|
||||||
@ -573,16 +584,22 @@ public class CallController extends BaseController {
|
|||||||
|
|
||||||
|
|
||||||
private void checkPermissions() {
|
private void checkPermissions() {
|
||||||
if (isVoiceOnlyCall) {
|
// TODO revert (just changed this for androidScreensharing Proof of concept)
|
||||||
onMicrophoneClick();
|
// if (isVoiceOnlyCall) {
|
||||||
} else if (getActivity() != null) {
|
// onMicrophoneClick();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
// } else if (getActivity() != null) {
|
||||||
requestPermissions(PERMISSIONS_CALL, 100);
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
} else {
|
// requestPermissions(PERMISSIONS_CALL, 100);
|
||||||
onRequestPermissionsResult(100, PERMISSIONS_CALL, new int[]{1, 1});
|
// } else {
|
||||||
}
|
// onRequestPermissionsResult(100, PERMISSIONS_CALL, new int[]{1, 1});
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
MediaProjectionManager mediaProjectionManager =
|
||||||
|
(MediaProjectionManager) getApplicationContext().getSystemService(
|
||||||
|
Context.MEDIA_PROJECTION_SERVICE);
|
||||||
|
getActivity().startActivityForResult(
|
||||||
|
mediaProjectionManager.createScreenCaptureIntent(), CAPTURE_PERMISSION_REQUEST_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isConnectionEstablished() {
|
private boolean isConnectionEstablished() {
|
||||||
@ -704,6 +721,27 @@ public class CallController extends BaseController {
|
|||||||
localVideoTrack.addSink(pipVideoView);
|
localVideoTrack.addSink(pipVideoView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initScreenShare(int resultCode, Intent intent){
|
||||||
|
videoCapturer = createScreenCapturer(resultCode, intent);
|
||||||
|
|
||||||
|
if (videoCapturer != null) {
|
||||||
|
SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", rootEglBase.getEglBaseContext());
|
||||||
|
videoSource = peerConnectionFactory.createVideoSource(true);
|
||||||
|
videoCapturer.initialize(surfaceTextureHelper, getApplicationContext(), videoSource.getCapturerObserver());
|
||||||
|
}
|
||||||
|
|
||||||
|
localVideoTrack = peerConnectionFactory.createVideoTrack("ARDAMSv0", videoSource);
|
||||||
|
localMediaStream.addTrack(localVideoTrack);
|
||||||
|
localVideoTrack.setEnabled(true);
|
||||||
|
localVideoTrack.addSink(pipVideoView);
|
||||||
|
|
||||||
|
videoCapturer.startCapture(1000, 1000, 10);
|
||||||
|
|
||||||
|
if (!isConnectionEstablished()) {
|
||||||
|
fetchSignalingSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void microphoneInitialization() {
|
private void microphoneInitialization() {
|
||||||
//create an AudioSource instance
|
//create an AudioSource instance
|
||||||
audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
|
audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
|
||||||
@ -746,6 +784,20 @@ public class CallController extends BaseController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VideoCapturer createScreenCapturer(int resultCode, Intent intent) {
|
||||||
|
if (resultCode != Activity.RESULT_OK) {
|
||||||
|
Log.d("","User didn't give permission to capture the screen.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new ScreenCapturerAndroid(intent, new MediaProjection.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
Log.d("","User revoked permission to capture the screen.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@OnLongClick(R.id.call_control_microphone)
|
@OnLongClick(R.id.call_control_microphone)
|
||||||
boolean onMicrophoneLongClick() {
|
boolean onMicrophoneLongClick() {
|
||||||
if (!audioOn) {
|
if (!audioOn) {
|
||||||
@ -883,6 +935,11 @@ public class CallController extends BaseController {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.callControlShareScreen)
|
||||||
|
public void onCallControlShareScreenClick() {
|
||||||
|
Toast.makeText(getApplicationContext(), "not yet implemented", Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
@OnClick({R.id.call_control_switch_camera})
|
@OnClick({R.id.call_control_switch_camera})
|
||||||
public void switchCamera() {
|
public void switchCamera() {
|
||||||
CameraVideoCapturer cameraVideoCapturer = (CameraVideoCapturer) videoCapturer;
|
CameraVideoCapturer cameraVideoCapturer = (CameraVideoCapturer) videoCapturer;
|
||||||
@ -1380,7 +1437,8 @@ public class CallController extends BaseController {
|
|||||||
|
|
||||||
private void initiateCall() {
|
private void initiateCall() {
|
||||||
if (!TextUtils.isEmpty(roomToken)) {
|
if (!TextUtils.isEmpty(roomToken)) {
|
||||||
checkPermissions();
|
// TODO revert (just changed this for androidScreensharing Proof of concept)
|
||||||
|
// checkPermissions();
|
||||||
} else {
|
} else {
|
||||||
handleFromNotification();
|
handleFromNotification();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M21.22,18.02l2,2L24,20.02v-2h-2.78zM21.99,16.02l0.01,-10c0,-1.11 -0.9,-2 -2,-2L7.22,4.02l5.23,5.23c0.18,-0.04 0.36,-0.07 0.55,-0.1L13,7.02l4,3.73 -1.58,1.47 5.54,5.54c0.61,-0.33 1.03,-0.99 1.03,-1.74zM2.39,1.73L1.11,3l1.54,1.54c-0.4,0.36 -0.65,0.89 -0.65,1.48v10c0,1.1 0.89,2 2,2L0,18.02v2h18.13l2.71,2.71 1.27,-1.27L2.39,1.73zM7,15.02c0.31,-1.48 0.92,-2.95 2.07,-4.06l1.59,1.59c-1.54,0.38 -2.7,1.18 -3.66,2.47z"/>
|
||||||
|
</vector>
|
@ -152,6 +152,16 @@
|
|||||||
app:placeholderImage="@drawable/ic_comment_white"
|
app:placeholderImage="@drawable/ic_comment_white"
|
||||||
app:roundAsCircle="true" />
|
app:roundAsCircle="true" />
|
||||||
|
|
||||||
|
<com.facebook.drawee.view.SimpleDraweeView
|
||||||
|
android:id="@+id/callControlShareScreen"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:backgroundImage="@color/call_buttons_background"
|
||||||
|
app:placeholderImage="@drawable/ic_baseline_stop_screen_share_24"
|
||||||
|
app:roundAsCircle="true" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<com.facebook.drawee.view.SimpleDraweeView
|
||||||
android:id="@+id/callControlEnableSpeaker"
|
android:id="@+id/callControlEnableSpeaker"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
|
Loading…
Reference in New Issue
Block a user