【问题标题】:How can I use AudioStream/AudioGroup with local Wifi-Hotspot如何将 AudioStream/AudioGroup 与本地 Wifi-Hotspot 一起使用
【发布时间】:2019-11-05 16:07:34
【问题描述】:

我想创建一个使用 AudioStream/AudioGroup 并且只能使用本地 WiFi 热点运行的 VoIP 系统。我在 android device1 上创建了一个 WiFi-Hotspot 并将 device2 连接到它。当我填写通过 getLocalIPAddress() 获得的 device1 的本地 IP 地址和通过 device1 上的 fetchIPs() 方法获得的 device2 的 IP 地址,然后在两个设备上单击“连接”时,代码不会抛出任何异常,但我没有听到任何设备的麦克风音频。

注1:此代码取自this answer by @murphybro2,略有改动。 注意 2:在 device1(主机)上使用 getLocalIPAddress() 时,IP 地址返回为 115.163.242.10,而从 device2 获取的 IP 格式为 192.168.xxx.yyy

我把android.permission.INTERNET、android.permission.ACCESS_WIFI_STATE和android.permission.RECORD_AUDIO放到Manifest文件中

MainActivity.java:

package com.applications.fihdi.testapp487623;

import android.content.Context;
import android.media.AudioManager;
import android.net.rtp.*;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.widget.*;

import java.io.*;
import java.net.*;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);


        try {
            String ip = getLocalIPAddress();
            Log.d("VOIP","String ip: " + ip);

            AudioManager audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            audio.setMode(AudioManager.MODE_IN_COMMUNICATION);
            final AudioGroup m_AudioGroup = new AudioGroup();
            m_AudioGroup.setMode(AudioGroup.MODE_NORMAL);
            final AudioStream m_AudioStream = new AudioStream(InetAddress.getByName(ip));
            Log.d("VOIP","localhost (same as ip??): = " + InetAddress.getLocalHost());

            int localPort = m_AudioStream.getLocalPort();

            Log.d("VOIP","Local Port: "+ Integer.toString(localPort));
            m_AudioStream.setCodec(AudioCodec.PCMU);
            m_AudioStream.setMode(RtpStream.MODE_NORMAL);

            ((TextView) findViewById(R.id.lblLocalPort)).setText(String.valueOf(localPort));

            ((TextView) findViewById(R.id.statusLabel)).setText("Status: local port number generated");

            findViewById(R.id.connectButton).setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    Log.d("VOIP","ConnectButton pressed");
                    String remoteAddress;
                    String remotePort;

                         remoteAddress = ((EditText) findViewById(R.id.editText2)).getText().toString();
                        //String remoteAddress = fetchIPs().get(0);
                         remotePort = ((EditText) findViewById(R.id.editText1)).getText().toString();

                    //Log.d("VOIP", fetchIPs().get(0));

                    try {
                        m_AudioStream.associate(InetAddress.getByName(remoteAddress), Integer.parseInt(remotePort));
                        Log.d("VOIP","AudioStream associated");
                        ((TextView) findViewById(R.id.statusLabel)).setText("Status: connected to: " + fetchIPs().get(0));
                        m_AudioStream.join(m_AudioGroup);
                        Log.d("VOIP","AudioStream joined");
                    } catch (Exception e) {
                        ((TextView) findViewById(R.id.statusLabel)).setText("Couldn't connect");
                        Log.d("VOIP","Exception with associating");
                    }

                }
            });

            findViewById(R.id.DisconnectButton).setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    m_AudioStream.release();
                }
            });

        } catch (Exception e) {
            Log.e("VOIP", "Exception when setting up the Audiostream!");
            e.printStackTrace();
        }
        findViewById(R.id.fetchButtons).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {

                Log.d("VOIP","FetchIp Button pressed");
                ArrayList<String> connectedIPs = fetchIPs();
                ((EditText) findViewById(R.id.editText2)).setText(connectedIPs.get(0));

                for(int i = 0; i<connectedIPs.size(); i++){
                    Log.d("VOIP", "connectedIps[" + i + "]: " + connectedIPs.get(i));
                }
            }
        });

    }

    public String getLocalIPAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        String ip = Formatter.formatIpAddress(inetAddress.hashCode());
                        Log.d("VOIP", "***** IP="+ ip);
                        return ip;
                    }
                }
            }
        } catch (SocketException ex) {
            Log.e("VOIP", ex.toString());
        }
        return null;
    }

    public ArrayList<String> fetchIPs() {
        BufferedReader bufRead = null;
        ArrayList<String> result = null;

        try {
            result = new ArrayList<String>();
            bufRead = new BufferedReader(new FileReader("/proc/net/arp"));
            String fileLine;
            while ((fileLine = bufRead.readLine()) != null) {


                String[] splitted = fileLine.split(" +");

                if ((splitted != null) && (splitted.length >= 4)) {

                    String mac = splitted[3];
                    if (mac.matches("..:..:..:..:..:..")) {
                        try {
                            String ping = "ping  -c 1 -W 1 " + splitted[0];
                            Runtime run = Runtime.getRuntime();
                            Process pro = run.exec(ping);
                            try {
                                pro.waitFor();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            int exit = pro.exitValue();
                            if (exit == 0) {
                                result.add(splitted[0]);
                            } else {
                                throw new Exception();
                            }
                        } catch (Exception e) {
                            Log.d("MainActivity", "Something went wrong with pinging the adress: " + splitted[0]);
                            Log.d("MainActivity", e.getMessage());
                        }
                    }
                }
            }
        } catch (Exception e) {

        }
            try {
                bufRead.close();
            } catch (Exception e) {

            }



        return result;
    }
}

main_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/lblLocalPort"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/localPort" />

    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="@string/iPHint"
        android:inputType="phone" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="@string/portHint"
        android:inputType="number" >

        <requestFocus />
    </EditText>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp">

        <Button
            android:id="@+id/connectButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/connect" />

        <Button
            android:id="@+id/DisconnectButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Disconnect" />

        <Button
            android:id="@+id/fetchButtons"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Fetch IPs" />
    </LinearLayout>

    <TextView
        android:id="@+id/statusLabel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView" />
</LinearLayout>

dimens.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="activity_vertical_margin">8dp</dimen>
<dimen name="activity_horizontal_margin">8dp</dimen>
</resources>

【问题讨论】:

    标签: android voip audio-streaming personal-hotspot


    【解决方案1】:

    getLocalIPAddress() 应该返回 Wifi 网络接口的 IP 地址。

    在当前代码中,您将返回列表中网络接口的第一个 IP 地址。

    您应该检查 netInterface.getName() 并与 wifi 接口名称进行比较并返回 IP 地址。

    一旦您的 IP 地址正确,您就可以继续进行。

    【讨论】:

    • 所以device1(托管热点的那个)的IP地址也需要以192.168.xxx.yyy的形式返回吗? this piece of code by @ajma 会成功吗?
    • 类似的代码应该可以解决问题,你没有使用wlan,检查热点网络接口。您可以先循环打印所有界面,然后检查。
    • 两个设备是否运行相同的代码,除了 device2 使用 wlan 网络接口 (wlan0) 的地址初始化其 AudioStream 而 device1 使用热点地址 (ap0) 初始化其 AudioStream 之外?我的老师根本没有接触过AudioStream/AudioGroup,他说主机和客户端需要不同的代码。
    • 我正在讨论网络接口,两个设备都应该在同一个网络中(192.168.xxx.yyy)。对于音频处理,双方都应该实现发送和接收逻辑。传输部分将有音频记录,接收器应该有音频播放。
    • 我检索了两台设备的 IP 地址,它们在同一个网络中。互相ping通工作。但是两个设备是否运行相同的代码来进行实时通信?我有点不想在这里对每一个小问题发表评论,你能在 Discord (dieomgkatze#7368) 上与我联系,以便我们聊天吗? (我得到这个工作有点重要)
    猜你喜欢
    • 2015-01-31
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    相关资源
    最近更新 更多