What do the numbers in Android Studio debugger window mean? - android

What do the highlighted numbers example, 4580, 4581 etc., mean? They are not PIDs, this was crossed checked with the ps command in adb shell.

This number is the Register number of the register where the Object's reference is stored.
What is register number?
Something completely useless from an app developer point of view! I am sure you know about the Dalvik VM on which android applications run. So, the frames in a Dalvik byte code are made up of registers. And these registers store the object references. Check this link to know more. Not sure why android studio shows them in debugger. I don't see any use of it.

In short: The number may not necessarily be the register number, it could be the ID from ObjectReferenceImpl, which is an implementation of ObjectReference interface from Java Debug Interface (JDI).
In length: From analysis of Idea Community code base, ThreadDescriptorImpl.java (ThreadDescriptorImpl), was found to be the class responsible for providing the thread description to be displayed in the debug window (please refer above image presented with the question). The ID is referred as thread.uniqueID(). The thread here is of ThreadReferenceProxyImpl type which extends ObjectReferenceProxyImpl, where the uniqueID method is implemented. This method in turn returns a uniqueID from an object of ObjectReference type. Upon cursory search the ObjectReference definition with satisfying criteria was not found in Idea code base. It was later found to be hidden in the definition of JDI interface. From the JDI implementation jar found in the Idea setup, ObjectReferenceImpl was found to provide the final implementation of uniqueID method. The code snippet is listed below -
private long myID;
private static synchronized long nextID()
{
return nextID++;
}
ObjectReferenceImpl(VirtualMachine aVm, Oop oRef)
{
super(aVm);
this.saObject = oRef;
this.myID = nextID();
}
public long uniqueID()
{
return this.myID;
}
However in saying so and answering the question, words like 'probably' and 'may be' were used because, the references for ObjectReference implementations were not found immediately in the Idea Community edition source code. And, the inferences were from the jar implementations. If direct references were to be provided in the future by someone looking at this question and answer, the answer can be modified to reflect certainty.

Related

Obfuscating or removing string literal from all calls to Log-function in Android

We are building an Android application where we use Timber for Log-output. We have defined our own .e, .d, .v etc functions and use if (BuildConfig.DEBUG) to see if we should output the log. This takes care of the issue that we don't want to output Debug-logs in our releases but all the string literals used in our functions calls are still present in the compiled source code. We furthermore use ProGuard for obfuscation. To exemplify, in a class we can have:
somObj.normalFunction(variable)
Log.d("This secret class achieved its secret mission!");
In our release, this will not be seen in the app logs but if you reverse-engineer the APK you will see something like:
q.b(m)
z.a("This secret class achieved its secret mission!");
which can give a hint to the hackers about what class they are looking at.
So what we're looking for is to either be able to completely REMOVE all the Log function calls at compile time (using some pre-processing, annotation or something, but hopefully without having to add something before EVERY function call) OR to obfuscate all the String literal parameters to those function calls. So, two ideal solutions would be if the source, just before compilation, instead looks like:
q.b(m);
or
q.b(m);
z.a("jgasoisamgp23mmwaföfm,ak,ä")
Just by thinking I can see two bad ways to achieve this. Either we surround ALL calls to Log.d with if(BuildConfig.DEBUG) which will make the compiler remove them before compilation. But this is very tideous. OR, we make sure that every time you want to add a log-printout you need to do
Log.d(LogClass.getLog(1234))
and you then define ALL those logs inside LogClass and then remove them with if(BuildConfig.DEBUG) and return null in getLog if that's the case. But that makes it more tideous every time you want to add a log.
So finally, is there any GOOD solution to this?
DISCLAIMER: I work for PreEmptive, the company that makes PreEmptive Protection - DashO.
DashO is capable of removing calls to specific methods (e.g., Log methods). While this doesn't remove the instructions to load the string literal, just the call itself, DashO also offers String Encryption, which would offer some protection to those string literals.
As an example, I ran this class through DashO:
public class App {
public static void main(String[] args) {
Log.d("Secret message here");
}
}
After removing calls to Log.d with String Encryption on, the decompiled output looks like this:
public class App
{
public static void main(String[] paramArrayOfString)
{
a.replace("Bwpfpb7u|ih}z{?($0&", -12 - -61);
}
}
DashO offers other protections (e.g., Control Flow Obfuscation) that tend to break decompilers; I've turned those off for this demonstration.
What I would do is one or some of the following:
Use Timber (so you don't need to bother removing things or adding if statements). You simply do this once in your Application#onCreate(); if you are in DEBUG, then you plant a DebugTree that prints to the console. Else, you plant an "empty tree" that does nothing.
Simulate Timber but create your own "YourLogger" class and do the same (if you don't want to include a "third-party" library even though it's just one class). So you'd have YourLogger.v("tag", "string") and inside you'd do: if (debug) { Log.v(tag, string); } and so on and so forth for all other log types.
Use Proguard to strip the logging, and what not.
1 and 2 imply you go through your app and replace all Log. lines with either Timber. or YourLogger.
Option 3 wouldn't need that, since the code would be removed during obfuscation and the calls would do nothing, but this is mode complicated (and I haven't done it in years, don't even remember how it's done, probably easy to look it up).
I'd go for 1.
Update
Since apparently I don't know how to read, I think that in order to achieve this, your only bet is to have some sort of lookup mechanism for the actual text you want to emit/hide.
Strings.xml is the easiest, since it's included with Android and you can even localize the error messages (if that were needed, of course). Yes, there's a lookup time penalty, but I'd say unless you're iterating over thousands of items and logging different strings every time or something, the penalty wont' be noticeable (I don't have data for this, you'd have to benchmark).
Alternatively, instead of relying on resources, you could just use a file, read it, and load the strings in memory... a trade off; do you use more memory at the cost of simplicity and time to code the solution, or do you use the built-in mechanism and pay the CPU time?

How to fix android.content.res.Resources$NotFoundException error?

I have tested the application on my device and few emulators. The app doesn't crash and I don't see anything on the LogCat but I can see around 400 crashes within 22 hours in ANRs & crashes.
The error doesn't say which resource is missing to check it and if it's missing why it is not crashing on my phone?
This is the line which causes the crash:
int themeLayout = sharedPreferences.getInt(THEME_KEY, R.layout.input_1);
mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
themeLayout, null);
If shared preference returns null then I assigned a default value to use that one but still, it crash. I checked the layout and it exists, also check the content.
I created the emulator with the same specification but it doesn't crash.
android.content.res.Resources$NotFoundException: at
android.content.res.ResourcesImpl.getValue (ResourcesImpl.java:202)
at android.content.res.Resources.loadXmlResourceParser
(Resources.java:2968) at android.content.res.Resources.getLayout
(Resources.java:1984) at android.view.LayoutInflater.inflate
(LayoutInflater.java:425) at android.view.LayoutInflater.inflate
(LayoutInflater.java:378) at
com.sunzala.afghankeyboard.android.SoftKeyboard.onCreateInputView
(SoftKeyboard.java:163) at
com.sunzala.afghankeyboard.android.SoftKeyboard.onStartInput
(SoftKeyboard.java:242) at
android.inputmethodservice.InputMethodService.doStartInput
(InputMethodService.java:2641) at
android.inputmethodservice.InputMethodService$InputMethodImpl.startInput
(InputMethodService.java:590) at
android.inputmethodservice.IInputMethodWrapper.executeMessage
(IInputMethodWrapper.java:186) at
com.android.internal.os.HandlerCaller$MyHandler.handleMessage
(HandlerCaller.java:37)
Edit:
I found this error:
E/dalvikvm: Could not find class
'android.graphics.drawable.RippleDrawable', referenced from method
android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering
The R values that we refer to in Java code, such as R.layout.input_8, are public static final int values on a code-generated R class. You will find that class in the build/generated/source/r/ directory of your module. The file will be fairly large, but you will see stuff like:
public static final class layout {
public static final int activity_main=0x7f050000;
}
That number (0x7f050000) is generated by the build tools (aapt, specifically, IIRC). And that value can change from build to build. As a result, it is not safe to persist such a number. Otherwise, you wind up with scenarios like this:
User installs your app
User does something in your app that causes you to persist a value (e.g., editor.putInt(THEME_KEY, R.layout.input_8).apply();)
Time passes
You ship an update to your app, where, as it turns out, the number for R.layout.input_8 changes
The user installs the update to your app
Your code calls sharedPreferences.getInt(THEME_KEY, R.layout.input_1); and retrieves a number that used to be a resource ID... but now is just a number, or points to some different resource
Your code crashes
The user gets frustrated and throws their phone against a wall
Note: no actual phones or walls were harmed in the creation of this scenario
This is a problem with your code. I do not know if it is the problem that is triggering your crashes, but it could be.
The problem is that you are persisting a value (0x7f050000) that you do not control. You think that R.layout.input_8 will always be 0x7f050000, but that is not the case.
What you need to do is store something else in the preference, then use that to look up the proper ID. There are two main approaches for this.
One is to use a simple index. Your naming scheme suggests that you have a series of numbered layouts, at least through 8. So, you could save a number between 1 and 8 in the SharedPreferences, then use that as an index into an array:
static final int[] THE_LAYOUTS={R.layout.input_1, R.layout.input_2, R.layout.input_3, R.layout.input_4, R.layout.input_5, R.layout.input_6, R.layout.input_7, R.layout.input_8};
In this solution, editor.putInt(THEME_KEY, R.layout.input_8).apply(); turns into editor.putInt(THEME_KEY, 8).apply();, and sharedPreferences.getInt(THEME_KEY, R.layout.input_1); turns into THE_LAYOUTS[sharedPreferences.getInt(THEME_KEY, 1)];.
The other is to save the string "R.layout.input_8". Given that, and getIdentifier() on a Resources object, you can get back the int value associated with that string for your current build. Personally, I find this to be more awkward and slower, but it's an option.

Why checkStartAndEnd is not found in Android java.util.Arrays?

I look at Android source code
https://android.googlesource.com/platform/libcore/+/cff1616/luni/src/main/java/java/util/Arrays.java#1742
I realize Android's Arrays contains a public static method named checkStartAndEnd, which is not found in Java standard SE.
However, when I type java.util.Arrays.checkStartAndEnd in Android Studio, or look at the documentation https://developer.android.com/reference/java/util/Arrays.html, I realize checkStartAndEnd isn't valid for Android's Arrays class.
May I know why is it so? Am I looking at wrong Android source code?
You cannot see / use it because it's hidden (check the #hide tag in the Javadoc). If you compare the Android Arrays class with the Java SE one, you'll see that this checkStartAndEnd basically equals to rangeCheck, which is a private method there as well. As to why did they rename it? I have no idea, maybe some licensing issue or something else.

How to get programmatically the data usage limit set by user on Android OS configuration?

User can define at Data Usage screen a limite and/or a warning limit for mobile data usage. So how can I get this information by code?
Screen of Data Usage configuration of native OS.
I wanna the limit value and warning value.
I've already tried this but not work and always return NULL to both:
final Long recommendedBytes = DownloadManager.getRecommendedMaxBytesOverMobile( this.context );
final Long maximumBytes = DownloadManager.getMaxBytesOverMobile( this.context );
// recommendedBytes and maximumBytes are NULL
And TrafficStats class just have a data transferred not the limits.
After days searching and research about this problem I couldn't find a answer for that. Bellow I will lift every attempt that I did.
1. Download Manager
With this class you can start download over any network or device
state and it will handle all states e.g. network loss, device reboot,
etc...
There are two methods called getMaxBytesOverMobile and
getRecommendedMaxBytesOverMobile, they was a pretty candidate
to solve this problem at first time. But after code tests and
Download Manager implementantion research I'd found that there is
no way to get thoose values by DownloadManager.
Reason
Thoose methods call Settings.Secure.getLong with they
respective labels
Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE and
Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE in
the turn makes a call to a lazy String map inside inside a
inner class called NameValueCache.
Ok so far but none of inner classes or Settings implementation it
self use DOWNLOAD_MAX_BYTES_OVER_MOBILE or
DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE inside.
I considered the lazy map was populate by a third entity, what
actually happens, so I found the NameValueTable Settings
inner class that handle the new values to lazy map. The
putString is a protected method call by Settings.Secure
and Settings.System inner classes (calls of Secure and
System).
So I could conclude that if the OS implementantion do not put thoose String values I can't get them.
2. TrafficStats
Just a quick look on official reference I could notice that it will
not help me because this class just provide the amount of bytes and
packages that was trafficked since last device boot.
http://developer.android.com/reference/android/net/TrafficStats.html
3. NetworkPolicyManager and NetworkPolicy
As #bina posted here the both classes are hidden and could not
be use by normal apps e.g. that will be published in Google Play.
https://stackoverflow.com/a/24445424/575643
4. ConnectivityManager
In short, you just can get the NetworkInfo that not provide
much information about user preferences (really none!). Just provide
informations about network and e.g. mobile network provider.
http://developer.android.com/reference/android/net/ConnectivityManager.html
After all I assume that no way to get this information nowadays. Please if you read it and found a way post here!
Thanks for all.
PS.: Sorry by english mistakes.
Do you want to get limit value(5GB) and warnning value(2GB) in this example?
If so, you can get limitBytes and warningBytes by the following code, if you can use android.permission.MANAGE_NETWORK_POLICY and android.permission.READ_PHONE_STATE.
However, android.permission.MANAGE_NETWORK_POLICY protectionLevel is signature.
NetworkPolicyManager manager = (NetworkPolicyManager) getSystemService("netpolicy");
NetworkPolicy[] networkPolicies = manager.getNetworkPolicies();
Log.d("NetworkPolicy", "limitBytes is " + networkPolicies[0].limitBytes);
Log.d("NetworkPolicy", "warningBytes is " + networkPolicies[0].warningBytes);
(NetworkPolicyManager and NetworkPolicy classes are hidden)

Android Spinner - System view VS User view

I have been creating Spinner controls (Combo boxes/Drop downs) in one of my apps, and was surprised to find out how difficult it was to achieve all of the following features:
User facing Strings are externalized, taking advantage of strings.xml internationalisation (I18N) feature of Android.
Spinner selections operate using a System view, which facilitates not having to work with or map Strings to meaningful values (yuck).
User view to System view mapping should be easy, automated and minimal (i.e not hand rolled for every component).
Others have attempted solutions to this, but universally as far as I could see they suffer from one or many of the following problems:
UI code is creeping into their enum class which doesn’t belong there (messy), nearly all existing solutions suffered from this.
Hardcoded User facing Strings in their enum classes. Because these are not externalized you cannot do I18N using the stock Android features.
Authors typically make the Fragment or Activity an OnItemSelectedListener which perpetuates a common problem of inheritance for convenience, where composition is more appropriate.
I have developed my own solution which does this: http://www.androidanalyse.com/android-spinner-externalize-user-strings-mapped-to-system-enum/
My question is, have I missed something? This seems like something that should not have been this hard (which makes me feel like I'm possibly reinventing the wheel).
Below is some example code showing my solution in-use (which is available Apache 2 license from the link above).
String none = getString(R.string.none);
String light = getString(R.string.light);
String medium = getString(R.string.medium);
String strong = getString(R.string.strong);
SpinnerUtil.createNewSpinner(view, R.id.wind, Arrays.asList(none, light, medium, strong), WindLevel.values(),
new SpinnerItemSelectedListener<WindLevel>() {
public void onItemSelected(Spinner item, WindLevel value) {
// Take whatever action you wish to here.
}});
I would just use ArrayAdapter<WindLevel>. Yes, you created a custom typed listener, but the regular event listener gets the position and can call getItem() on the ArrayAdapter<WindLevel> to get a WindLevel properly typed.
IMHO, the vast majority of Spinner widgets will be populated with material read in from a database, the Internet, or some other dynamic data source, rather than populated by some sort of enum with display values coming from static strings that can be internationalized ahead of time.
This is not to say that your code is useless: if you find it useful, then it was worth writing. And I am sure that there are apps out there that contain your targeted pattern (i.e., a Spinner backed by an enum or equivalent where the display values are known in advance and can be internationalized) who might find your solution useful as well. Every developer who writes enough code cooks up these sorts of helper classes and the like that help map an OS or framework model into something that better fits the developer's own mental model. So long as you are not perceiving any performance issues, it's all good.
Also, note that OnItemSelectedListener is an interface; implementing that interface on an existing class is not inheritance.
I believe the reason nobody answered you is :
What problem are you trying to solve ? Spinners existed prior to your well designed attempt.
Why reinvent them in exactly the same way they exist in Android ?
http://developer.android.com/guide/topics/ui/controls/spinner.html
It is a beautiful wheel indeed you designed, but still, it is just a wheel :)
UPDATE :
I think I begin to understand what you did. This is interesting. I'm not sure why you did not go to the pattern implemented by the ListPreference with its entries and entryvalues.
In fact, I'm not sure I understand why the Android team did not go that route either.
In any case, it is worth proposing your idea to the Android framework. It is after all open source.

Categories

Resources