how reliable is android Build.SERIAL - android

I have an app that checks the value returned by Build.SERIAL, and then uses that as a sort of validation when transferring data between the app and the website. Everything is working fine except for occasionally a user is unable to connect. In the docs it says Build.SERIAL returns the serial id if available, My question is does this mean that some devices will have it and some won't, or does it mean that a device may be able to retrieve it at some times, and others it won't?
I was assuming its the first, but I'm have users that are having an issue with it and I cannot repeat it. And when I tried searching for more information on what exactly "If available" meant I couldn't really find anything.
EDIT Just for more clarification, I have a user that has a serial id and can use the software just fine. The problem is occasionally he gets an error saying the serial id is not registered, I have not been able to recreate the problem so I am only guessing that the device sometimes does not grab the serial id. I was wondering if anyone could confirm that this is, or is not, an issue. I have already put some things in place to catch the error if it happens again, but it seems to be randomly happening.
EDIT 2 So i found out that the Build.serial is still returning the serial id so that is not the problem, ill eventually figure it out, but for now I'll just leave this question up until someone can explain when it is or isn't available in case it helps someone in the future.

Build.SERIAL can be empty or sometimes return a different value (proof 1, proof 2) than what you can see in your device's settings.
There are several ways to get that number depending on the device's manufacturer and Android version, so I decided to compile every possible solution I could found in a single gist. Here's a simplified version of it :
public static String getSerialNumber() {
String serialNumber;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serialNumber = (String) get.invoke(c, "gsm.sn1");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "ril.serialnumber");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "ro.serialno");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "sys.serialnumber");
if (serialNumber.equals(""))
serialNumber = Build.SERIAL;
// If none of the methods above worked
if (serialNumber.equals(""))
serialNumber = null;
} catch (Exception e) {
e.printStackTrace();
serialNumber = null;
}
return serialNumber;
}
I try to update the gist regularly whenever I can test on a new device or Android version. Contributions are welcome too.

Related

Check if RS232 response contains malformed chars

I have android platform on one end and arduino on the other, connected via serial. Everything works fine, however in some cases arduino restarts itself and causes a flow of unknown characters while its restarting to the serial.
Here is a serial log while arduino is rebooting:
�z������"&O�Z&���B
���F ���cd�:{����t�>��+������2�~����. ���r���DD���^��.�.B�.��ڮ2t��Z:��,R��A�ڢr��Ckˡ���.-���N^���b�����^���
Question is, how can I check on android end if the response was malformed?
You should probably add some kind of "framing" to your messages. CR/LF isn't enough.
For example, put a special "preamble" at the front, and watch for it on the Android side. Choose something that will not occur in the body ("payload") of the message. And choose something that is very unlikely to occur in the random chars that show up on a reboot, a couple of chars long.
You could also put a CRC at the end. "Fletcher" is easy.
I ended up using simple solution like this:
private String filterData(String receivedStr) {
if (receivedStr.contains(RECV_HEADER) && receivedStr.contains(mReadRules.RECV_END)) {
int header_pos = receivedStr.indexOf(RECV_HEADER);
int crc_pos = receivedStr.indexOf(RECV_END);
return receivedStr.substring(header_pos, crc_pos);
} else {
return null;
}
}
It also extracts message if its wrapped around with malformed data.

getUidRxBytes() and getUidTxBytes() always return 0 in Android 4.3

I feel like I am on crazy pills right now. A specific part of my application has been working just fine for several days, and today it just stopped working and I can not figure out why. This part of my code used to output the total data since boot that each specific app has sent and received. Now, the values always show up as 0.
A couple things that may or may not be affecting this:
1.) My Nexus 4 was just updated to Android 4.3 today, but I doubt this is an issue because this worked just fine right after I updated.
2.) With the Android API 18 update, some methods from the Traffic Stats API are now deprecated, but these are methods I am not even using, so this should have no effect.
http://developer.android.com/reference/android/net/TrafficStats.html
All help is greatly appreciated.
PackageManager packageManager=this.getPackageManager();
List<ApplicationInfo> appList=packageManager.getInstalledApplications(0);
for (ApplicationInfo appInfo : appList) {
String appLabel = (String) packageManager.getApplicationLabel(appInfo);
int uid = appInfo.uid;
Log.d("data", String.valueOf(TrafficStats.getUidRxBytes(uid) + TrafficStats.getUidTxBytes(uid)));
Update[January 23, 2014]: Testing the getUidRxBytes() and getUidTxBytes() on my Nexus 4 running Android 4.4.2 shows that the values are no longer 0, but are reporting the correct statistics.
I have reported the issue to the AOSP issue tracker: here
I have also created an alternate solution to the problem which I have pasted below:
private Long getTotalBytesManual(int localUid){
File dir = new File("/proc/uid_stat/");
String[] children = dir.list();
if(!Arrays.asList(children).contains(String.valueOf(localUid))){
return 0L;
}
File uidFileDir = new File("/proc/uid_stat/"+String.valueOf(localUid));
File uidActualFileReceived = new File(uidFileDir,"tcp_rcv");
File uidActualFileSent = new File(uidFileDir,"tcp_snd");
String textReceived = "0";
String textSent = "0";
try {
BufferedReader brReceived = new BufferedReader(new FileReader(uidActualFileReceived));
BufferedReader brSent = new BufferedReader(new FileReader(uidActualFileSent));
String receivedLine;
String sentLine;
if ((receivedLine = brReceived.readLine()) != null) {
textReceived = receivedLine;
}
if ((sentLine = brSent.readLine()) != null) {
textSent = sentLine;
}
}
catch (IOException e) {
}
return Long.valueOf(textReceived).longValue() + Long.valueOf(textReceived).longValue();
}
The TrafficStats class get the information about network traffic from the /proc/uid_stat/<uid> directory. This contains information about the tcp, udp bytes and packets sent and received. If the files are not present the TrafficStats class can't get the network stats. You can check if the files are present, If not you are out of luck and should look for other way.
If the files are present you can try to read it yourself.
Also the getUidTxBytes() and getUIDRxBytes() report only the TCP traffic and miss UDP traffic. So if your app is doing lots of UDP traffic (like voip) then you'll not get any info.
There is already a bug filed for this : https://code.google.com/p/android/issues/detail?id=32410
I have done some detailed research about this, and to clarify some details, since Android 4.3 the TrafficStats API has changed in the way it extracts details from the device.
Prior to Android 4.3 the UID traffic stats were available for TCP and UDP and included API for bytes and packets & sent and received. That data was extracted from the /proc/uid_stat/[pid]/* files.
In Android 4.3, the developers has decided to switch to a better and more safe API, using the xt_qtaguid UID statistics, which is part of the netfilter kernel module in Linux.
This API (procfs) allows access based on process UID, and this is why when you try to access to TrafficStats API in Android=>4.3 you will get zero information for not-own UID.
btw, the commit that caused the issue is the following:
https://github.com/android/platform_frameworks_base/commit/92be93a94edafb5906e8bc48e6fee9dd07f5049e
*Improve TrafficStats UID APIs.
Deprecate transport layer statistics, leaving only the summarized
network layer statistics.
Improve documentation to be clear about layers where measurements
occur, and their behavior since boot. Under the hood, move to using
xt_qtaguid UID statistics.
Bug: 6818637, 7013662
Change-Id: I9f26992e5fcdebd88c671e5765bd91229e7b0016*

How to detect unknown phone number in call logs (android provider)

I would like to detect the unknown phone number in my call logs list.
An unknown number on the phone is either -1 or -2.
My question is how to detect this type of call?.
I try to detect with :
number = Integer.parseInt(number);
if(number < 0){
}
but it is not working.
Try the following:
1) Log everything.
Put
Log.debug("ClassName", "number = " +number);
2) number = Integer.parseInt(number);
does not look quite right.
try
assuming incomingPhoneNumber is defined as a String.
String incomingPhoneNumber;
try{
int phoneNumber = Integer.parseInt(incomingPhoneNumber);
}catch (Exception e) {
Log.debug("ClassName", "error = "+e.getMessage());
}
in eclipse you need to goto window -->Show View --> Logcat to and examine the log message but you should also just set breakpoints and run in debug mode. Step one line at a time.
Tell us if you get a negative number for the incoming call.
3) Place breakpoints at the very beginning and run in debug mode. Tell us what you get.
4) Communicate with the user questions. People are trying to help but you need to answer our questions for us to help you. For example we do need to see the definition for number to know if
the code is going to work.

How to prevent name caching and detect bluetooth name changes on discovery

I'm writing an Android app which receives information from a Bluetooth device. Our client has suggested that the Bluetooth device (which they produce) will change its name depending on certain conditions - for the simplest example its name will sometimes be "xxx-ON" and sometimes "xxx-OFF". My app is just supposed to seek this BT transmitter (I use BluetoothAdapter.startDiscovery() ) and do different things depending on the name it finds. I am NOT pairing with the Bluetooth device (though I suppose it might be possible, the app is supposed to eventually work with multiple Android devices and multiple BT transmitters so I'm not sure it would be a good idea).
My code works fine to detect BT devices and find their names. Also, if the device goes off, I can detect the next time I seek, that it is not there. But it seems that if it is there and it changes name, I pick up the old name - presumably it is cached somewhere. Even if the bluetooth device goes off, and we notice that, the next time I detect it, I still see the old name.
I found this issue in Google Code: here but it was unclear to me even how to use the workaround given ("try to connect"). Has anyone done this and had any luck? Can you share code?
Is there a simple way to just delete the cached names and search again so I always find the newest names? Even a non-simple way would be good (I am writing for a rooted device).
Thanks
I would suggest 'fetchUuidsWithSdp()'. It's significance is that, unlike the similar getUuids() method, fetchUuidsWithSdp causes the device to update cached information about the remote device. And I believe this includes the remote name as well as the SPD.
Note that both the methods I mentioned are hidden prior to 4.0.3, so your code would look l ike this:
public static void startServiceDiscovery( BluetoothDevice device ) {
// Need to use reflection prior to API 15
Class cl = null;
try {
cl = Class.forName("android.bluetooth.BluetoothDevice");
} catch( ClassNotFoundException exc ) {
Log.e(CTAG, "android.bluetooth.BluetoothDevice not found." );
}
if (null != cl) {
Class[] param = {};
Method method = null;
try {
method = cl.getMethod("fetchUuidsWithSdp", param);
} catch( NoSuchMethodException exc ) {
Log.e(CTAG, "fetchUuidsWithSdp not found." );
}
if (null != method) {
Object[] args = {};
try {
method.invoke(device, args);
} catch (Exception exc) {
Log.e(CTAG, "Failed to invoke fetchUuidsWithSdp method." );
}
}
}
}
You'll then need to listen for the BluetoothDevice.ACTION_NAME_CHANGED intent, and extract BluetoothDevice.EXTRA_NAME from it.
Let me know if that helps.

Getting next alarm information when there is no such function

I have this code in my app
Alarm1 = Settings.System.getString(getContentResolver(),
Settings.System.NEXT_ALARM_FORMATTED);
Its working on htcs,motorolas,but not on galaxy s phones.The application crashes.
Would the following catch the error without crashing the application service?
String Alarm1=null;
try{
Alarm1 = Settings.System.getString(getContentResolver(),
Settings.System.NEXT_ALARM_FORMATTED);
}
catch (Exception e) {
Log.i("Exception", "Exception next alarm not found = " + e);
}
if (TextUtils.isEmpty(Alarm1)) {
//if i am i here either no alarm is set or couldn't read it from the phone
//do something else
}
Unless there is a different code for the galaxy s, and can i find it.How can i make it throw an exception on a phone that works, for testing purposes?Thanks.
I have the same problem on a widget i developed, it seems that on Galaxy S there is no entry on settings.db with ID NEXT_ALARM_FORMATTED, this makes the app crash. Sadly using try/catch it's not enough to solve the issue, widget still crashes.
I don't have a Galaxy S to debug the issue, if you find any workaround (other than inserting using sqlite3 the row con settings.db) let me know. Maybe you can try to simulate this behaviour by passing an invalid ID to the Settings function, i will try later today...
P.S. To temporary fix this on galaxy s you can (via adb shell)
sqlite3 /data/data/com.android.providers.settings/databases/settings.db
UPDATE "system" SET value='' WHERE name='next_alarm_formatted';
Settings.System.NEXT_ALARM_FORMATTED is deprecated since API 21. Use the following instead:
AlarmManager.AlarmClockInfo alarmInfo = am.getNextAlarmClock();
where am is an instance of AlarmManager.

Categories

Resources