I am developing an application which first discover the peers in range and then connect with all of them one by one my function look like this:
void connectTo(WifiP2pDevice device) {
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.groupOwnerIntent=15;
wifiP2pManager.connect(wifiDirectChannel, config, actionListener);
wifiP2pManager.createGroup(wifiDirectChannel, actionListener);
}
But I don't know the difference between the connect and createGroup function of Wifip2pManager class. What's the core difference between them, Please help!
I know I am late to answer but I am sure it would help others. There is no need to createGroup, you simply need to call connect method in this way:
void connectTo(WifiP2pDevice device) {
WifiP2pConfig wifiP2pConfig = new WifiP2pConfig();
wifiP2pConfig.deviceAddress = device.deviceAddress;
wifiP2pConfig.groupOwnerIntent = 0;
wifiP2pConfig.wps.setup = WpsInfo.PBC;
if (wifiP2pManager != null) {
wifiP2pManager.connect(mChannel, wifiP2pConfig,
new ActionListener() {
#Override
public void onSuccess() {
// WiFiDirectBroadcastReceiver will notify us.
// Ignore for now.
Utility.showToast(
WifiP2PConnectionActivity.this,
Constants.CONNECTED);
}
#Override
public void onFailure(int reason) {
Utility.showToast(
WifiP2PConnectionActivity.this,
getErrorMessage(reason));
}
});
}
It will get connected now.
wifiP2pConfig.groupOwnerIntent = 0; is set to zero so that you allow other device to become owner and your own device as client everytime. groupOwnerIntent prioritices our own device priority to be lesser of becoming groupOwner. Rest is upto you how you want your device to behave.
Related
I'm new to Android Studio and I'm using the functionality of Local Only Hotspot to turn on and off programmatically the hotspot (found this two post for reference: How to turn on/off wifi hotspot programmatically in Android 8.0 (Oreo),How to turn on Wifi-Hotspot programmatically on Android >= 7.1 (including sharing the internet access)? .
private void turnOnHotspot() {
wifiManager.startLocalOnlyHotspot(new
WifiManager.LocalOnlyHotspotCallback()
{
#Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
hotspotReservation = reservation;
String key = hotspotReservation.getWifiConfiguration().preSharedKey;
String ussid = hotspotReservation.getWifiConfiguration().SSID;
System.out.println("KEY: "+ key);
System.out.println("USSID: "+ ussid);
currentConfig = hotspotReservation.getWifiConfiguration();
System.out.println("STARTED THE HOTSPOT");
}
#Override
public void onStopped() {
super.onStopped();
System.out.println("STOPPED THE HOTSPOT");
}
#Override
public void onFailed(int reason) {
super.onFailed(reason);
System.out.println("FAILED THE HOTSPOT");
}
}, new Handler());
}
private void turnOffHotspot() {
active = false;
if (hotspotReservation != null) {
hotspotReservation.close();
System.out.println("CLOSE HOTSPOT");
}
}
But from what I gather from other older posts and documentation, this method gives a local network without internet access and a random SSID and Password that cannot be personalised.
I need to connect only one device to this hotspot to share the mobile data (to have internet access), but I didn't find anything that could have help me. Is there another alternative?
Is there any way to automatically connect a specific device via Bluetooth LE on app startup?
I've been scrolling through stack overflow for the past few hours and have seen a number of similar questions, although majority are quite outdated and deal with reflections or other complex methods that I can't quite comprehend (these methods I've tried to implement, but not successfully, as I didn't really understand what was going on).
So far, I've managed to find the device by its friendly name, although I have no clue what to execute in that if statement. This is within my MainActivity:
protected void onCreate(Bundle savedInstanceState) {
...
if (bluetoothAdapter == null) {
Toast.makeText(getApplicationContext(),"Bluetooth not supported",Toast.LENGTH_SHORT).show();
} else {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if(pairedDevices.size()>0){
for(BluetoothDevice device: pairedDevices){
if (deviceName.equals(device.getName())) {
//Device found!
//Now how do I pair it?
break;
}
...
Assuming you've successfully identified the BlueToothDevice, you now need to connect to the GATT(Generic Attribute Profile), which allows you to transfer data.
Use the BlueToothDevice.connectGatt method. Using the first overload, the method takes in a Context , a boolean (false = directly connect, true = connect when available), and a BlueToothGhattCallback. The callback receives info from the device.
BlueToothGatt blueToothGatt = device.connectGatt(this, false, blueToothGattCallback);
An example to implement the callback:
BluetoothGattCallback blueToothGattCallback =
new BluetoothGattCallback()
{
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if(newState == BlueToothProfile.STATE_CONNECTED){
/* do stuff */
}
}
}
More details on the callbacks here.
Ended up scrolling through the source code for this app, particularly the SerialSocket, SerialService and SerialListener files which completely solved my problem.
After connectivityManager.getActiveNetworkInfo() got deprecated in API 29, it was quite a struggle to put together a network monitoring function that would also distinguish metered (cell) vs WiFi connection.
The problems I faced were 2:
connectivityManager.isActiveNetworkMetered() -- when both WiFi and Mobile data were on, it returned true (at least on my emulator, and I couldn't check on a device). When only WiFi was on, it returned false, as expected.
connectivityManager.isDefaultNetworkActive() -- it would always be active even if WiFi and Mobile were off.
The only way I found to work around this is via (1) onCapabilitiesChanged() and (2) getActiveNetwork()==null. The code is pasted below.
Do you know if there are other ways to do it? The whole implementation seems cumbersome, and the internet is full of deprecated examples.
Thanks
private static void monitorNetworks(){
NetworkRequest.Builder builder = new NetworkRequest.Builder();
connectivityManager.registerNetworkCallback(
builder.build(),
ncb = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
scanAndSend();
}
#Override
public void onLost(Network network) {
scanAndSend();
}
#Override
public void onUnavailable(){
scanAndSend();
}
#Override
public void onCapabilitiesChanged (Network network,
NetworkCapabilities networkCapabilities){
boolean metered = !networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
Log.d(TAG, "NET_CAPABILITY_NOT_METERED: " +
String.valueOf(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)));
sendMetered(metered);
}
}
);
}
private static void scanAndSend(){
boolean is_connected = false;
if(connectivityManager.getActiveNetwork()==null) is_connected = false;
else is_connected = true;
sendConnectivityIntent(IS_NETWORK_AVAILABLE, is_connected);
}
private static void sendMetered(boolean metered) {
sendIntent(IS_NETWORK_METERED, metered);
}
private static void sendIntent(String val_name, boolean val) {
Intent intent = new Intent();
intent.setAction(CONNECTIVITY_ACTION);
intent.putExtra(val_name, val);
context.sendBroadcast(intent);
}
I'm making an Android app using Couchbase. There are two devices connected to the same WiFi synchronizing data. I was using Couchbase Sync Gateway but the project needs to be peer to peer, without Sync Gateway in the middle. When I used Sync Gateway every change in one app was updated immediately. But now it's not working. The function I'm using:
private void showAnswers() {
manager = DataManager.getSharedInstance(getApplicationContext());
answersQuery = Answer.getAnswersForQuestion(manager.database, mQuestion.get_id());
liveQuery = answersQuery.toLiveQuery();
liveQuery.addChangeListener(new LiveQuery.ChangeListener() {
#Override
public void changed(LiveQuery.ChangeEvent event) {
QueryEnumerator result = event.getRows();
Map<String, Integer> counts = getAnswerCounts(result);
adapter = (QuestionOptionsAdapter) mQuestionOptions.getAdapter();
adapter.setAnswerCounts(counts);
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});
}
});
liveQuery.start();
}
I don't know why the Live Query change listener isn't working. It just works once when I start the Activity.
Thank you everybody for your help.
Due to the breaking changes in Android WebRTC client's example, I'm looking for the code-example which shows how to add and work with DataChannel in Android. I need to just send "Hello Worlds" via DataChannel between 2 Android devices. Here's the old code:
https://chromium.googlesource.com/external/webrtc/stable/talk/+/master/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java#177
It uses some classes and interfaces which don't exist in the new version anymore.
So how can I add support of DataChannel to my Android WebRTC application, send and receive a text through it?
I added DataChannel in a project with an older version of webrtc. I looked at the most up to date classes and it seems the methods and callbacks are still there, so hopefully it will work for you.
Changes to PeerConnectionClient:
Create DataChannel in createPeerConnectionInternal after isInitiator = false;:
DataChannel.Init dcInit = new DataChannel.Init();
dcInit.id = 1;
dataChannel = pc.createDataChannel("1", dcInit);;
dataChannel.registerObserver(new DcObserver());
Changes to onDataChannel:
#Override
public void onDataChannel(final DataChannel dc) {
Log.d(TAG, "onDataChannel");
executor.execute(new Runnable() {
#Override
public void run() {
dataChannel = dc;
String channelName = dataChannel.label();
dataChannel.registerObserver(new DcObserver());
}
});
}
Add the channel observer:
private class DcObserver implements DataChannel.Observer {
#Override
public void onMessage(final DataChannel.Buffer buffer) {
ByteBuffer data = buffer.data;
byte[] bytes = new byte[data.remaining()];
data.get(bytes);
final String command = new String(bytes);
executor.execute(new Runnable() {
public void run() {
events.onReceivedData(command);
}
});
}
#Override
public void onStateChange() {
Log.d(TAG, "DataChannel: onStateChange: " + dataChannel.state());
}
}
I added onReceivedDataevents to PeerConnectionEvents interface and all the events are implemented in the CallActivity so I handle the data received on the channel from there.
To send data, from CallActivity:
public void sendData(final String data) {
ByteBuffer buffer = ByteBuffer.wrap(data.getBytes());
peerConnectionClient.getPCDataChannel().send(new DataChannel.Buffer(buffer, false));
}
I only took a quick look at the new classes and made minor changes to my code, I hope it will work for you with no more changes.
Good luck
I'm sorry that I have a question to the code from Guy S.
In your code, there are two following statements in both createPeerConnectionInternal() and onDataChannel().
dataChannel.registerObserver(new DcObserver());
I think it may cause twice registrations. Is it correct??
I mean, before making a call, it created a dataChannal and registered an Observer. Then.. if there is a call comes in, the onDataChannel called, then the dataChannel point to dc and register again??