Cannot use WifiP2pManager.setDeviceName on Android 11 (Wi-Fi Direct) - java

My team and I are working with Wi-Fi Direct technology on Android devices. Until now, the used devices were on Android 8, 9 and 10. We were able to change the Wifi P2P device name of the devices via the WifiP2pManager.setDeviceName method.
Unfortunately, from Android 11 it is impossible to call this method without system permissions.
I came here to ask you if there is a solution to change the WifiP2p device name of non-rooted Android 11 devices programmatically.
If not, is there an alternative to Wi-Fi Direct (excepted Bluetooth) supported from Android 8 on which you can start a connection between two (or more) devices, communicate and send files programmatically without a connection to the internet?
Thank you

Maybe now it's too late but just in case :
We had to use reflection to change our device names.
We're using this implementation :
public void setDeviceName(String name) {
if(name.length() > 32) { // Name size limit is 32 chars.
name = name.substring(0, 32);
}
Class[] paramTypes = new Class[3];
paramTypes[0] = WifiP2pManager.Channel.class;
paramTypes[1] = String.class;
paramTypes[2] = WifiP2pManager.ActionListener.class;
Object[] argList = new Object[3];
argList[0] = mChannel; // Your current channel
argList[1] = name;
argList[2] = new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Log.d(TAG, "Wifi name successfully set to " + name);
}
#Override
public void onFailure(int reason) {
Log.e(TAG, "Device name set failed: reason = " + reason);
}
};
try {
Method setDeviceNameMethod = WifiP2pManager.class.getMethod("setDeviceName", paramTypes);
setDeviceNameMethod.setAccessible(true);
setDeviceNameMethod.invoke(mWifiP2pMgr, argList);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException |
IllegalArgumentException e) {
Log.e(TAG, "Exception while trying to set device name.\n" + e.toString());
}
}

Related

trying to customize hotspot SSID but stuck at WifiConfiguration

I'm trying to make an app on android studio that can customize the user's hotspot name (SSID), but found that WifiConfiguration was deprecated. I'm not sure about the difference between "NetworkSpecifier" and "WifiNetworkSuggestion", and how to use them to fix this. I'm new to android studio and I couldn't find a similar solution. Can anyone teach me what should I do? Or is it possible to customize it?
`
public void configureHotspot(String name) {
WifiConfiguration apConfig = new WifiConfiguration();
apConfig.SSID = name;
apConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
try {
Method setConfigMethod = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
boolean status = (boolean) setConfigMethod.invoke(mWifiManager, apConfig);
Log.d(TAG, "setWifiApConfiguration - success? " + status);
} catch (Exception e) {
Log.e(TAG, "Error in configureHotspot");
e.printStackTrace();
}
}
`
This part of the code is from this example: "https://github.com/aegis1980/WifiHotSpot", in "MyOreoWifiManager.java".
(this is the only example I found that can successfully turn on my phone's hotspot.)
I think I could keep the try-and-catch part because "WifiManager" is not deprecated, so maybe the problem is at apConfig only.

Issues with converting java to c#

I'm attempting to convert the code located at How to use signalr in android Service from java to c# and have been making some progress. I'm now stuck at the final method. The java code is:
private void startSignalR() {
Platform.loadPlatformComponent(new AndroidPlatformComponent());
mInstance.setmHubConnection();
mInstance.setHubProxy();
ClientTransport clientTransport = new ServerSentEventsTransport(mInstance.mHubConnection.getLogger());
SignalRFuture<Void> signalRFuture = mInstance.mHubConnection.start(clientTransport);
try {
signalRFuture.get();
} catch (InterruptedException | ExecutionException e) {
Log.e("SimpleSignalR", e.toString());
return;
}
mInstance.sendMessage(MainActivity.unm,"Hello All!");
String CLIENT_METHOD_BROADAST_MESSAGE = "recievedMessage";
mInstance.mHubProxy.on(CLIENT_METHOD_BROADAST_MESSAGE,
new SubscriptionHandler2<String,LoginInfo>() {
#Override
public void run(final String msg,final LoginInfo loginInfo) {
final String finalMsg = loginInfo.FullName + " says " + loginInfo.Password;
Intent intent = new Intent();
intent.setAction(MY_ACTION);
intent.putExtra("DATAPASSED", finalMsg);
sendBroadcast(intent);
}
}
, String.class,LoginInfo.class);
}
Using a java to c# converter, this translated to:
private void startSignalR()
{
Platform.loadPlatformComponent(new AndroidPlatformComponent());
mInstance.setmHubConnection();
mInstance.setHubProxy();
ClientTransport clientTransport = new ServerSentEventsTransport(mInstance.mHubConnection.Logger);
SignalRFuture<Void> signalRFuture = mInstance.mHubConnection.Start(clientTransport);
try
{
signalRFuture.get();
}
catch (Exception e) when (e is InterruptedException || e is ExecutionException)
{
// Log.e("SimpleSignalR", e.ToString());
return;
}
mInstance.sendMessage("", "Hello All!");
string CLIENT_METHOD_BROADAST_MESSAGE = "recievedMessage";
//String CLIENT_METHOD_BROADAST_MESSAGE = "messageReceived";
mInstance.mHubProxy.on(CLIENT_METHOD_BROADAST_MESSAGE, new SubscriptionHandler2AnonymousInnerClass(this)
, typeof(string), typeof(LoginInfo));
}
private class SubscriptionHandler2AnonymousInnerClass : SubscriptionHandler2<string, LoginInfo>
{
private readonly SignalRSrv outerInstance;
public SubscriptionHandler2AnonymousInnerClass(SignalRSrv outerInstance)
{
this.outerInstance = outerInstance;
}
//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
//ORIGINAL LINE: #Override public void run(final String msg,final LoginInfo loginInfo)
public override void run(string msg, LoginInfo loginInfo)
{
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final String finalMsg = loginInfo.FullName + " says " + loginInfo.Password;
string finalMsg = loginInfo.FullName + " says " + loginInfo.Password;
Intent intent = new Intent();
intent.Action = MY_ACTION;
intent.PutExtra("DATAPASSED", finalMsg);
sendBroadcast(intent);
}
}
This, of course, generated several errors in Visual Studio 2017.
First, the line Platform.loadPlatformComponent(new AndroidPlatformComponent()); generated the error Platform is inaccessible due to its protection level. Platform in Xamarin for Visual Studio 2017 is indeed protected and is a internal class in System and I cannot change this, so I'm at a loss as how to proceed with it. The same line generates the error The type or namespace name 'AndroidPlatformComponent' could not be found, these errors a numerous and not unexpected I just can't find an equivalent to AndroidPlatformComponent in Visual Studio 2017 so I'm at a loss as how to solve this one.
Next, on this line ClientTransport clientTransport = new ServerSentEventsTransport(mInstance.mHubConnection.Logger); generates the error The type or namespace name 'ClientTransport' could not be found, I was also unable to find an equivalent to this and again I'm at a loss as to proceed. Also on this line, .Logger is not defined for the hub connection, apparently it's .getLogger() in java, I was unable to find an equivalent for this one as well.
Next the line SignalRFuture<Void> signalRFuture = mInstance.mHubConnection.Start(clientTransport);' generates the error 1The type or namespace name 'SignalRFuture<>' could not be found, this seemes to be specific to SignalR, again, I am unable to find an equivalent.
The next one has me totally stumped, the line private class SubscriptionHandler2AnonymousInnerClass : SubscriptionHandler2<string, LoginInfo> generates the error The type or namespace name 'SubscriptionHandler2<,>' could not be found. I've looked everywhere online and read up on AnonymousInnerClass, but it was not help with this.
I'm hoping that the users here are more familiar with SignalR and the differences between c# functionality and java functionality. I'm not at all familiar with java nor am I familiar with SignalR and foreground services.
As it turns out, the last method in the java code I was converting was wiring up an event to pass the message received from the hub to the activity. In c# / Visual Studio (2017), that's done very differently which is why I didn't understand/recognize what was going on. So I created a handler in C# and execute a popup message for the message. This in itself may pose problems, but at least I know what's going on. This is the code I wrote to start SignalR from within the service and WireUp the handler:
private void startSignalR()
{
// Company, Department, and section are private variables
// their values are pulled from the intent bundle
// in the OnBind method, that code is:
// Bundle bundlee = intent.GetBundleExtra("TheBundle");
// MyUser = bundlee.GetParcelable("MyUser") as User;
// This information is put into the bundle when the user is logged in.
// I then pass that information to the SignalR client
// when I set the hub connection and placed on the querystring to the hub.
mInstance.setmHubConnection(username, firstname,lastname,company,department,section);
mInstance.setHubProxy();
try
{
// Connect the client to the hup
mInstance.mHubConnection.Start();
// Set the event handler
mInstance.WireUp();
}
catch (System.Exception e) when (e is InterruptedException || e is ExecutionException)
{
ShowMessage("Error: + e.Message)
}
}
This is the WireUp code, this is a method in the client code:
public void WireUp()
{
// set the event handler
mHubProxy.On("broadcastMessage", (string platform, string message) =>
{
if (OnMessageReceived != null)
OnMessageReceived(this, string.Format("{0}: {1}", platform, message));
});
}
As I had anticipated, the popup message won't appear when the app is in the background, so I'm researching a workaround

How to check which sim is set as default sim in android programatically

I am trying to check if my if my mobile device is dual sim, if sim1 is ready, if sim2 is ready, I am done with this using java reflection, now i want to find out if sim1 isRoaming and if sim2 isRoaming, and if its dual sim which sim is set as default. Is it possible with the help of java reflection.
You can do something like this:
public int getDefaultSimmm(Context context) {
Object tm = context.getSystemService(Context.TELEPHONY_SERVICE);
Method method_getDefaultSim;
int defaultSimm = -1;
try {
method_getDefaultSim = tm.getClass().getDeclaredMethod("getDefaultSim");
method_getDefaultSim.setAccessible(true);
defaultSimm = (Integer) method_getDefaultSim.invoke(tm);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Method method_getSmsDefaultSim;
int smsDefaultSim = -1;
try {
method_getSmsDefaultSim = tm.getClass().getDeclaredMethod("getSmsDefaultSim");
smsDefaultSim = (Integer) method_getSmsDefaultSim.invoke(tm);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return smsDefaultSim;
}
Starting from API 22 (Lollipop MR1) android has officially added SubscriptionManager class which gives all the information required by the developer in relation to sim cards and related services.
Documentation for SubscriptionManager
However support for retrieving defaults for calls, SMS and Mobile data were added in API 24.
If you use your minimum SDK version to 24 you can use getDefaultSmsSubscriptionId() method to get SMS default set by the user
SubscriptionManager manager = context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int defaultSmsId = manager.getDefaultSmsSubscriptionId();
SubscriptionInfo info = manager.getActiveSubscriptionInfo(defaultSmsId);
Note: Above mention call requires READ_PHONE_STATE permission. Make sure you add it in your manifest file
A very late answer but I got into developing an application which has the above requirement
Below is the latest way to get it done.
/**
* #return - True - if any sim selected as default sim , False - No default sim is selected or
* permission for reading the sim status is not enabled
*/
boolean isDefaultSimSetForCall() {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
Log.d(Utils.getTag(), "Read Phone state permission Disabled");
genericCallbacks.onPermissionAccessError(Constants.PermissionErrorCodes.READ_PHONE_STATE_ACCESS);
return false;
} else {
PhoneAccountHandle defaultPhoneAccount = telecomManager.getDefaultOutgoingPhoneAccount(Uri.fromParts("tel", "text", null).getScheme());
if (defaultPhoneAccount != null) {
Log.d(Utils.getTag(), "DefaultOutgoingPhoneAccount: " + defaultPhoneAccount.getId());
return true;
}
}
return false;
}
From the received PhoneAccountHandle, we can get the necessary fields

Retrieving MAC Address Programmatically - Android

I'm having an issue with retrieving the MAC address of the device programatically, before anyone mentions anything about other posts I have read them already such as:
How to find MAC address of an Android device programmatically
however I tried using the code with my own application and tested it with a simple log.d, only to find that it is returning nothing. The message of "seeing if this works shows" but nothing else. So i am presuming the mac address is null.
Log.d("seeing if this works", macAddress2);
The code of what I have done is shown here:
//Set onclick listener for the Get Mac Address button
getMac.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wInfo = wifiManager.getConnectionInfo();
String macAddress2 = wInfo.getMacAddress();
macAddress.setText(macAddress2);
}
});
Which Android version are you testing on? The latest(10/2015) Android M preview has blocked the app from getting the hardware identifiers for Wifi and Bluetooth.
To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.
There is a workaround by reading the Wifi MAC from /sys/class/net/wlan0/address, which however will also be blocked in the Android N as claimed by Google.
Try this:
public static String getMacAddr() {
try {
List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(Integer.toHexString(b & 0xFF) + ":");
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
return res1.toString();
}
} catch (Exception ex) {
}
return "02:00:00:00:00:00";
}
From here:
http://robinhenniges.com/en/android6-get-mac-address-programmatically
Works for me.
Do you have this in the manifest?
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

Desktop java app copy and transfer android data via USB

I have a desktop java app, and also an android app. Two app work together.
The user in desktop app have a button to launch the transfer between device data app to computer app and vice versa.
So I need to transfer data with a simple USB cable, and without internet connection/WiFi/Bluetooth/adb.
I found two Java MTP library that works on Windows to resolve my problem, and the USB Host/accesory fonctionnality of android:
jMTP successfully recognizes my Android devices, folder, and other things
I have success to transfer a file in computer ---> device, but i have an error when i try to transfer a file in device ---> computer
I put my code after the explaination.
jusbpmp but i don't have the possibility to transfer device ---> computer.
USB Host/accesory not usefull because transfer are launch from desktop app, and when i read on the android developper guide website, it seems to be not correspond from what i need, or maybe if the user start transfer from the device.
I try from 1 week to success in this task but it seems i need help.
Java + jMTP code
private static void jMTPeMethode()
{
PortableDeviceManager manager = new PortableDeviceManager();
PortableDevice device = manager.getDevices()[0];
// Connect to USB tablet
device.open();
System.out.println(device.getModel());
System.out.println("---------------");
// Iterate over deviceObjects
for (PortableDeviceObject object : device.getRootObjects())
{
// If the object is a storage object
if (object instanceof PortableDeviceStorageObject)
{
PortableDeviceStorageObject storage = (PortableDeviceStorageObject) object;
for (PortableDeviceObject o2 : storage.getChildObjects())
{
if(o2.getOriginalFileName().equalsIgnoreCase("Test"))
{
//Device to computer not working
PortableDeviceToHostImpl32 copy = new PortableDeviceToHostImpl32();
try
{
copy.copyFromPortableDeviceToHost(o2.getID(), "C:\\TransferTest", device);
} catch (COMException ex)
{
}
// //Host to Device working
// BigInteger bigInteger1 = new BigInteger("123456789");
// File file = new File("c:/GettingJMTP.pdf");
// try {
// storage.addAudioObject(file, "jj", "jj", bigInteger1);
// } catch (Exception e) {
// //System.out.println("Exception e = " + e);
// }
}
System.out.println(o2.getOriginalFileName());
}
}
}
manager.getDevices()[0].close();
}
This is the result of the code and the error
`
Nexus 9
---------------
Music
Podcasts
Ringtones
Alarms
Notifications
Pictures
Movies
Download
DCIM
Android
! Failed to get IStream (representing object data on the device) from IPortableDeviceResources, hr = 0x80070057
test
ReleveData
`
I read in internet 0x80070057 is a generic windows exception .
Edit:
Windows site say for the hr error
ERROR_INVALID_PARAMETER 0x80070057 :
The parameter supplied by the application is not valid.
But i don't see witch parameter is not valid
Here is the link of C class of the library use for transfer data device to computer, you can see my error line 230.
And this is the jMTP library i use.
Can you help me, or purpose an other way to do what i need(Usb4Java, libUSB) ? I shall be really grateful.
Thanks by advance.
Ok, i found the problem.
The problem come from o2.getID() parameter give to the methode copy.copyFromPortableDeviceToHost.
Because o2 representing the folder, and not the file in the folder, so it's not possible to send folder, for success i need to send file in folder.
So i cast my PortableDeviceObject o2 to an PortableDeviceFolderObject, so that get a list of child Object with targetFolder.getChildObjects() in the PortableDeviceFolderObject representing files' and then i can iterate on any child objet from the folder.
And for each file i call the methode copy.copyFromPortableDeviceToHost, with the right id.
Here is the correction code, copy/transfer file from computer to device and device to computer.
I hope it's help.
public class USBTransfertMain {
public static void main(String[] args) throws Throwable {
jMTPeMethode();
}
private static void jMTPeMethode()
{
PortableDeviceFolderObject targetFolder = null;
PortableDeviceManager manager = new PortableDeviceManager();
PortableDevice device = manager.getDevices()[0];
// Connect to USB tablet
device.open();
System.out.println(device.getModel());
System.out.println("---------------");
// Iterate over deviceObjects
for (PortableDeviceObject object : device.getRootObjects())
{
// If the object is a storage object
if (object instanceof PortableDeviceStorageObject)
{
PortableDeviceStorageObject storage = (PortableDeviceStorageObject) object;
for (PortableDeviceObject o2 : storage.getChildObjects())
{
if(o2.getOriginalFileName().equalsIgnoreCase("testFolder"))
{
targetFolder = (PortableDeviceFolderObject) o2;
}
System.out.println(o2.getOriginalFileName());
}
copyFileFromComputerToDeviceFolder(targetFolder);
PortableDeviceObject[] folderFiles = targetFolder.getChildObjects();
for (PortableDeviceObject pDO : folderFiles) {
copyFileFromDeviceToComputerFolder(pDO, device);
}
}
}
manager.getDevices()[0].close();
}
private static void copyFileFromDeviceToComputerFolder(PortableDeviceObject pDO, PortableDevice device)
{
PortableDeviceToHostImpl32 copy = new PortableDeviceToHostImpl32();
try {
copy.copyFromPortableDeviceToHost(pDO.getID(), "C:\\TransferTest", device);
} catch (COMException ex) {
ex.printStackTrace();
}
}
private static void copyFileFromComputerToDeviceFolder(PortableDeviceFolderObject targetFolder)
{
BigInteger bigInteger1 = new BigInteger("123456789");
File file = new File("C:\\GettingJMTP.pdf");
try {
targetFolder.addAudioObject(file, "jj", "jj", bigInteger1);
} catch (Exception e) {
System.out.println("Exception e = " + e);
}
}
}

Categories