jmdns.jar not working on android 4.0 or later - android

jMdns is a great java library to provide zeroconf/bonjour capabilities to your Android application.
I successfully using this in a project up until Android 4.0 Ice Cream Sandwich aka ICS, once Android 4.0 devices were starting to be used more often I am facing application not working.
I have tested application in android 4.0 earlier, it show me list of Discover Devices but in android 4.0 or later it show nothing.
I've tested this demo "https://github.com/twitwi/AndroidDnssdDemo" on 4.1 but its not working.
I have written Below code based on suggestion mention in "http://snctln.com/2012/08/03/jmdns-and-android-4-0/"
private android.net.wifi.WifiManager.MulticastLock lock;
private android.os.Handler handler = new android.os.Handler();
private JmDNS jmdns = null;
public WifiManager wifi;
private void setUp()
{
WifiManager wifiMgr = (WifiManager) getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
int ip = wifiInfo.getIpAddress();
String ipAddress = Formatter.formatIpAddress(ip);
try {
jmdns.create(_bindingAddress);
ServiceInfo[] infos = jmdns.list("_afpovertcp._tcp.local.");
for (int i=0; i < infos.length; i++) {
Log.i("Servic : ",infos[i].getName()+"");
// notifyUser("\nServic : "+infos[i].getName()+"");
}
} catch (IOException e) {
e.printStackTrace();
}
}
your suggestion are appreciable

My simple guess would be that it's trying to download data on the main thread. This is not possible from Ice Cream Sandwich and forward. Try to look at logcat while it runs on the phone, it should clearly show a warning/error message about it if it's the case.

You can let it run via the main thread ala
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}

Related

How to detect Samsung S10 5G is running on 5G network?

Android Q added a new network type, NETWORK_TYPE_NR for 5G which is
not available for Android Pie. Recently released Samsung S10 fully supports 5G. It can show 5G icon on the status bar when it is on the 5G network.
Is it possible for a third-party app to know if Android Pie device on a 5G network or not?
Any help will be appreciated.
The following link is the definition for the new network type. It is not available on the Android Pie branch.
Source code for Pie release
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/pie-release-2/telephony/java/android/telephony/TelephonyManager.java
The latest source code that has NETWORK_TYPE_NR
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/telephony/java/android/telephony/TelephonyManager.java#2375
I believe they backported the code from Q to Pie as the logic for 5G was implemented at the end of last year in Q (alpha).
So when using
TelephonyManager.getNetworkType()
you will likely get
20 (5G)
EDIT
As per comment below: The network type will be 13 so it doesn't solve the thing.
EDIT
Try using reflection
static boolean isNRConnected(TelephonyManager telephonyManager) {
try {
Object obj = Class.forName(telephonyManager.getClass().getName())
.getDeclaredMethod("getServiceState", new Class[0]).invoke(telephonyManager, new Object[0]);
Method[] methods = Class.forName(obj.getClass().getName()).getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("getNrStatus") || method.getName().equals("getNrState")) {
method.setAccessible(true);
return ((Integer) method.invoke(obj, new Object[0])).intValue() == 3;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
There is an official documentation to detect 5G on Android 11.
https://developer.android.com/about/versions/11/features/5g#detection
Call TelephonyManager.listen(), passing in LISTEN_DISPLAY_INFO_CHANGED, to determine if the user has a 5G network connection.
as #Hunter suggested you need to use "listen" from telephony manager but if it's api 30+ you need to have READ_PHONE permission granted and listen for LISTEN_DISPLAY_INFO_CHANGED and override onDisplayInfoChanged from PhoneStateListener
(context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).listen(customPhoneStateListener,PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
The listener should be something like this:
private class CustomPhoneStateListener : PhoneStateListener() {
override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
super.onDisplayInfoChanged(telephonyDisplayInfo)
when (telephonyDisplayInfo.overrideNetworkType) {
//5G
OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO,
OVERRIDE_NETWORK_TYPE_NR_NSA,
OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> setNetworkChange(NETWORK_TYPE_NR)
OVERRIDE_NETWORK_TYPE_LTE_CA -> {
setNetworkChange(19) //LTE+
}
else -> setNetworkChange(telephonyDisplayInfo.networkType)
}
} else {
setNetworkChange(telephonyDisplayInfo.networkType)
}
}
}
Link: https://developer.android.com/about/versions/11/features/5g#detection
Couldn't add this as a comment, but as #Pavel Machala said, looking at the ServiceState class in the AOSP yields the following:
/**
* Get the NR 5G status of the mobile data network.
* #return the NR 5G status.
* #hide
*/
public #NRStatus int getNrStatus() {
final NetworkRegistrationState regState = getNetworkRegistrationState(
NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState == null) return NetworkRegistrationState.NR_STATUS_NONE;
return regState.getNrStatus();
}
I have extracted the ServiceState.java from SM-G977N firmware and it confirms that they have added
ServiceState.getNrStatus()
5G(NR) is active is if NetworkRegistrationState.NR_STATUS_CONNECTED = 3;

Minimum db level of WIFI to communicate with Server in android

i want to send the data to server from an android app. some times i cant able to sync the whole data to server i think because of wifi db level if so what is the minimum db level can i use to start the sync. can anyone please explain me in that.
To get the db of the wifi i am using the following code
WifiManager wifiManager = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE);
List<ScanResult> scanResult = wifiManager.getScanResults();
for (int i = 0; i < scanResult.size(); i++) {
Log.d("scanResult", "Speed of wifi"+scanResult.get(i).level);//The db level of signal
}
return info.isConnected();

How to programmatically check if an Android device supports Bluetooth SPP profile?

I could not find any standard API in Android to check for SPP profile support. Is there any way (direct or indirect) by which one can determine this programmatically? One indirect method that I could think of was to use BluetoothAdapter.listenUsingRfcommWithServiceRecord to start an RFCOMM server socket, which should (presumably) succeed if the device supports SPP and fail otherwise. Would this work, or is there a better/correct way?
String sspUuid = "00001101-0000-1000-8000-00805f9b34fb";
boolean uuidExists = false;
ParcelUuid[] uuids = {};
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
uuids = device.getUuids()
} else {
Method getUuidsMethod = device.getClass().getMethod("getUuids", null);
uuids = (ParcelUuid[]) getUuidsMethod.invoke(device, null);
}
for (ParcelUuid uuid : uuids) {
if (uuid.toString().equalsIgnoreCase(sspUuid)) {
uuidExists = true;
break;
}
}
if (uuidExists) {
socket = device.createRfcommSocketToServiceRecord(UUID.fromString(sspUuid));
}
For anyone still wondering I use this that works on older and new version of android. Don't forget to add exception handling.

Device discovery in local network

I'm currently developing an android app using SDK >= 16 which should be able to discover different android devices (later also iOS devices) in a local area network using the WiFi radio.
My first guess was to use multicast which turned out to be non functional on my Samsung Galaxy S2: packets are only received when sent from the same device.
My second guess is to actively scan the network using a limited IP address range and wait for a proper response. Unfortunately, this implies that the network uses DHCP to address the IP addresses.
None of the above solutions seem to be the perfect solution.
My current solution for my first guess:
public class MulticastReceiver extends AsyncTask<Activity, Integer, String> {
private static final String host = "224.1.1.1";
private static final int port = 5007;
private static final String TAG = "MulticastReceiver";
protected String doInBackground(Activity... activities) {
WifiManager wm = (WifiManager)activities[0].getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock multicastLock = wm.createMulticastLock("mydebuginfo");
multicastLock.acquire();
String message = "Nothing";
if (multicastLock.isHeld()) {
Log.i(TAG, "held multicast lock");
}
try {
InetAddress addr = InetAddress.getByName(host);
MulticastSocket socket = new MulticastSocket(port);
socket.setTimeToLive(4);
socket.setReuseAddress(true);
socket.joinGroup(addr);
byte[] buf = new byte[5];
DatagramPacket recv = new DatagramPacket(buf, buf.length, addr, port);
socket.receive(recv);
message = new String(recv.getData());
socket.leaveGroup(addr);
socket.close();
} catch (Exception e) {
message = "ERROR " + e.toString();
}
multicastLock.release();
return message;
}
}
This code results in blocking on line socket.receive(recv); If I specify a timeout, I get a timeout exception.
Check my answer in very similar question Android Network Discovery Service (ish) before API 14
I do not belive that multicast is not working on Galaxy S2, some time ago when I was coding some network application, I made several test on many devices, some older like G1 but also on S2, S3 and Galaxy Tab 10.
But to be able to use multicast you must enable it programatically.
Have you used this piece of code?
WifiManager wifi = (WifiManager)getSystemService( Context.WIFI_SERVICE );
if(wifi != null){
WifiManager.MulticastLock lock = wifi.createMulticastLock("Log_Tag");
lock.acquire();
}
Check out http://developer.android.com/training/connect-devices-wirelessly/index.html It mentions two ways of finding local services- NSD and wifi direct.

Can't connect from Android to bonjour service, hosted on iMac

My goal is to find all bonjour services in WIFI network, find their ip/port, and communicate through HTTP.
Bonjour service, hosted on iMac is discovered incorrectly - service name is found, but port = 0, InetAddress[] = null.
Connection to the same service hosted on Windows PC is working properly (same version of soft from one vendor) - name, url and port discovered correctly.
Bonjour service browser sees both of services correctly.
JmDNS 3.4.0 lib is used, see code example (some code is omitted):
MulticastLock lock = wifi.createMulticastLock(MULTICAST_LOCK_TAG);
lock.setReferenceCounted(true);
lock.acquire();
final InetAddress inetAddress = getLocalIpAddress();
jmdns = JmDNS.create(inetAddress, JMDNS_NAME);
ServiceInfo[] infos = jmdns.list(CAMERA_SERVERS);
if (infos != null && infos.length > 0) {
for (int i = 0; i < infos.length; i++) {
name = infos[i].getName();
InetAddress[] addresses = infos[i].getInetAddresses();
url = addresses[0].getHostAddress();
port = infos[i].getPort();
}
PS. Tried dns_sd.jar from Apple, but it relies on native code and cant be used in Android.
Any ideas?
Thanks.
use below code. Tested and implemented and working fine
android.net.wifi.WifiManager.MulticastLock lock;
android.os.Handler handler = new android.os.Handler();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
handler.postDelayed(new Runnable() {
public void run() {
setUp1();
}
}, 1000);
}
private void setUp1()
{
android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) getSystemService(android.content.Context.WIFI_SERVICE);
lock = wifi.createMulticastLock("mylockthereturn");
lock.setReferenceCounted(true);
lock.acquire();
try {
//http://stackoverflow.com/questions/13677199/jmdns-doesnt-work-properly-on-android-4-1
WifiInfo wifiInfo = wifi.getConnectionInfo();
int ip = wifiInfo.getIpAddress();
String ipAddress = Formatter.formatIpAddress(ip);
InetAddress _bindingAddress = InetAddress.getByName(ipAddress);
jmdns = JmDNS.create(_bindingAddress);
ServiceInfo[] infos = jmdns.list("_afpovertcp._tcp.local.");
for (int i=0; i < infos.length; i++) {
notifyUser("\nServic : "+infos[i].getName()+"");
}
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
}
private void notifyUser(final String msg) {
handler.postDelayed(new Runnable() {
public void run() {
TextView t = (TextView)findViewById(R.id.text);
t.setText(msg+"\n=== "+t.getText());
}
}, 1);
}
For starters try to use the JmDNS.create method overload that takes no parameters. The problem is that there might be several network interfaces (mobile and wifi) and you may bind to the wrong IP using the getLocalIpAddress. Read more about how JmDNS guesses those parameters itself here. The reason it works on the PC because your getLocalIpAddress returns the WiFi ip. Perhaps because it's the only network interface.
Also make sure that the service you want to access is available via the WiFi. It's very common for wireless routers to separate the WiFi network and the ethernet network for obvious security reasons.

Categories

Resources