Android 视频通讯第一篇:连接服务器
1.开发环境
开发工具:AndroidStudio、Kotlin
使用jvu-rtmp-client-1.5.10.此版本为破解版本
2.连接
2.1声明red5Client,回调接口
private var red5Client: INetConnection? = null
private val singleExecutor = Executors.newSingleThreadExecutor();
/**
* 连接服务器接口回调
*/
val connectServerCallback = object : INetConnection.ListenerAdapter(){
override fun onAsyncError(source: INetConnection?, message: String?, e: Exception?) {
Log.i(TAG, "connectServerCallback onAsyncError: $message $e")
}
override fun onIOError(source: INetConnection?, message: String?){
Log.i(TAG, "connectServerCallback#onIOError: " + message!!)
}
override fun onNetStatus(source: INetConnection?, info: Map<String, Any>){
Log.i(TAG, "connectServerCallback #onNetStatus: $info")
val code = info["code"]
if (NetConnection.CONNECT_SUCCESS == code){
//连接成功
} else{
}
}
}
2.2连接服务器
/**
* @param authentication:服务器需要的认证信息,按服务器要求提供,可以是各种类型数据
* connect Chat服务器
*/
private fun connect(authentication: UserProfile) {
singleExecutor.execute() {
Log.i(TAG, "red5Client:connect $authentication")
red5Client = UltraNetConnection()
red5Client?.addEventListener(connectServerCallback)
//设置client为当前对象,以便服务器调用客户端方法
red5Client?.client(this)
//SERVER_URL 服务器地址
red5Client?.connect(SERVER_URL, authentication)
}
}
3.新建UltraNetConnection.java、UltraNetStream.java
3.1UltraNetConnection.java
import com.smaxe.logger.ILogger;
import com.smaxe.uv.ProtocolLayerInfo;
import com.smaxe.uv.Responder;
import com.smaxe.uv.UrlInfo;
import com.smaxe.uv.client.INetConnection;
import com.smaxe.uv.client.a.d;
import com.smaxe.uv.client.a.h;
import com.smaxe.uv.client.a.i;
import com.smaxe.uv.client.a.k;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
public final class UltraNetConnection extends i
implements INetConnection {
private final h a;
private d b = null;
private a c = null;
private ExecutorService d = null;
private ScheduledExecutorService e = null;
private boolean f = false;
private boolean g = false;
private static final int h = 19;
private static final int i = 9;
private static final int[] j = {5, 2, 7, 1, 0, 3, 6, 4};
private static byte[] k = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
public static void setSwfFileSizeAndHash(Map<String, Object> paramMap, File paramFile)
throws Exception {
a(paramMap, paramFile);
}
public UltraNetConnection() {
this(null);
}
public UltraNetConnection(Map<String, Object> paramMap) {
this(paramMap, null, null);
}
public UltraNetConnection(Map<String, Object> paramMap, ExecutorService paramExecutorService, ScheduledExecutorService paramScheduledExecutorService) {
super(paramMap);
this.d = (paramExecutorService == null ? Executors.newCachedThreadPool() : paramExecutorService);
this.e = (paramScheduledExecutorService == null ? Executors.newSingleThreadScheduledExecutor() : paramScheduledExecutorService);
this.f = (paramExecutorService == null);
this.g = (paramScheduledExecutorService == null);
this.a = new k(this.e);
}
public void addHeader(String paramString, boolean paramBoolean, Object paramObject) {
this.b.a(paramString, paramBoolean, paramObject);
}
public void call(String paramString, Responder paramResponder, Object... paramArrayOfObject) {
if (!connected())
return;
this.b.a(paramString, paramResponder, paramArrayOfObject);
}
public void close() {
b(com.smaxe.uv.a.e.b("NetConnection.Connect.Closed", "Connection is closed."));
}
public void connect(String paramString, Object... paramArrayOfObject) {
// b(k);
UrlInfo localUrlInfo = UrlInfo.parseUrl(paramString);
com.smaxe.uv.client.a.e locale = new com.smaxe.uv.client.a.e();
locale.a(this.d);
locale.a((ILogger) configuration().get("logger"));
this.b = locale;
this.c = new a();
try {
Method bitchMethod = com.smaxe.uv.client.a.h.class.getMethod("a", String.class, String.class, int.class, Map.class);
Object btichResult = bitchMethod.invoke(this.a, localUrlInfo.protocol, localUrlInfo.host, localUrlInfo.port, configuration());
Method[] aryMethod = com.smaxe.uv.client.a.d.class.getMethods();
for (Method method : aryMethod) {
if (method.getName().equals("a") && method.getParameterTypes().length == 6) {
method.invoke(this.b, this, btichResult, paramString, localUrlInfo.getApp(), this.c, paramArrayOfObject);
break;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
super.connect(paramString, paramArrayOfObject);
}
public boolean connected() {
if (this.b == null)
return false;
return this.b.a() == 3;
}
public String connectedProxyType() {
return connected() ? this.b.b() : null;
}
public boolean usingTLS() {
return connected() ? this.b.c() : false;
}
public ProtocolLayerInfo getInfo() {
return this.b.d();
}
public int getUploadBufferSize() {
return this.b.e();
}
public void setMaxUploadBandwidth(int paramInt) {
if (paramInt < 0)
throw new IllegalArgumentException("Parameter 'bandwidth' is negative: " + paramInt);
this.b.a(paramInt);
}
public void onBWDone() {
}
public void onBWDone(Object[] paramArrayOfObject) {
}
private void b(Map<String, Object> paramMap) {
if (this.b == null)
return;
this.b.a(paramMap);
if ((this.f) && (this.d != null))
this.d.shutdown();
if ((this.g) && (this.e != null))
this.e.shutdown();
this.d = null;
this.e = null;
}
static void a(byte[] paramArrayOfByte) {
if ((paramArrayOfByte == null) || (paramArrayOfByte.length != 25))
return;
k = paramArrayOfByte;
}
d a() {
return this.b;
}
private static void b(byte abyte0[])
throws IllegalArgumentException {
int l = 0;
for (int i1 = 1; i1 < abyte0.length - 1; i1++)
l += abyte0[i1] & 0xff;
l &= 0xff;
int j1 = abyte0[1] & 0xf;
if ((abyte0[0] & 0xff) != (byte) (l >> 0 & 0xf) || (abyte0[abyte0.length - 1] & 0xff) != (byte) (l >> 4 & 0xf) || abyte0[1] + abyte0[abyte0.length - 2] != 15)
a(16);
boolean aflag[] = new boolean[21];
byte abyte1[] = new byte[8];
int k1 = 1;
int l1 = j1;
for (int i2 = 0; i2 < abyte1.length; i2++) {
for (; aflag[l1 % aflag.length]; l1++) ;
aflag[l1 % aflag.length] = true;
abyte1[i2] = abyte0[2 + l1 % aflag.length];
k1 += 2;
l1 += k1;
}
if ((abyte1[1] & 0xf) != 3)
a(32);
boolean flag = (abyte1[3] & 0xf) >= 8;
int j2 = (flag ? abyte1[3] - 8 : abyte1[3]) & 0xf;
if (j2 < 1)
a(1);
if (flag) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2000 + (abyte1[4] & 0xf));
calendar.set(Calendar.MONTH, (abyte1[5] & 0xf) - 1);
calendar.set(Calendar.DAY_OF_MONTH, ((abyte1[6] & 0xf) << 4) + (abyte1[7] & 0xf));
if (System.currentTimeMillis() - calendar.getTimeInMillis() > 0L)
a(18);
}
}
private static void a(int paramInt) {
switch (paramInt & 0xF) {
case 0:
throw new IllegalArgumentException(a(new long[]{8460391658548064800L, 8315163859177334048L, 8319872964449869929L, 7205878151055483136L}));
case 1:
throw new IllegalArgumentException(a(new long[]{8460391658548064800L, 8315163859177334048L, 8319309735340351598L, 7811060823377406308L, 7162256601089340786L, 8532478991051810162L, 120946281218048L}));
case 2:
throw new IllegalArgumentException(a(new long[]{8462924959242482208L, 2314957309810076517L, 2335505025909089656L, 2378011653932580864L}));
}
}
private static String a(long[] paramArrayOfLong) {
byte[] arrayOfByte = new byte[paramArrayOfLong.length * 8];
int m = 0;
for (int n = 0; n < paramArrayOfLong.length; n++)
for (int i1 = 0; i1 < 8; i1++) {
byte i2 = (byte) (int) (paramArrayOfLong[n] >> j[i1] * 8 & 0xFF);
if (i2 == 0)
break;
arrayOfByte[(n * 8 + i1)] = i2;
m++;
}
return new String(arrayOfByte, 0, m);
}
static void a(UltraNetConnection netconnection, String s, Exception exception) {
netconnection.a(s, exception);
}
static void a(UltraNetConnection netconnection, String s) {
netconnection.a(s);
}
static void a(UltraNetConnection netconnection, Map map) {
netconnection.b(map);
}
static void b(UltraNetConnection netconnection, Map map) {
netconnection.a(map);
}
static void c(UltraNetConnection netconnection, Map map) {
netconnection.a(map);
}
private class a extends d.a {
public a() {
}
public void a(String paramString, Exception paramException) {
UltraNetConnection.a(UltraNetConnection.this, paramString, paramException);
}
public void a(String paramString) {
UltraNetConnection.a(UltraNetConnection.this, paramString);
}
public void a(Map<String, Object> paramMap) {
String str = (String) paramMap.get("code");
if ((!"NetConnection.Connect.Success".equals(str)) && (!"NetConnection.Connect.Bandwidth".equals(str)) && (!"NetConnection.Call.Failed".equals(str)))
UltraNetConnection.a(UltraNetConnection.this, paramMap);
UltraNetConnection.b(UltraNetConnection.this, paramMap);
}
public void a(long paramLong1, long paramLong2) {
if (!((Boolean) UltraNetConnection.this.configuration().get("enableAcknowledgementEventNotification")).booleanValue())
return;
Map localMap = com.smaxe.uv.a.e.b("NetConnection.Connect.Bandwidth", "'Acknowledgement' event notification.");
localMap.put("acknowledgement", Long.valueOf(paramLong1));
localMap.put("info", new ProtocolLayerInfo(UltraNetConnection.this.getInfo()));
localMap.put("uploadBufferSize", Long.valueOf(paramLong2));
UltraNetConnection.c(UltraNetConnection.this, localMap);
}
}
}
3.2UltraNetStream.java
import android.util.Log;
import com.smaxe.uv.client.ICamera;
import com.smaxe.uv.client.IMicrophone;
import com.smaxe.uv.client.INetConnection;
import com.smaxe.uv.client.INetStream;
import com.smaxe.uv.client.IVideo;
import com.smaxe.uv.client.a.c;
import com.smaxe.uv.client.video.EmptyVideo;
import com.smaxe.uv.stream.MediaData;
import java.lang.reflect.Method;
import java.util.Map;
public final class UltraNetStream extends c
implements INetStream {
private com.smaxe.uv.client.a.d a = null;
private IVideo b = new EmptyVideo();
private volatile boolean c = false;
private IMicrophone d = null;
private ICamera e = null;
private e f = null;
private c g = null;
private a h = null;
private a i = null;
public UltraNetStream(INetConnection paramINetConnection) {
this.a = ((UltraNetConnection) paramINetConnection).a();
this.a.a(paramINetConnection, this, new d());
this.h = new a();
this.i = new a();
}
public void onTimeCoordInfo(Object obj) {
Log.i("", "onTimeCoordInfo" + obj);
}
public INetStream.Info getInfo() {
return new INetStream.Info(this.h.a, this.h.b, this.h.c, this.i.a, this.i.b, this.i.c);
}
public ICamera getCamera() {
return this.e;
}
public IMicrophone getMicrophone() {
return this.d;
}
public IVideo getVideo() {
if ((this.b instanceof MyVideo))
return ((MyVideo) this.b).a();
return this.b;
}
public double bufferLength() {
return this.c ? this.a.b(this) : this.b.bufferLength();
}
public int bufferSize() {
return this.c ? this.a.c(this) : 0;
}
public long bytesLoaded() {
return this.b.bytesLoaded();
}
public long bytesTotal() {
return this.b.bytesTotal();
}
public int clearBuffer() {
return this.a.a(this);
}
public void attachAudio(IMicrophone paramIMicrophone) {
if (this.d == paramIMicrophone)
return;
if (this.d != null) {
this.d.removeListener(this.g);
this.g = null;
}
this.d = paramIMicrophone;
if (this.d != null)
this.d.addListener(this.g = new c());
}
public void attachCamera(ICamera paramICamera, int paramInt) {
if (this.e == paramICamera)
return;
if (this.e != null) {
this.e.removeListener(this.f);
this.f = null;
}
this.e = paramICamera;
if (this.e != null)
this.e.addListener(this.f = new e(paramInt));
}
public void publish(String paramString1, String paramString2) {
paramString2 = paramString2 == null ? "live" : paramString2;
if ((!"append".equalsIgnoreCase(paramString2)) && (!"live".equalsIgnoreCase(paramString2)) && (!"record".equalsIgnoreCase(paramString2)))
throw new IllegalArgumentException("Wrong publish type '" + paramString2 + "'. Use 'live','record' or 'append' type");
this.a.a(this, paramString1, paramString2);
this.c = true;
}
public void send(String paramString, Object... paramArrayOfObject) {
this.a.a(this, paramString, paramArrayOfObject);
}
public double currentFPS() {
return this.b.fps();
}
public double liveDelay() {
return this.b.liveDelay();
}
public double time() {
return this.b.time();
}
public void play(IVideo paramIVideo, Object... paramArrayOfObject) {
if (paramIVideo == null)
throw new IllegalArgumentException("Parameter 'video' is null");
this.b = new MyVideo(paramIVideo);
this.a.a(this, this.b, paramArrayOfObject);
}
public void pause() {
this.a.d(this);
}
public void receiveAudio(boolean paramBoolean) {
this.a.a(this, paramBoolean);
}
public void receiveVideo(boolean paramBoolean) {
this.a.b(this, paramBoolean);
}
public void resume() {
this.a.e(this);
}
public void seek(double paramDouble) {
this.a.a(this, paramDouble);
}
public void togglePause() {
if (this.c)
pause();
else
resume();
}
public void close() {
attachAudio(null);
attachCamera(null, 0);
this.a.f(this);
super.close();
}
public void _RtmpSampleAccess(boolean paramBoolean1, boolean paramBoolean2) {
}
static void a(UltraNetStream netstream, String s, Exception exception) {
netstream.a(s, exception);
}
static void a(UltraNetStream netstream, String s) {
netstream.a(s);
}
static void a(UltraNetStream netstream, Map map) {
netstream.c(map);
}
static void b(UltraNetStream netstream, Map map) {
netstream.a(map);
}
static IVideo a(UltraNetStream netstream) {
return netstream.b;
}
static void c(UltraNetStream netstream, Map map) {
netstream.b(map);
}
static void d(UltraNetStream netstream, Map map) {
netstream.d(map);
}
static boolean b(UltraNetStream netstream) {
return netstream.c;
}
static a c(UltraNetStream netstream) {
return netstream.i;
}
static com.smaxe.uv.client.a.d d(UltraNetStream netstream) {
return netstream.a;
}
static a e(UltraNetStream netstream) {
return netstream.h;
}
private final class a {
public int a = 0;
public int b = 0;
public int c = 0;
public a() {
}
public MediaData a(MediaData paramMediaData) {
this.a = (this.b == 0 ? 0 : this.a + paramMediaData.rtime);
this.b += 1;
this.c += paramMediaData.size();
return paramMediaData;
}
}
private final class MyVideo
implements IVideo {
private final IVideo b;
public MyVideo(IVideo arg2) {
this.b = arg2;
}
public IVideo a() {
return this.b;
}
public double bufferLength() {
return this.b.bufferLength();
}
public long bytesLoaded() {
return this.b.bytesLoaded();
}
public long bytesTotal() {
return this.b.bytesTotal();
}
public void clear() {
this.b.clear();
}
public void clearPlayBuffer() {
this.b.clearPlayBuffer();
}
public double fps() {
return this.b.fps();
}
public double liveDelay() {
return this.b.liveDelay();
}
public void reset() {
this.b.reset();
}
public double time() {
return this.b.time();
}
public void onAudioData(MediaData paramMediaData) {
this.b.onAudioData(UltraNetStream.e(UltraNetStream.this).a(paramMediaData));
}
public void onVideoData(MediaData paramMediaData) {
this.b.onVideoData(UltraNetStream.c(UltraNetStream.this).a(paramMediaData));
}
public void onFlvData(MediaData paramMediaData) {
this.b.onFlvData(paramMediaData);
}
public void onCuePoint(Object paramObject) {
this.b.onCuePoint(paramObject);
}
public void onMetaData(Object paramObject) {
this.b.onMetaData(paramObject);
}
public void onSetDataFrame(String paramString, Object paramObject) {
this.b.onSetDataFrame(paramString, paramObject);
}
}
private final class c extends IMicrophone.ListenerAdapter {
public c() {
}
public void onAudioData(MediaData paramMediaData) {
if (!UltraNetStream.b(UltraNetStream.this))
return;
UltraNetStream.d(UltraNetStream.this).a(UltraNetStream.this, UltraNetStream.e(UltraNetStream.this).a(paramMediaData));
}
}
private final class e extends ICamera.ListenerAdapter {
private final int b;
private long c = 0L;
public e(int arg2) {
this.b = arg2;
}
public void onVideoData(MediaData paramMediaData) {
if (!UltraNetStream.b(UltraNetStream.this))
return;
if (this.b > 0) {
try {
Class<?> clzF = Class.forName("com.smaxe.uv.a.a.f");
Method m = clzF.getMethod("a", int.class);
long l = System.currentTimeMillis();
if (l - this.c < this.b)
return;
int value = (Integer) m.invoke(clzF, paramMediaData.tag());
switch (value) {
case 1:
case 5:
this.c = l;
break;
default:
return;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
UltraNetStream.d(UltraNetStream.this).b(UltraNetStream.this, UltraNetStream.c(UltraNetStream.this).a(paramMediaData));
}
public void onFlvData(MediaData paramMediaData) {
if (!UltraNetStream.b(UltraNetStream.this))
return;
UltraNetStream.d(UltraNetStream.this).c(UltraNetStream.this, paramMediaData);
}
}
private class d extends com.smaxe.uv.client.a.d.a {
public d() {
}
public void a(String paramString, Exception paramException) {
UltraNetStream.a(UltraNetStream.this, paramString, paramException);
}
public void a(String paramString) {
UltraNetStream.a(UltraNetStream.this, paramString);
}
public void a(Map<String, Object> paramMap) {
UltraNetStream.a(UltraNetStream.this, paramMap);
}
public void b(Map<String, Object> paramMap) {
UltraNetStream.b(UltraNetStream.this, paramMap);
UltraNetStream.a(UltraNetStream.this).onCuePoint(paramMap);
}
public void c(Map<String, Object> paramMap) {
UltraNetStream.c(UltraNetStream.this, paramMap);
UltraNetStream.a(UltraNetStream.this).onMetaData(paramMap);
}
public void d(Map<String, Object> paramMap) {
UltraNetStream.d(UltraNetStream.this, paramMap);
}
public void a(String paramString, Map<String, Object> paramMap) {
UltraNetStream.a(UltraNetStream.this).onSetDataFrame(paramString, paramMap);
}
}
}
4.权限
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />