Is reflection useful for Android? - android

I learnt a bit about reflection after reading about it in some tpics here. From what I understands, it is used to check the avaibility of a certain class/method/field at runtime. But is it really useful in Android ? Android provide us with the api version at runtime and we can know if a particular class/method or field is available by reading the Android doc (or with error message with Android Studio).
I understand how it can be useful with Java in general, but is there any meaning to use it in Android?

Reflection (in every languages) is very powerful.
In Android most of time reflection is not needed, because you can find Security Exceptions, problems. It depends on what You do.
If you use undocumented classes, libs, you can use it, and it's very useful.
Sometimes, to do particular things, like turn on/off 3g on old device, change device language, you need rooted device to use reflection.
Finally, depends always on what You do.

Sometimes it works , and some times it does't work .
E.T work example :
You can reflect the method to hang off a phone call (there are a lot example codes on Internet so I won't copy the code.).
Doesn't work example:
If you want to switch data connect status , use reflection works on 4.4 but will not work on 5.0 because it's a binder connection, the BN will check Permission the app granted , but this permission only granted to system app . So if your app is a third part app,on 5.0 you can't use reflection to switch data connect status.
Hope that helps

This is a very general question, it really depends on what you're trying to do. Sometimes you have to use reflection, if the APIs are hidden, all depends on your use case, generally you should avoid reflection as it complicates your code more than its needs to be and its potentially unsafe for further versions of android.

In my opinion it's a good to way to do particular things.
For example you can use the methods of PowerProfile class to do a simple power model for your phone.
By the method getAveragePower(POWER_WIFI_SCAN) you can take the average current in mA consumed by the subsystem (in this case: wi-fi during scan).
So to use PowerProfile's methods for get your battery capacity you you could use java reflection in this way:
private Object mPowerProfile_;
private static final String POWER_PROFILE_CLASS = "com.android.internal.os.PowerProfile";
private Double batteryCapacity = Double.valueOf(1);
public Double getBatteryCapacity(Context ctx) {
try {
mPowerProfile_ = Class.forName(POWER_PROFILE_CLASS).getConstructor(Context.class).newInstance(this);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
batteryCapacity = (Double) Class.forName(POWER_PROFILE_CLASS).getMethod("getAveragePower", String.class).invoke(mPowerProfile_, "battery.capacity");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

Related

Android - where can I see the request url that is generated when setDataSource(..) is called?

I am trying to add headers to my setDataSource() method. Is there any way I could see the request itself that is sent ? I need to do this because I'd like to confirm if the url generated by setDataSource method is correctly formed. I don't however see any apis in the MediaPlayer class that can help me do this. Any direction or a solution would be most appreciated.
For non-file media source, the framework handle it by MediaHTTPConnection which is a hide API. You can change its field VERBOSE to true to see the printed log.
Since it's not exported, we can't use it directly. The following code might helpful, but I am not sure if it works. Run it before setDataSource().
try {
Class mediaServiceClass = Class.forName("android.media.MediaHTTPConnection");
Field field = mediaServiceClass.getDeclaredField("VERBOSE");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.setBoolean(null, true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
You can refer here to see the detail implementation of MediaHTTPConnection.

Out of memory - Android

I'm using ffmpeg in my Android application and sometimes I'm getting out of memory error, I'm calling the ffmpeg inside a HandlerThread, is it ok to catch out of memory error and exit the thread while the main thread keeps on running?
I read a lot of this being not a good practice, the thing is that I really need that because I have to edit the DB when there is any kind of error
fc = new FfmpegController(context, fileTmp);
try {
fc.processVideo(clip_in, clip_out, false,
new ShellUtils.ShellCallback() {
#Override
public void shellOut(String shellLine) {
}
#Override
public void processComplete(int exitValue) {
//Update the DB
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
} catch (InterruptedException e) {
} catch (Exception e) {
}catch (OutOfMemoryError e) {
//update the DB
}
No something is going wrong if you are getting OutOfMemory errors. I would look into buffering your audio, as likely you are running the whole clip through ffmpeg at once, which is going to use up alot of memory.
Also, keep in mind that lots of us doing Audio in Android end up using the NDK primarily because of issues like you are experiencing. Audio has to be really high performance, and using the NDK allows you to write more low level memory efficient audio handling.
Android's AudioTrack has a write method that allows you to push an Audio buffer to it. A warning that this is not entry level and requires some knowledge of AudioBuffer's as well as requires you to read buffers in, send them to ffmpeg and then pass to AudioTrack. Not easy to do, and unfortunately more advanced audio on Android is not easy.

How to store private key in android without pin code

I'm new to android and security.
My app uses an encrypted DB which is encrypted by a private key. I want to find a way to store this private key in a protected place, without adding any additional password/pin code.
From what I've read, Android's keystore is the place to do it, but from my understanding, if I'll use it, it demands that I'll set a pin code for the device (which I don't want to do!).
Any suggestions regarding where to store this key and how? (any keystore related solution is acceptable as long as I don't have to set a pin code)
My direction is using some external open source keystore (any suggestions?) which I'll compile as part of my app (and because android doesn't share information between apps it will be ok to use).
I'm aware that my last assumption isn't correct when using a rooted device, but for my case I use only non-rooted devices.
I've searched a lot (here and else where) and couldn't find what I was looking for...
Any help is highly appreciated!!
10x
One thing you need to keep in mind is that the KeyChain isn't available until API 14. If you intend on targeting earlier API versions you need another option. You could use SpongyCastle to create your own KeyStore.
If you are not going to ask the user for a password you should at the very least obscure the password.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
KeyStore ks = null;
try {
ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null,null);
// Add certs or keys
ks.store(new FileOutputStream(new File(getFilesDir(),"out.bks")),"password".toCharArray());
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
static {
Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}
}

setPin() shows error in eclipse that "setPin() is undefined for BluetoothDevice"

I don't find many BluetoothDevice methodes such as , setPasskey(), setPin(), setPairingConfirmation(), setRemoteOutOfBandData().
I searched on Android site as well but I don't find it. When I use these methods in my program in eclipse it shows me an error: its undefined for the type BluetoothDevice.
Are these obsolete now? If yes then what are the new methods of same type.
It is assumed that paring process is performed only by applications delivered with a platform!
This means that this application have access to hidden API. For example you can find hidden API for Bluetooth here.
It is strongly recommended to not use hidden API since it can change without warning in next Android release.
If you are still planning to use this API safest way is to use reflection:
try {
Class<? extends BluetoothDevice> c = device.getClass(); // BluetoothDevice.class
Method createBond = c.getMethod("createBond");
Object result = createBond.invoke(device);
Boolean castedResult = (Boolean)result;
Log.d(TAG, "Result: " + castedResult.toString());
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
There is also alternative way to easy use hidden API, but I didn't try it.

Check if method exists

I want to check if the method Camera.Parameters.getHorizontalViewAngle() exists on the device (it's only available from API 8 and my min SDK API is 7). I tried to use "reflection", as explained here, but it catches an error saying the number of arguments is wrong:
java.lang.IllegalArgumentException: wrong number of arguments
Anybody could help?
Camera camera;
camera = Camera.open();
Parameters params = camera.getParameters();
Method m = Camera.Parameters.class.getMethod("getHorizontalViewAngle", new Class[] {} );
float hVA = 0;
try {
m.invoke(params, hVA);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.invoke(params, hVA);
should be
m.invoke(params, null);
Camera.Parameters.getHorizontalViewAngle() doesn't take any arguments and the above line has the argument hVA. If you're looking for the return variable do hVA = m.invoke(params, null);
Personally, I recommend conditional class loading, where you isolate the new-API code in a class that you only touch on a compatible device. I only use reflection for really lightweight stuff (e.g., finding the right CONTENT_URI value to use for Contacts or ContactsContract).
For example, this sample project uses two implementations of an abstract class to handle finding a Camera object -- on a Gingerbread device, it tries to use a front-facing camera.
Or, this sample project shows using the action bar on Honeycomb, including putting a custom View in it, while still maintaining backwards compatibility to older versions of Android.
I know this is a hack, but why can't you put the first call to the method in a try/catch of it's own, and nest the rest of your try/catch code in there. If the outer catch executes, the method doesn't exist.

Categories

Resources