我正在尝试在Android和桌面之间实时传输音频。我开发了应用程序,一个用于android,一个用于桌面。 桌面应用程序成功地在两个桌面之间进行实时音频传输,并且android应用程序成功地用于两个Android设备之间的音频传输。 我正在使用本地IP地址和端口进行此过程(在两个应用程序中)。
问题是当我尝试在Android和桌面之间传输音频(使用相同的应用程序)时,它无法正常工作。 我只能传输单向音频,例如在台式机接收语音或传输音频时。
请帮助
这是Android应用程序的代码
package com.example.myrtpapplication;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.net.rtp.AudioCodec;
import android.net.rtp.AudioGroup;
import android.net.rtp.AudioStream;
import android.net.rtp.RtpStream;
import android.os.Handler;
import android.os.StrictMode;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
public class MainActivity extends AppCompatActivity {
EditText remote_ip_editText;
EditText remote_port_editText;
TextView locolport;
AudioStream audioStream;
AudioGroup audioGroup;
String localip;
Handler handler;
int flag=0;
private static int REQUEST_EXTERNAL_STORAGE=1;
private String[] PERMISSIONS={
Manifest.permission.RECORD_AUDIO,
Manifest.permission.MODIFY_AUDIO_SETTINGS,
Manifest.permission.INTERNET,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
verifyPermissions(MainActivity.this);
if(flag==1) {
locolport = (TextView) findViewById(R.id.lp);
remote_ip_editText = (EditText) findViewById(R.id.remote_ip);
remote_port_editText = (EditText) findViewById(R.id.remote_port);
handler = new Handler();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
int line = 0;
try {
AudioManager audiomanager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audiomanager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audiomanager.setSpeakerphoneOn(true);
// audiomanager.adjustStreamVolume(AudioManager.STREAM_VOICE_CALL, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
if (audiomanager.isMicrophoneMute()) {
Toast.makeText(MainActivity.this, "Microphone is mute", Toast.LENGTH_LONG).show();
}
audioGroup = new AudioGroup();
audioGroup.setMode(AudioGroup.MODE_ECHO_SUPPRESSION);
localip = getLocalAddress().toString();
audioStream = new AudioStream(getLocalAddress());
locolport.append(String.valueOf(audioStream.getLocalPort()));
audioStream.setCodec(AudioCodec.PCMU);
audioStream.setMode(RtpStream.MODE_NORMAL);
//Toast.makeText(MainActivity.this, "line = 10", Toast.LENGTH_SHORT).show();
} catch (SocketException se) {
Toast.makeText(MainActivity.this, se.getMessage(), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "line = " + line + e.getMessage() + "\n" + localip, Toast.LENGTH_LONG).show();
Log.e("-------", e.toString());
e.printStackTrace();
}
}else{
Toast.makeText(MainActivity.this, "permissions denied rizi", Toast.LENGTH_SHORT).show();
}
}
public void call(View view)
{
try {
//Toast.makeText(MainActivity.this, remote_ip_editText.getText().toString(), Toast.LENGTH_SHORT).show();
InetAddress remoteIp = InetAddress.getByName(remote_ip_editText.getText().toString());
Toast.makeText(MainActivity.this, remote_port_editText.getText().toString(), Toast.LENGTH_SHORT).show();
Integer remotePort= Integer.parseInt(remote_port_editText.getText().toString());
audioStream.associate(remoteIp, remotePort);
audioStream.join(audioGroup);
Toast.makeText(MainActivity.this, "call Success", Toast.LENGTH_SHORT).show();
}
catch (UnknownHostException ex){
Toast.makeText(MainActivity.this, "Unkown host Exception "+ ex.getMessage(), Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
Toast.makeText(MainActivity.this, "Exception "+ e, Toast.LENGTH_SHORT).show();
}
}
public InetAddress getLocalAddress()
{
InetAddress localAddress;
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface networkInterface = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = networkInterface.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress ip = enumIpAddr.nextElement();
if (!ip.isLoopbackAddress()) {
if (ip.isSiteLocalAddress()) {
return ip;
}
}
}
}
}
catch (Exception e)
{
Toast.makeText(MainActivity.this, "Exception at get local Address"+e.getMessage(), Toast.LENGTH_SHORT).show();
}
return null;
}
public void verifyPermissions(Activity activity) {
// Check if we have write permission
int permission1= ActivityCompat.checkSelfPermission(activity, Manifest.permission.MODIFY_AUDIO_SETTINGS);
int permission2= ActivityCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO);
int permission3= ActivityCompat.checkSelfPermission(activity, Manifest.permission.INTERNET);
if (permission1 != PackageManager.PERMISSION_GRANTED || permission2 != PackageManager.PERMISSION_GRANTED || permission3 != PackageManager.PERMISSION_GRANTED ) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS,
REQUEST_EXTERNAL_STORAGE
);
}else{
flag=1;
}
}
}
这是桌面应用程序的代码。我在桌面应用程序发送器类和接收器类中使用2个类。我在main方法中使用这些类作为线程。
接收者类
package rtpstreamdesktop;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Player;
public class SimpleVoiceReceiver implements Runnable
{
/**
* @param args
*/
public void run(){
// ip and port declaration for rtp session
String url = "rtp://192.168.8.106:60002/audio/16";
MediaLocator mrl = new MediaLocator(url);
// Create a player for this rtp session
Player player = null;
try
{
player = Manager.createPlayer(mrl);
} catch (Exception e)
{
System.out.println("player creation exception");
}
if (player != null)
{
System.out.println("Player created: ");
player.realize();
// wait for realizing (construction of media player)
while (player.getState() != Player.Realized)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("Starting player: ");
player.start();
} else
{
System.err.println("Player doesn't created: ");
System.exit(-1);
}
}
}
发射器类
package rtpstreamdesktop;
import java.util.Vector;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.DataSink;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NotRealizedError;
import javax.media.Processor;
import javax.media.control.FormatControl;
import javax.media.control.TrackControl;
import javax.media.format.AudioFormat;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.DataSource;
/**
*
* @author Abdul Rab
*
*/
public class SimpleVoiceTransmiter implements Runnable
{
/**
* @param args
*/
public void run()
{
CaptureDeviceInfo di = null;
Format format;
format = new AudioFormat(AudioFormat.ULAW_RTP, 8000, 8, 1);
// First find a capture device that will capture linear audio
// data at 8bit 8Khz
AudioFormat captureFormat = new AudioFormat(AudioFormat.LINEAR, 8000, 16, 1);
Vector devices = CaptureDeviceManager.getDeviceList(captureFormat);
if (devices.size() > 0)
{
di = (CaptureDeviceInfo) devices.elementAt(0);
} else
{
System.err.println("No capture devices");
// exit if we could not find the relevant capturedevice.
System.exit(-1);
}
// Create a processor for this capturedevice & exit if we
// cannot create it
Processor processor = null;
try
{
processor = Manager.createProcessor(di.getLocator());
} catch (Exception e)
{
System.out.println("Procesor Exception: ");
}
// configure the processor
processor.configure();
while (processor.getState() != Processor.Configured)
{
try
{
Thread.sleep(100);
} catch (InterruptedException e)
{
System.out.println("interupted processor exception: ");
}
}
processor.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));
TrackControl track[] = processor.getTrackControls();
boolean encodingOk = false;
// Go through the tracks and try to program one of them to
// output gsm data.
for (int i = 0; i < track.length; i++)
{
if (!encodingOk && track[i] instanceof FormatControl)
{
if (((FormatControl) track[i]).setFormat(format) == null)
{
track[i].setEnabled(false);
} else
{
encodingOk = true;
}
} else
{
// we could not set this track to gsm, so disable it
track[i].setEnabled(false);
}
}
// At this point, we have determined where we can send out
// gsm data or not.
// realize the processor
if (encodingOk)
{
if (!new net.sf.fmj.ejmf.toolkit.util.StateWaiter(processor).blockingRealize())
{
System.err.println("Failed to realize");
return;
}
// get the output datasource of the processor and exit
// if we fail
DataSource ds = null;
try
{
ds = processor.getDataOutput();
} catch (NotRealizedError e)
{
e.printStackTrace();
System.exit(-1);
}
// hand this datasource to manager for creating an RTP
// datasink our RTP datasink will multicast the audio
try
{
String url = "rtp://192.168.8.102:60010/audio/16";
MediaLocator m = new MediaLocator(url);
DataSink d = Manager.createDataSink(ds, m);
d.open();
d.start();
System.out.println("Starting processor");
processor.start();
Thread.sleep(30000);
} catch (Exception e)
{
System.out.println("RTP connection exception: ");
System.exit(-1);
}
}
}
}
主类
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package rtpstreamdesktop;
/**
*
* @author Rizwan
*/
public class RtpStreamDesktop {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new Thread(new SimpleVoiceReceiver()).start();
new Thread(new SimpleVoiceTransmiter()).start();
}
}
答案 0 :(得分:0)
我不会不喜欢你的代码如何在一个方向上工作,因为你在Android端使用(正确)Android.net.rtp包(比你发送/接收Voip数据包),而它似乎你在PC端没有任何Voip模块;在您的代码中,您尝试使用MediaLocator播放Voip数据包,但Voip数据包不是媒体文件(如mp3)。
在我看来,解决方案可能是在PC端,导入一个Voip Java模块(有一些开源类似于&#39; pjsip&#39;)但你必须适应和研究它。这部分既费时又不容易,因为你必须了解voip的工作原理等等......
Ciao,Fausto