此处的主要活动代码和 logcat文件,我使用的是Android Studio上一版本。如果有人知道,请帮助!;
public class MainActivity extends WifiActivity implements OnTouchListener{
private ImageButton mSpeakButton;
private TextView mDisplay;
private DisplayAsyncTask mDisplayTask;
private ImageView rxView;
private ImageView txView;
private static String mSendTempFile;
private static String mPlayTempFile;
private IntentFilter CIntentFilter;
private MediaRecorder mRecorder = null;
private MediaPlayer mPlayer = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WifiManager wifi = (WifiManager) getSystemService(this.WIFI_SERVICE);
wifi.setWifiEnabled(true);
CIntentFilter = new IntentFilter();
CIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
CIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
CIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
CIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
WifiP2pManager mManager = (WifiP2pManager) getSystemService(this.WIFI_P2P_SERVICE);
Channel mChannel = mManager.initialize(this, getMainLooper(), null);
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Toast.makeText(MainActivity.this,"Discovery Initiated",Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reasonCode) {
// Code for when the discovery initiation fails goes here.
// Alert the user that something went wrong.
}
});
mSpeakButton = (ImageButton) findViewById(R.id.speakButton);
mDisplay = (TextView) findViewById(R.id.screenText);
rxView = (ImageView) findViewById(R.id.rxView);
txView = (ImageView) findViewById(R.id.txView);
mSpeakButton.setOnTouchListener(this);
mSendTempFile = getFilesDir() + "/send_temp.3gp";
mPlayTempFile = getFilesDir() + "/play_temp.3gp";
}
@Override
protected void onResume() {
super.onResume();
mDisplayTask = new DisplayAsyncTask();
mDisplayTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
protected void onPause() {
super.onPause();
mDisplayTask.stop();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
private void bufToFile(byte[] buf, String fname) {
BufferedOutputStream bos;
try {
bos = new BufferedOutputStream(new FileOutputStream(new File(fname)));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
return;
}
try {
bos.write(buf);
bos.flush();
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected void showData(byte[] data) {
rxView.setImageResource(R.drawable.led_red_on);
Toast.makeText(this, "showData = " + data.length, Toast.LENGTH_SHORT).show();
bufToFile(data, mPlayTempFile);
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mPlayTempFile);
mPlayer.prepare();
mPlayer.start();
mPlayer.setLooping(false);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
mPlayer = null;
rxView.setImageResource(R.drawable.led_red_off);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
private void startRecording() {
txView.setImageResource(R.drawable.led_green_on);
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mSendTempFile);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mRecorder.start();
}
private byte[] fileToBuf(String fname) {
InputStream in;
try {
in = new BufferedInputStream(new FileInputStream(fname));
} catch (FileNotFoundException e) {
return null;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[100 * 1024];
try {
int len;
while ((len = in.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (IOException e) {
return null;
}
try {
bos.close();
in.close();
} catch (IOException e) {}
return bos.toByteArray();
}
private void stopRecording() {
txView.setImageResource(R.drawable.led_green_off);
try {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
} catch (RuntimeException e) {
e.printStackTrace();
return;
}
byte[] data = fileToBuf(mSendTempFile);
publishData(data);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
startRecording();
break;
case MotionEvent.ACTION_UP:
stopRecording();
break;
}
return false;
}
private class DisplayAsyncTask extends AsyncTask<Void, Void, Void> {
private boolean stop = false;
public void stop() {
stop = true;
}
@Override
protected Void doInBackground(Void... params) {
while(!stop) {
publishProgress();
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {}
}
return null;
}
@Override
public void onProgressUpdate(Void... values) {
StringBuilder sb = new StringBuilder();
ConnectionState state = MainActivity.this.getState();
if(state.mConnected) {
sb.append("CONNECTED\n");
if(state.mWeAreGroupOwner) {
sb.append("GO\n");
} else {
sb.append("CL\n");
}
} else {
sb.append("NOT CONNECTED\n");
}
mDisplay.setText(sb.toString());
}
}
}
和错误logcat文件
wifidirecttalkie, PID: 14950
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.senniksoft.wifidirecttalkie/com.senniksoft.wifidirecttalkie.MainActivity}: java.lang.IllegalArgumentException: instance name or service type cannot be empty
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2338)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: instance name or service type cannot be empty
at android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo.newInstance(WifiP2pDnsSdServiceInfo.java:94)
at com.senniksoft.wifidirecttalkie.WifiActivity.setupService(WifiActivity.java:90)
at com.senniksoft.wifidirecttalkie.WifiActivity.onCreate(WifiActivity.java:112)
at com.senniksoft.wifidirecttalkie.MainActivity.onCreate(MainActivity.java:51)
at android.app.Activity.performCreate(Activity.java:5293)
和WifiActivity代码
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener;
import android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.ViewSwitcher;
import com.senniksoft.wifidirecttalkie.ConnectionState.Buddy;
public abstract class WifiActivity extends Activity {
private WifiP2pManager mManager;
private Channel mChannel;
private BroadcastReceiver mReceiver;
private IntentFilter mIntentFilter;
private TextView mTextView;
private TextView mStatTextView;
private WifiP2pDnsSdServiceInfo mServiceInfo;
private WifiP2pDnsSdServiceRequest mServiceRequest;
private MessageDeduplicator mDeduplicator = new MessageDeduplicator();
private DiscoveryBGThread mDiscoveryTask;
private StatusDisplayBGThread mStatusUpdateTask;
private ConnectionBGThread mConnectionTask;
private ServerBGThread mServerTask;
private final static String LOGTAG = "WIFI_P2P_VS";
private final String SERVICE_NAME = "_walkietalkie._tcp";
public final static int SERVER_PORT = 42634;
private TextView mConnStatTextView;
private RegisterClientBGThread mRegisterTask;
private ReceivedMessageShower mMessageShowTask;
/**
* Get mac address of our wifi adapter, notice that this can
* differ some bits from our Wifi P2P adapter address.
* @return
*/
private String getMacAddress() {
WifiManager wifiMan = (WifiManager) this.getSystemService(
Context.WIFI_SERVICE);
WifiInfo wifiInf = wifiMan.getConnectionInfo();
return wifiInf.getMacAddress();
}
/**
* Setup for service discovery/Bonjour
*/
private void setupService() {
// Create a string map containing information about your service.
Map<String, String> record = new HashMap<String, String>();
record.put("listenport", String.valueOf(SERVER_PORT));
record.put("device_name", Helpers.getDeviceName());
// Service information. Pass it an instance name, service type
// _protocol._transportlayer , and the map containing
// information other devices will want once they connect to this one.
mServiceInfo =
WifiP2pDnsSdServiceInfo.newInstance(getMacAddress(), SERVICE_NAME, record);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
mTextView = (TextView) findViewById(R.id.textView);
mStatTextView = (TextView) findViewById(R.id.statTextView);
mConnStatTextView = (TextView) findViewById(R.id.connStatTextView);
// add intent filter for getting Wifi Framework intents
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
setupService();
setupServiceListeners();
setupDebugButtons();
}
/**
* Buttons to switch betw phone and debug view
*/
private void setupDebugButtons() {
Button debugButton = (Button) findViewById(R.id.debugButton);
debugButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {((ViewSwitcher) findViewById(R.id.viewSwitcher)).showNext();}
});
debugButton = (Button) findViewById(R.id.debugButton2);
debugButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {((ViewSwitcher) findViewById(R.id.viewSwitcher)).showNext();}
});
}
@Override
protected void onResume() {
super.onResume();
// init a new connection state on every app resume
state = new ConnectionState(getMacAddress());
// register our broadcast receiver to listen for events
registerReceiver(mReceiver, mIntentFilter);
// register our bonjour service in the net
mManager.addLocalService(mChannel, mServiceInfo, null);
// listen for bonojour services of other peers
mServiceRequest = WifiP2pDnsSdServiceRequest.newInstance();
mManager.addServiceRequest(mChannel, mServiceRequest, null);
// start all background tasks
mDiscoveryTask = new DiscoveryBGThread();
mStatusUpdateTask = new StatusDisplayBGThread();
mConnectionTask = new ConnectionBGThread();
mServerTask = new ServerBGThread();
mRegisterTask = new RegisterClientBGThread();
mMessageShowTask = new ReceivedMessageShower();
mDiscoveryTask.start();
mStatusUpdateTask.start();
mConnectionTask.start();
mServerTask.start();
mRegisterTask.start();
mMessageShowTask.start();
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
// stop the background tasks
mDiscoveryTask.setStop();
mStatusUpdateTask.setStop();
mConnectionTask.setStop();
mServerTask.setStop();
mRegisterTask.setStop();
mMessageShowTask.setStop();
// unregister eveything
mManager.removeLocalService(mChannel, mServiceInfo, null);
mManager.removeServiceRequest(mChannel, mServiceRequest, null);
mManager.cancelConnect(mChannel, null);
mManager.removeGroup(mChannel, null);
}
/**
* Class to send data from the child
* class (MainActivity)
* @param data
*/
protected void publishData(byte[] data) {
if(state.mWeAreGroupOwner) {
broadcastData(data);
} else {
sendData(data);
}
}
protected abstract void showData(byte[] data);
private void broadcastData(byte[] data) {
if(!state.mWeAreGroupOwner) {
return;
}
Log.d(LOGTAG, "BROADCAST");
byte[] msg = NetworkProtocol.composeMessage(NetworkProtocol.CMD_SEND_DATA, data);
for(InetSocketAddress a: state.getClientAddresses()) {
Log.d(LOGTAG, "CLIENT BROADCAST TO IP="+a);
sendMessageToAddr(msg, a);
}
}
private void sendData(byte[] data) {
if(state.mWeAreGroupOwner) {
return;
}
Log.d(LOGTAG, "SEND");
byte[] msg = NetworkProtocol.composeMessage(NetworkProtocol.CMD_SEND_DATA, data);
mDeduplicator.addMessage(data);
sendMessageToAddr(msg, state.getGroupOwnerConnectionInfos());
}
private void dataReceived(byte[] data) {
if(!mDeduplicator.messageIsNew(data)) {
return;
}
// put into queue
messagesToProcess.offer(data);
// rebroadcast immediately
if(state.mWeAreGroupOwner) {
broadcastData(data);
}
}
private BlockingQueue<byte[]> messagesToProcess = new ArrayBlockingQueue<byte []>(100);
/**
* This thread looks on the queue which contains received messages.
* Every time we got one, we call showData() with the data in
* the queue. This is to serialize receive events which also
* might arrive concurrently.
* @author joni
*
*/
private class ReceivedMessageShower extends Thread {
private boolean stop = false;
public void setStop() {
stop = true;
}
@Override
public void run() {
while(!stop) {
try {
final byte[] data = messagesToProcess.poll(1000, TimeUnit.MILLISECONDS);
if(data != null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
showData(data);
}
});
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {}
}
}
}
}
private class ServerConnectionThread extends Thread {
private final Socket client;
public ServerConnectionThread(Socket client) {
this.client = client;
}
public void run() {
try {
InputStream in = client.getInputStream();
String cmd = NetworkProtocol.getMessageType(in);
if(cmd != null && cmd.equals(NetworkProtocol.CMD_REGISTER_CLIENT)) {
String mac = NetworkProtocol.getMacAddress(in);
state.updateClientIp(mac, client.getInetAddress());
}
if(cmd != null && cmd.equals(NetworkProtocol.CMD_SEND_DATA)) {
final byte[] data = NetworkProtocol.getData(in);
runOnUiThread(new Runnable() {
@Override
public void run() {
WifiActivity.this.dataReceived(data);
}
});
}
in.close();
client.close();
} catch (IOException e) {}
}
}
/**
* Async method to send a raw byte message to an ip address
* @param msg
* @param addr
*/
private void sendMessageToAddr(final byte[] msg, final InetSocketAddress addr) {
if(addr == null)
return;
new Thread() {
public void run() {
Socket socket = new Socket();
try {
socket.bind(null);
socket.connect(addr, 5000);
socket.getOutputStream().write(msg);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
/**
* Out of simplicity, every node runs this thread all the time.
* It tries to communicate to the group owner our mac address
* (and he can get over the socket also our ip address).
* @author joni
*
*/
private class RegisterClientBGThread extends Thread {
private boolean stop = false;
public void setStop() {
stop = true;
}
@Override
public void run() {
while(!stop) {
tryToRegister();
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {}
}
}
private void tryToRegister() {
if(!state.mConnected || state.mWeAreGroupOwner) {
return;
}
byte[] msg = NetworkProtocol.composeMessage(NetworkProtocol.CMD_REGISTER_CLIENT, getMacAddress());
sendMessageToAddr(msg, state.getGroupOwnerConnectionInfos());
}
}
private class ServerBGThread extends Thread {
private ServerSocket serverSocket;
public void setStop() {
try {
serverSocket.close();
} catch(Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
serverSocket = new ServerSocket(SERVER_PORT);
try {
while(true) {
Socket client = serverSocket.accept();
ServerConnectionThread conn = WifiActivity.this.new ServerConnectionThread(client);
conn.start();
}
} catch (SocketException e) {
// our serverSocket got killed, exit
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private ConnectionState state;
public ConnectionState getState() {
return state;
}
/**
* Called in onResume, sets up service discovery listeners
*/
private void setupServiceListeners() {
DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
@Override
/**
* Yay we got a device which published its name
*/
public void onDnsSdTxtRecordAvailable(String domain, Map<String, String> record, WifiP2pDevice device) {
state.updateStatus(device, record.get("device_name"));
try {
state.updateStatus(device,
Integer.parseInt(record.get("listenport")));
} catch(Exception e) {}
}
};
DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
@Override
public void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice device) {
if(ConnectionState.macAddressAlmostEqual(device.deviceAddress, getMacAddress())) {
return;
}
Buddy b = state.getBuddy(device.deviceAddress);
b.device = device;
if(registrationType.startsWith(SERVICE_NAME)) {
b.rightService = true;
}
}
};
mManager.setDnsSdResponseListeners(mChannel, servListener, txtListener);
}
/**
* Every 10sec, make a rediscovery of peers so we see new ones.
* The results are not received here but in the broadcast receiver.
* @author joni
*
*/
private class DiscoveryBGThread extends Thread {
private boolean stop = false;
public void setStop() {
stop = true;
}
@Override
public void run(){
while(!stop) {
mManager.discoverServices(mChannel, null);
mManager.requestConnectionInfo(mChannel, null);
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {}
}
}
}
/**
* Display debug info
* @author joni
*
*/
private class StatusDisplayBGThread extends Thread {
private boolean stop = false;
public void setStop() {
stop = true;
}
@Override
public void run() {
while(!stop) {
updateStatus();
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {}
}
}
private void updateStatus() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(state.buddiesToString());
mStatTextView.setText(state.toString());
}
});
}
}
/**
* Connect as soon as possible, reconnect, set state etc.
* @author joni
*
*/
private class ConnectionBGThread extends Thread {
private boolean stop = false;
public void setStop() {
stop = true;
}
This is main Wifi operation codes that does wifi peer to peer connections between mobile phones
@Override
public void run() {
while(!stop) {
manageConnection();
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {}
}
}
}
private void manageConnection() {
final StringBuilder connState = new StringBuilder();
if(state.connected()) {
connState.append("CONNECTED\n");
// search for buddies which have to be invited
for(Buddy b: state.findSingleBuddies()) {
connState.append("INVITE: " + b + "\n");
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = b.device.deviceAddress;
mManager.connect(mChannel, config, null);
}
} else {
connState.append("NOT CONNECTED\n");
if(state.haveGroupOwner()) {
connState.append("E GROUP OWNER, WAIT 10 sec\n");
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {}
} else {
connState.append("NO GROUP OWNER\n");
// try to connect to the first buddy
Buddy b = state.findBuddyToConnect();
if(b != null) {
connState.append("CONNECT TO: " + b + "\n");
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = b.device.deviceAddress;
mManager.connect(mChannel, config, null);
} else {
connState.append("NO BUDDY TO CONNECT TO\n");
}
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
mConnStatTextView.setText(connState.toString());
}
});
}
}
&#13;
这是主要的Wifi操作代码,用于在手机之间进行wifi对等连接
答案 0 :(得分:0)
您在WifiActivity中调用的newInstance
的静态方法WifiP2pDnsSdServiceInfo
似乎是错误的。这是方法签名:
public static WifiP2pDnsSdServiceInfo newInstance (String instanceName, String serviceType, Map<String, String> txtMap)
(Added in API level 16)
问题是(基于您的堆栈跟踪)instanceName或serviceType为空。确保在致电WifiP2pDnsSdServiceInfo.newInstance(getMacAddress(), SERVICE_NAME, record);
时getMacAddress()
和SERVICE_NAME
不为空。