The basic sample project of OpenTok shows how to make a VideoCall, showing the subscribers videostream in a small frame above the publishers stream.
I'm trying to achieve the same, only vice versa.
Problems:
Simply changing the two container views in the layout xml doesnt work. What happens is, that the publisher stream (the one that should now be on top of the other stream) is not showing up (is invisble)
This issue describes the exact problem, hinting me towards using setZOrderMediaOverlay(true); setZOrderOnTop(true); The problem with this approach is that now the publisher stream is on top of everything, even the android gui which is not tolerable for my use case.
Using only setZOrderMediaOverlay(true); does not work. The publisher view still is invisble.
Any idea on how to achieve this?
Try using TextureViews instead of GLSurfaceView, which is what OpenTok sdk uses by default.
To enable TextureViews, build your session in this way:
Session session = new Session.Builder(this, "apiKey", "sessionId")
.sessionOptions(new Session.SessionOptions() {
#Override
public boolean useTextureViews() {
return true;
}
}).build();
That will make the Publisher and Subscriber objects use TextureViews for its rendering.
Oficial doc is here
Related
I'm having trouble solving this bug and hope someone can guide me. I created the share screen function in android with WebRTC (EglBase). it works perfectly fine until the user stops sharing and then shares again, the participant's screen will be a black screen, and can't see the content.
I have already check the SurfaceViewRenderer is assigned correctly. I believe the problem may be on how I implemented the init() and release() functions.
In this function, I init the screen share video
EglBase root = EglBase.create();
screenShare.init(root.getEglBaseContext(), null);
screenShare.setZOrderMediaOverlay(true);
remoteParticipant.setView(screenShareVideoView);
In this function, I release the screen share
screenShare.clearImage();
screenShare.release();
screenShare.setVisibility(View.INVISIBLE);
Maybe I re-init the view after release() incorrectly.
I know that there are a lot of questions about capturing screenshots, and I have checked most of them. They have the same answer (with small code variations).
I have following method for screenshot capturing:
#NonNull
public static Bitmap takeScreenShot(Window window) throws IOException {
final View rootView = window.getDecorView().getRootView();
final boolean drawingCacheEnabled = rootView.isDrawingCacheEnabled();
rootView.setDrawingCacheEnabled(true);
try {
return Bitmap.createBitmap(rootView.getDrawingCache());
} finally {
rootView.setDrawingCacheEnabled(drawingCacheEnabled);
}
}
And you can use it like these: takeScreenShot(getActivity().getWindow())
However these approach has several limitations:
If you have some dialogs on the screen they will not be captured on
screenshot.
Will it work with hardware accelerated views? According
to documentation:
When hardware acceleration is turned on, enabling the
drawing cache has no effect on rendering because the system uses a
different mechanism for acceleration which ignores the flag
Screenshot contains black boxes
instead of GLviews. (e.g. when you app has maps.). It seems to be as a result of 2nd point.
So my question is, is there any solution without rooting that can solve at least some of my issues?
Check out the following GitHub repo (not mine!): https://github.com/AndroidDeveloperLB/ScreenshotSample
Also, the following will be useful reading:
How to properly take a screenshot, globally?
The demand is that saving a video frame in the video call. I have made a demo that take a screenshot through the GLSurfaceView's method "onDrawFrame". But when I use the webrtc, it have its own renderer "VideoRendererGUI" .And then when I want to override it, I find it can't be overrided. the main part code :
vsv = (GLSurfaceView) findViewById(R.id.glviewchild_call);
vsv.setPreserveEGLContextOnPause(true);
vsv.setKeepScreenOn(true);
VideoRendererGui.setView(vsv, new Runnable() {
#Override
public void run() {
init();
}
});
And If you have another way to take a screenshot, you can also share with me.
Thanks a lot!
If you use a SurfaceViewRenderer to display the stream, you can use the solution in this answer to capture a frame on the call.
Basically, using surfaceViewRenderer.AddFrameListener with a class that implements EGLRenderer.FrameListener
I will assume that the SurfaceViewRenderer of the peer you want to take a screenshot of is called remotePeerSurfaceViewRenderer, also I will asume that the button that you will use to take a screenshot is called btnScreenshot
So all what you need to do is as "Webo80" said in the answer above use the FrameListener, the issue is the FrameListener implementation of the webrtc takes only the first frame available once the Listener is attached to the SurfaceViewRenderer, so my approach to do that is by attaching the webrtc implementation of the FrameListsner at the second I need to take a screenshot and remove it once it is taken:
btnScreenshot.setOnClickListener((view)-> {
remotePeerSurfaceViewRenderer.addFrameListsner(new EglRenderer.FrameListener() {
#Override
public void onFrame(Bitmap bitmap) {
runOnUiThread(() -> {
/*
do what ever you want with the bitmap for example
imgView.setImageBitmap(bitmap);
*/
localVideoView.removeFrameListener(this);
});
}
}, 1);
})
Important note:
1. Please don't forget to runOnUiThread as Iam doing
2. Please don't forget to remove the listener inside the button onClick() method
I have tried this solution and it is working more than fine, if you want to make your custom solution you have to completely implement the interface "EglRenderer.FrameListener"
I am sorry to say due to unavailability of canvas and other facilities in Android It's not possible to capture screenshot programatically using WebRTC. One can dodge this situation by animating the app's UI and capturing the screenshot manually , store it at configured location and exchange it with other party.
I have a WebView with youtube video and 3 tabs. YouTube video is available in 1st Tab while in other 2 tabs there is a content.
Now i want to pause a video when user moves to other tabs. I have tried with
webView.onPause();
and
Class.forName("android.webkit.WebView")
.getMethod("onPause", (Class[]) null)
.invoke(webView, (Object[]) null);
but it is pausing whole WebView and my other 2 tabs are also not responding. How to stop just a video instead of whole WebView process
You can evaluate Javascript from android and stop video playing.
webView.evaluateJavascript(javascript, callBack);
or older versions.
webView.loadUrl(javascript);
check this
https://developer.android.com/reference/android/webkit/WebView.html#evaluateJavascript(java.lang.String,android.webkit.ValueCallback
What type video do you have? iframe or video tag?
On older devices (api <=21) I don't think this is actually possible, but an easy way to retrieve the given idea of a webview's inner controls are to:
Navigate to ../Android/android-sdk/tools/androiduiautomator.bat and open it up.
Make sure your device is connected via an ADB bridge (which it most likely will be)
Take a device screenshot of your screen and hover over the webkit control you want to call onPause which should bring up some information to the right hand side of your screen.
Substitute the id for
Class.ForName("yourId")
and just call a generic click event which should cause an inner effect of pausing. It could also be
Field.getDeclaredField("Id")
but I'm not positive. One of those two should procure a desired result.
You write you have A WebView and 3 tab, do you use from that WebView in All tab?
My Solution is that you use from Another WebView in other tab and if it tabs be selected some data that maybe be needed,be send to them.
In fact this don't solve your question, but i hope that can solve your problem.
I had similar issues with WebViews malfunctioning across my app. I decided to use the complementary function of onPause() (i.e. onResume()) in the same way:
Class.forName("android.webkit.WebView")
.getMethod("onResume", (Class[]) null)
.invoke(webView, (Object[]) null);
I am using the official PlayGameServices plugin for Unity, and have been following the installation to the point. Authentication seems to work like a charm, but when I want to do the ShowAchievementsUI();, nothing happends. No UI, no errors, no crashes.
Ive been googling around for a while, it seems other people have hit this problem, but with no solution in sight.
My code at the moment is :
using GooglePlayGames;
using UnityEngine.SocialPlatforms;
void Start() {
PlayGamesPlatform.DebugLogEnabled = true;
PlayGamesPlatform.Activate();
LoginSocialGamecenter();
}
public static void LoginSocialGamecenter() {
if (Social.localUser.authenticated) {
Social.ShowAchievementsUI (); Debug.Log("Pancakes!");
return;
}
}
And "Pancakes!" comes out perfectly. Authentication UI on first install also shows up nicely. It fails on all devices I have, but the debug message shows up perfectly on Android.
According to the documentation, it should work as described:
Showing the Achievements UI
To show the built-in UI for all leaderboards, call
Social.ShowAchievementsUI.
using GooglePlayGames;
using UnityEngine.SocialPlatforms;
...
// show achievements UI
Social.ShowAchievementsUI();
This will show a standard UI appropriate for the look and feel of the platform (Android or iOS).
Akhil got it right. There needs to be more than five achievements or the window won't appear.
It will make no error reports on this, simply return false.