原文转自

http://stackoverflow.com/questions/21085261/apprtcdemo-with-local-server-works-between-browsers-but-not-android-native-to-br

I am developing a chat application and done with it. Now I want to implement video chat also. After research a lot I decided to go with "WebRTC" library.

What I have done?

1) Able to run AppRtcDemo at local server and Its working fine between browsers.

Reference : http://www.webrtc.org/reference/getting-started

2) Able to build Android AppRtcDemo.But when I run it say "Cross origin does not support".

After research I found in webrtc discussion that to resolve this issue I need to set-up own turn server.

3) So I install latest rfc5766TurnServer recommended by webrtc. I got success to run turn server.

Reference : http://code.google.com/p/rfc5766-turn-server/

I do following changes to ApprtcDemo (web) and (Android) to work with my Turn server

1) apprtc.py

Replace:

turn_url = 'https://computeengineondemand.appspot.com/'
turn_url = turn_url + 'turn?' + 'username=' + user + '&key=4080218913'

With point to my turn server:

turn_url = 'http://192.168.5.85:3478/?service=turn&username=biraj'

2) index.html

Replace:

var pcConfig = {{ pc_config|safe }};

With:

var pcConfig = {"iceServers": [{"url": "stun:stun.l.google.com:19302"},            {"url":"turn:biraj@192.168.5.85:3479", "credential":"0x5b04123c3eec4cf0be64ab909bb2ff5b"}]};

Android

1)AppRTCDemoActivity.java

Replace:

roomInput.setText("https://apprtc.appspot.com/?r=");

With my local apprtc server:

roomInput.setText("http://192.168.5.86:8080/?r=");

2) AppRTCClient.java

In private PeerConnection.IceServer requestTurnServer(String url){} function

Replace:

connection.addRequestProperty("origin", "https://apprtc.appspot.com");

With:

connection.addRequestProperty("origin", "http://192.168.5.86:8080");

3) /assets/channel.html

Replace:

<script src="https://apprtc.appspot.com/_ah/channel/jsapi"></script>

With:

<script src="http://192.168.5.86:8080/_ah/channel/jsapi"></script>

Now my question is why this is working between browsers but not between android AppRtcDemo and browser.

When I run AppRtcDemo on android after doing above changes local camera preview is started at right-top corner and message prompt "waiting for ICEcandidates" then nothing happens.

Thanks in advance.

Thanks to All for supporting my question.After long rocky ride with ApprtcDemo I got success and it works fine.I am posting the solution.

Find the "GAEChannelClient.java" java file.

and do change as below.

/*
* libjingle
* Copyright 2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ package org.appspot.apprtc; import java.io.InputStream; import android.annotation.SuppressLint;
import android.app.Activity;
import android.util.Log;
import android.webkit.ConsoleMessage;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient; /**
* Java-land version of Google AppEngine's JavaScript Channel API:
* https://developers.google.com/appengine/docs/python/channel/javascript
*
* Requires a hosted HTML page that opens the desired channel and dispatches JS
* on{Open,Message,Close,Error}() events to a global object named
* "androidMessageHandler".
*/
public class GAEChannelClient {
private static final String TAG = "GAEChannelClient";
private WebView webView;
private final ProxyingMessageHandler proxyingMessageHandler; /**
* Callback interface for messages delivered on the Google AppEngine
* channel.
*
* Methods are guaranteed to be invoked on the UI thread of |activity|
* passed to GAEChannelClient's constructor.
*/
public interface MessageHandler {
public void onOpen(); public void onMessage(String data); public void onClose(); public void onError(int code, String description);
} /** Asynchronously open an AppEngine channel. */
@SuppressLint("SetJavaScriptEnabled")
public GAEChannelClient(Activity activity, String token, MessageHandler handler) {
webView = new WebView(activity); webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAllowFileAccessFromFileURLs(true); // Maybe you
// don't
// need this
// rule
webView.getSettings().setAllowUniversalAccessFromFileURLs(true); webView.setWebChromeClient(new WebChromeClient() { // Purely for
// debugging.
public boolean onConsoleMessage(ConsoleMessage msg) {
Log.d(TAG, "console: " + msg.message() + " at " + msg.sourceId() + ":" + msg.lineNumber());
return false;
}
});
webView.setWebViewClient(new WebViewClient() { // Purely for debugging.
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Log.e(TAG, "JS error: " + errorCode + " in " + failingUrl + ", desc: " + description);
} @Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
System.out.println("HI");
return super.shouldOverrideUrlLoading(view, url);
}
}); proxyingMessageHandler = new ProxyingMessageHandler(activity, handler, token);
webView.addJavascriptInterface(proxyingMessageHandler, "androidMessageHandler");
// webView.loadUrl("file:///android_asset/channel.html");
try {
InputStream is = activity.getAssets().open("channel.html");
StringBuilder builder = new StringBuilder();
byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
builder.append(new String(buffer));
}
is.close();
String str = builder.toString();
webView.loadDataWithBaseURL("http://192.168.5.86:8080", str,"text/html","utf-8",null);}catch(Exception e){
e.printStackTrace();}}/** Close the connection to the AppEngine channel. */publicvoid close(){if(webView ==null){return;}
proxyingMessageHandler.disconnect();
webView.removeJavascriptInterface("androidMessageHandler");
webView.loadUrl("about:blank");
webView =null;}// Helper class for proxying callbacks from the Java<->JS interaction// (private, background) thread to the Activity's UI thread.privatestaticclassProxyingMessageHandler{privatefinalActivity activity;privatefinalMessageHandler handler;privatefinalboolean[] disconnected ={false};privatefinalString token;publicProxyingMessageHandler(Activity activity,MessageHandler handler,String token){this.activity = activity;this.handler = handler;this.token = token;}publicvoid disconnect(){
disconnected[0]=true;}privateboolean disconnected(){return disconnected[0];}@JavascriptInterfacepublicString getToken(){return token;}@JavascriptInterfacepublicvoid onOpen(){System.out.println("GAEClient : Open");
activity.runOnUiThread(newRunnable(){publicvoid run(){if(!disconnected()){
handler.onOpen();}}});}@JavascriptInterfacepublicvoid onMessage(finalString data){System.out.println("GAEClient : Message : "+data );
activity.runOnUiThread(newRunnable(){publicvoid run(){if(!disconnected()){
handler.onMessage(data);}}});}@JavascriptInterfacepublicvoid onClose(){System.out.println("GAEClient : Close");
activity.runOnUiThread(newRunnable(){publicvoid run(){if(!disconnected()){
handler.onClose();}}});}@JavascriptInterfacepublicvoid onError(finalint code,finalString description){System.out.println("GAEClient : Erroe : "+ description);
activity.runOnUiThread(newRunnable(){publicvoid run(){if(!disconnected()){
handler.onError(code, description);}}});}}}

Channel.html in assets folder

<html>
<head>
<script src="http://192.168.5.86:8080/_ah/channel/jsapi"></script>
</head>
<!--
Helper HTML that redirects Google AppEngine's Channel API to a JS object named
|androidMessageHandler|, which is expected to be injected into the WebView
rendering this page by an Android app's class such as AppRTCClient.
-->
<body onbeforeunload="closeSocket()" onload="openSocket()">
<script type="text/javascript">
var token = androidMessageHandler.getToken();
if (!token)
throw "Missing/malformed token parameter: [" + token + "]"; var channel = null;
var socket = null; function openSocket() {
channel = new goog.appengine.Channel(token);
socket = channel.open({
'onopen': function() { androidMessageHandler.onOpen(); },
'onmessage': function(msg) { androidMessageHandler.onMessage(msg.data); },
'onclose': function() { androidMessageHandler.onClose(); },
'onerror': function(err) { androidMessageHandler.onError(err.code, err.description); }
});
} function closeSocket() {
socket.close();
}
</script>
</body>
</html>
asked Jan 13 at 6:37
 
    
Will you provide the logs during android and web communication. –  Ichigo Kurosaki Jan 18 at 8:01
    
@Biraj Zalavadia: like you have spend 1 month, i have lost 3 month still could not make it work, you mentioned your modification worked for you but i did exactly like you have shown which never worked for me. Could you please also join on my link here: stackoverflow.com/questions/23949237/… –  YumYumYum May 30 at 7:28
    
@hushao asks "[H]ow do you create you[r] local server? [Is it] the same [as] apprtc.appspot.com "? –  drs Jul 22 at 1:28 

Sadly I don't know if you have done these things:

  1. Use the SAME stun and turn server on every application (wether PC or mobile).
  2. Are you even sending the ICE candidates between the applications (I think you do, but just to verify).
  3. Are you sure that the STUN/TURN url are the ones that give the error, as I can't believe that these things do about cross-origins (they shouldn't, as you are just connecting from a client to a server. Cross origin is mostly 'used' on web pages that load data from an external source. You aren't allowed to do that from an XHR). I am really thinking it has something to do with https://apprtc.appspot.com/_ah/channel/jsapi, as this is a good example of cross origin stuff.

What if you open the web page that is working in your chrome browser on mobile? What does it do then? (note that you can connect your phone to your pc to have the full developer tools chrome has. Chrome runs on your android device but you can see the devtools on your pc).

If you can provide me these answers I might be able to help you. Try to revert all those changes and just use google's TURN server, but only make that https://apprtc.appspot.com/_ah/channel/jsapifile local.

EDIT: I see you found your answer. Would you mind to share it?

answered Jan 18 at 22:30
MarijnS95
1,7011118
 
    
I added the javascript inside the html file instead of loading via network. But still not working. Can you please help, nobody is sharing details who made it work. –  YumYumYum May 28 at 15:51
1  
@YumYumYum What exactly is not working? I have seen that the OP has found an answer but I have no idea what. –  MarijnS95 May 28 at 16:54
    
@MarjinS95: Actually what OP has reported here and on other url i have done exactly same + spend more then 1 month on it, and its not working like OP said it was. My problem is in AppRTCDemo when i execute to connect with local setup, it does not do anything after joining the room. if you want should i open a new question related to this and link you that please? I think you are the only person who understood this issue, most of all others are very confused. –  YumYumYum May 29 at 14:56
1  
@YumYumYum Opening a new question would be nice (you can add some more details, maybe even some logging about what functions are executed and what not). I am mainly a javascripter, no java'er, so I have not that much knowledge about it but do understand most of it. I'd also like to see some url's you are using to find out if you have any cross-origin problems too. –  MarijnS95 May 29 at 15:07
    
OK - i will do that, but i believe you can solve it. Most of the related issues were ignored by many other experts. But it think its more JavaScript related problem, i will create a new question about this with every details and step by step i took. Then inform you here today. Thanks a lot for your support, i really appreciate it. –  YumYumYum May 29 at 15:13

如何使官方提供的AppRTCDemo 运行在自己搭建的server(官方提供的apprtc)上(官方的server源码)的更多相关文章

  1. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.0,完善基础功能(源码)

    (前段时间封闭式开发完了一个项目,最近才有时间继续更新GG的后续版本,对那些关注GG的朋友来说,真的是很抱歉.)GG的前面几个版本开发了一些比较高级的功能,像视频聊天.远程桌面.文件传送.远程磁盘等, ...

  2. 可在广域网部署运行的QQ高仿版 -- GG叽叽V1.8(源码)

    距离的GG 1.0发布已经三周了,这三周内,我利用业余时间为GG增加了视频聊天的功能.个人觉得进展有些缓慢,主要是因为大多数时间都花在了UI上.由于本人不会PS,所以图片素材都是从网上一个一个搜下来的 ...

  3. Maqetta源码运行

    一.Maqetta简介 Maqetta是IBM开发的一个创建桌面和移动用户界面的HTML5设计编辑工具.该项目已经捐助给开源机构Dojo基金会.Maqetta提供WYSIWYG可视化HTML5用户界面 ...

  4. 【流媒体开发】VLC Media Player - Android 平台源码编译 与 二次开发详解 (提供详细800M下载好的编译源码及eclipse可调试播放器源码下载)

    作者 : 韩曙亮  博客地址 : http://blog.csdn.net/shulianghan/article/details/42707293 转载请注明出处 : http://blog.csd ...

  5. 鸿蒙内核源码分析(信号消费篇) | 谁让CPU连续四次换栈运行 | 百篇博客分析OpenHarmony源码 | v49.04

    百篇博客系列篇.本篇为: v49.xx 鸿蒙内核源码分析(信号消费篇) | 谁让CPU连续四次换栈运行 | 51.c.h .o 进程管理相关篇为: v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁 ...

  6. AirTest源码分析之运行器

    from: https://blog.csdn.net/u012897401/article/details/82900562 使用:根据airtest文档说明,可以通过命令行来启动air脚本,需要传 ...

  7. Tensorflow版Faster RCNN源码解析(TFFRCNN) (2)推断(测试)过程不使用RPN时代码运行流程

    本blog为github上CharlesShang/TFFRCNN版源码解析系列代码笔记第二篇   推断(测试)过程不使用RPN时代码运行流程 作者:Jiang Wu  原文见:https://hom ...

  8. 老李推荐:第5章1节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 官方简介

    老李推荐:第5章1节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 官方简介   在MonkeyRunner的框架中,Monkey是作为一个服务来接受来自Monkey ...

  9. 鸿蒙内核源码分析(用栈方式篇) | 程序运行场地谁提供的 | 百篇博客分析OpenHarmony源码 | v20.04

    百篇博客系列篇.本篇为: v20.xx 鸿蒙内核源码分析(用栈方式篇) | 程序运行场地谁提供的 | 51.c.h .o 精读内核源码就绕不过汇编语言,鸿蒙内核有6个汇编文件,读不懂它们就真的很难理解 ...

随机推荐

  1. SpringBoot实例

    7player 7号球员 -- Show Time !跳至内容 首发 左边锋 技术流 外援 教练 7号 基于SpringBoot + Mybatis实现SpringMVC Web项目[原创] 目录 [ ...

  2. EmguCV 一些结构

    一.MCvTermCriteria epsilon Epsilon max_iter Maximum iteration type CV_TERMCRIT value 二.MCvScalar vo T ...

  3. Cocoapods配置

    这真是蛋疼的东西,配置了几次,每次都不同,每次都折腾半天.这一段时间应该不会变了,记录下来. 一 换源 看了教程都说官方源https://rubygems.org/不能访问,我特意点了一下,发现能访问 ...

  4. Json与类对象转换

    Json在js,jquery中可以直接使用,比如下串: { "from":"en" ,"to":"zh" ," ...

  5. jQuery extend 实现代码封装

    jQuery 有两种方式封装代码 $.extend 和 $.fn.extend,我们也称为封装插件 $.extend DEMO // 封装 $.extend({ say:function(option ...

  6. IOS移动设备处理器指令集 armv6、armv7、armv7s及arm64

    Arm处理器,因为其低功耗和小尺寸而闻名,几乎所有的手机处理器都基于arm,其在嵌入式系统中的应用非常广泛,它的性能在同等功耗产品中也很出色. Armv6.armv7.armv7s.arm64都是ar ...

  7. android NumberPicker 数组越界的坑

    被这个问题耽误了一个多小时... 直接上解决方案,参考红色部分. private void initViews() { wheel = (NumberPicker) findViewById(R.id ...

  8. IIS不能对网站添加默认文档(由于权限不足而无法写入配置文件)

    IIS7以上版本配置网站时需要手动配置网站目录的文件夹权限 增加"IIS_IUSER"用户的修改权限 但增加后仍然提示“ 由于权限不足无法写入配置文件” 通常是Web.config ...

  9. LightOj 1236 - Pairs Forming LCM (分解素因子,LCM )

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1236 题意:给你一个数n,求有多少对(i,  j)满足 LCM(i, j) = n, ...

  10. iOS cocospods Updating local specs repositories

    pod install --verbose --no-repo-update (在安装的时候) pod update --verbose --no-repo-update (在更新库的时候) 如果长时 ...