原文转自

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. linux中,常用的账号管理命令

    创建新用户:adduser 用户名创建新用户并将其加入一个现有组中:adduser 用户名 -G 组名创建新用户并使其只属于该组:adduser 用户名 -g 组名创建用户密码:passwd 用户名创 ...

  2. 理解Oracle TM和TX锁

    在Oracle中有很多锁,通过v$lock_type视图可以查看Oracle中所有类型的锁,在本篇文章中我们熟悉一下TM和TX锁的类型 SQL> select * from v$lock_typ ...

  3. CentOS下IP的配置

    1.打开命令窗口,切换成root账户:su - root 2.进入目录:/etc/sysconfig/network-scripts,打开文件vi ifcfg-eth0 3.修改参数: ## 名称DE ...

  4. js 日期

    let date = new Date(); let year = date.getFullYear(); let money = money = date.getMonth() + 1; let d ...

  5. time模块目录下自己建立一个名为log的文件夹

    使用python调用ping命令,然后在日志中记录ping的结果,用来监测网络连通情况. 代码: [python]from time import *from subprocess import *w ...

  6. Algorithm | Tree traversal

    There are three types of depth-first traversal: pre-order,in-order, and post-order. For a binary tre ...

  7. cookie案例-显示用户上次访问网站的时间

    package cn.itcast.cookie; import java.io.IOException; import java.io.PrintWriter; import java.util.D ...

  8. 浏览器中Javascript单线程分析

    线程这个特性对于一门语言环境来说是尤其重要的,在Java/C++环境下都提供了多线程API操作. 但在Javascript中据说代码执行时单线程的,大量计算的逻辑会阻塞浏览器HTML渲染,但setTi ...

  9. mysql笔记(存储引擎)

    读写锁:. 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也最高. 页面锁:开销和 ...

  10. PL/SQL不支持64位Oracle Client 解决办法

    解决X64操作系统PL/SQL连接报错问题 make sure you have the 32 bits oracle client installed 说明PLSQL Developer并不支持Or ...