Non intrusive logs in Android - android

Is there a way to have non intrusive logs in Android ?, for example, if I have a method like the following one:
public void aMedthod() {
doSmt();
if (mSomeState) {
if (doSmtElse()) {
Log.v("MyApp","Success")
}
}
}
What I'd like to do is replacing that Log line with something as less intrusive as possible, in order to package the app for production without any trace of the Log library and at the same time, not having to delete nor comment any piece of code.

Jake Wharton made an awesome library that can accomplish exactly that. Take a look here.
just use this to init:
if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
}

Related

Is it required/recommended to remove Trace.beginSection endSection API from release variant?

I just found that using Trace.beginSection can help troubleshoot performance issues while using systrace tool.
The documentation states "This tracing mechanism is independent of the method tracing mechanism offered by Debug#startMethodTracing"
But just like debug logs, do we need to comment/remove Trace API before releasing the app. Or is it allowed/benign to leave Trace API invocations in release code?
Preparing for release checklist does not mention anything about trace API.
But I am doubtful because there are other methods like Trace.setCounter which can be used to log debug info.
Typically I remove the traces when I'm done with them but Google leaves it in for some of the most basic building blocks like RecyclerView so it's probably fine.
Here's an example from the RecyclerView source:
// androidx.recyclerview.widget.RecyclerView
void consumePendingUpdateOperations() {
if (!mFirstLayoutComplete || mDataSetHasChangedAfterLayout) {
TraceCompat.beginSection(TRACE_ON_DATA_SET_CHANGE_LAYOUT_TAG);
dispatchLayout();
TraceCompat.endSection();
return;
}
if (!mAdapterHelper.hasPendingUpdates()) {
return;
}
// if it is only an item change (no add-remove-notifyDataSetChanged) we can check if any
// of the visible items is affected and if not, just ignore the change.
if (mAdapterHelper.hasAnyUpdateTypes(AdapterHelper.UpdateOp.UPDATE) && !mAdapterHelper
.hasAnyUpdateTypes(AdapterHelper.UpdateOp.ADD | AdapterHelper.UpdateOp.REMOVE
| AdapterHelper.UpdateOp.MOVE)) {
TraceCompat.beginSection(TRACE_HANDLE_ADAPTER_UPDATES_TAG);
startInterceptRequestLayout();
onEnterLayoutOrScroll();
mAdapterHelper.preProcess();
if (!mLayoutWasDefered) {
if (hasUpdatedView()) {
dispatchLayout();
} else {
// no need to layout, clean state
mAdapterHelper.consumePostponedUpdates();
}
}
stopInterceptRequestLayout(true);
onExitLayoutOrScroll();
TraceCompat.endSection();
} else if (mAdapterHelper.hasPendingUpdates()) {
TraceCompat.beginSection(TRACE_ON_DATA_SET_CHANGE_LAYOUT_TAG);
dispatchLayout();
TraceCompat.endSection();
}
}
It's okay to leave them in but do not leave any confidential information because it will be exposed to anyone profiling the app.

Actual behavior of DevicePolicyManager.setApplicationHidden

Is there anyone knows SDK well enough to tell why after making my app device-owner and executing DevicePolicyManager.setApplicationHidden for a list of apps I can't then find them unless I'd put PackageManager.getInstalledApplications(PackageManager.GET_META_DATA or PackageManager.MATCH_UNINSTALLED_PACKAGES) in the query flags? (meaning just GET_META_DATA won't work and hidden applications would not be unhidden)
I try to find them to unhide them — but no success unless I am looking for uninstalled also.
My theory is that Android doesn't really hide them, but actually marking them uninstalled yet keeping all the data — but I didn't find any information regards it in the documentation. Wonder if someone can clarify this behavior (with source).
Thanks!
The naming is ambiguous but indeed setApplicationHidden effectively uninstalls the app but keeps the APK and data in storage. If you're looking for a way to prevent use of the app without uninstalling it you can try setPackagesSuspended.
You can find the source for setApplicationHidden in PackageManagerService.setApplicationHiddenSettingAsUser() (relevant abstract below). Its logic is simple:
setApplicationHiddenSettingAsUser calls packageSetting.setHidden() to mark the package as hidden for the user,
other methods of PackageManagerService call packageSetting.getHidden() to decide whether the package should be returned.
Code abstract for setApplicationHiddenSettingAsUser:
#Override
public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
int userId) {
PackageSetting pkgSetting;
...
try {
...
synchronized (mPackages) {
pkgSetting = mSettings.mPackages.get(packageName);
...
if (pkgSetting.getHidden(userId) != hidden) {
pkgSetting.setHidden(hidden, userId);
mSettings.writePackageRestrictionsLPr(userId);
...
}
}
...
}
}

Design application using more confuse code?

Recently I had opened some real apps by using this
So I'm getting the source code from that. In those source code, I found that most of the code is designed like this
public class LockActivity extends Activity {
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
if (GlobalDataHolder.m9617e()) {
bm.m8771b(getApplicationContext(), getPackageManager());
finish();
}
}
protected void onResume() {
super.onResume();
if (GlobalDataHolder.m9617e()||this.f4719a.m9124j()) {
bm.m8771b(getApplicationContext(), getPackageManager());
finish();
return;
}
startActivity(new Intent(getApplicationContext(), LaunchActivity.class));
}
public void onPause() {
super.onPause();
}
public void onDestroy() {
super.onDestroy();
}
}
And also the java file named by Garbled text such as
aa.java
bh.java
cj.java
My question is
1) Why those developer create the function named 'm8771b','m9617e'
2) Why most of apps is designed like that?
3) Is this more secure for avoid other to copy their code?
4) Should we also design the application like that?
5) How they can remember where they put the function?
People don't write code like that... unless they are either a savant or inexperienced. Using seemingly random strings of methods/class names is something called Obfuscation, which means to hide the real meaning of something in order to make it difficult to read.
Obfuscation Wiki as it pertains to software development
There are programs out there, like ProGuard which do this for us. Its purpose is to both compact and obscure code. That way it is difficult for someone to decompile and reconstruct the project without pouring over what it does (depending on complexity) endlessly.
Since Java always compiles into bytecode, it is predictable in the way in which it can be decompiled and much more standard that a write-once compile-anywhere language. ProGuard helps protect intellectual property or proprietary software and keep people from just stealing code.

Android app publishing checklist

The android app publishing checklist says that I need to delete all Log statements from my code. Does that mean I need to delete them or would just commenting them out do? I would need those Log statements for updation and maintenance purpose later on so i don't want to delete them.Publishing checklist
You don't have to remove your logs from code, just disable them in RELEASE mode. The easiest way to achieve that, check mode before log something
if (BuildConfig.DEBUG) {
Log.i("TAG", "Log");
}
But it will be painful if you have a lot of logs in your code, so good idea is to write your custom wrapper above the Android Log class, with ability to turn on/off logging in one place, for example in Application class.
Or you can use some smart loggers like Timber
EDIT
About log wrapper, to be honest I've never created such wrapper, I prefer to use Timber, but the simplest version may look like this
public class Logger {
public static void e(String tag, String body) {
if (BuildConfig.DEBUG) {
Log.e(tag, body);
}
}
public static void v(String tag, String body) {
if (BuildConfig.DEBUG) {
Log.v(tag, body);
}
}
...
}
and instead of using
Log.e("Tag", "Body");
use
Logger.e("Tag", "Body");
The publishing check list just don't want you to include log statements when your app is published because it may contain some sensitive information and that sort of stuff. So you just need to make sure that it is not executed.
As long as the log statement is not executed, it's fine.
You can do the following:
Delete the statement
comment the statement
add an impossible if statement:
if (0 != 0) {
//log
}
P.S. The second solution the the most recommended.

Is DexGuard tamper and Environment detection helpful?

I am very new to DexGuard and Proguard. I was going through their documentation and sample examples. They have dexguard_util which helps you detect if the application is tampered with and also helps in detecting if it is running in the environment it is supposed to run. The document suggests that this tamper and environment detection be encrypted using the following code is dexgaurd-project.txt.
-encryptclasses A$D
-encryptstrings A$D
follwing is the activity
public class A extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
new D().c();
}
private class D
{
public void c()
{
//some code to which detects the tampering and environment and takes action accordingly
}
}
}
What if a hacker inject this line of code.
public class A extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//code commented by hacker
//new D().c();
}
private class D
{
public void c()
{
//some code to which detects the tampering and environment and takes action accordingly
}
}
}
Then my application will run without running those tests which I think is a big problem. Is my understanding of how reverse engineering works wrong or there are better ways of doing this. Please share better methods of doing this if they exist. Thanks in advance. Note that public class A cannot be encrypted as it is an entry point and is kept using this command in progaurd-project.txt
-keep class somepackage.A
When it comes to anti-tampering, it is important to keep in mind that their goal is not to stop any and all potential tampering efforts, but, rather, it's just a matter of raising the security bar of the target high enough to dissuade most attackers.
With that said, the
A bit of a tangent:
The document suggests that this tamper and environment detection be encrypted using the following code is dexgaurd-project.txt.
Class encryption does prevent basic static analysis of the application package, e.g. simply unzipping the package and loading it in jd-gui. However, as this answer shows, it's trivial to circumvent: one only has to hook into the static method that decrypts the apk on load, and dump it. But this allows the security bar to be raised.
Now back to your original question:
What if a hacker inject this line of code.
As an attacker, that would be the next step. However, that would require repackaging the app, and signing it with the hacker's signing key. Therefore, it is necessary to combine Dexguard's anti-tampering measures like checking the apk signature.
Is DexGuard tamper and Environment detection helpful?
In summary, yes, it is helpful in as far as it raises the bar above the vast majority of apps out there. But it's no silver bullet.

Categories

Resources