11

I am building an app that requires a lot of drawing on the canvas. I notice that the app is a bit laggy in devices with high resolution (nexus 7 for example). I saw there is a Force GPU option in the developer option. When Force GPU is enabled, my app runs absolutely smooth.

I have read that this Force GPU option is called Hardware Acceleration and it is available only for Android 3.0 and above.

My app is targeting Android 2.3 and above.

Is it possible to programmatically enable Hardware Accelerated (or Force GPU--whatever the magic is called) on any Android 3.0 or above devices?

Something like:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){

    Turn On Hardware Accelerate HERE but How can i do this?
    any code snippet would be welcome/helpful/thanks

}
Kyll
  • 7,036
  • 7
  • 41
  • 64
xiaowoo
  • 2,248
  • 7
  • 34
  • 45
  • Sorry for the confusion, I am building my app on android 2.3 api 10, so it doesn't really have or getWindow().setFlags( WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); – xiaowoo Mar 03 '13 at 21:10
  • Did you add suppression to your onCreate? – wtsang02 Mar 03 '13 at 21:12
  • Please set your build target to API Level 11 or higher, then use `android:hardwareAccelerated="true"`. – CommonsWare Mar 03 '13 at 21:16
  • if i set my build tartget to API Level 11 then I won't be able to support API level 10 devices... I would like to still be able to support api 10... – xiaowoo Mar 03 '13 at 21:18
  • wtsang02, i tried your code but its erroring me with "FLAG_HARDWARE_ACCELERATED cannot be resolved or is not a field" because WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED is not available in api 10 – xiaowoo Mar 03 '13 at 21:22
  • 'if i set my build tartget to API Level 11 then I won't be able to support API level 10 devices" -- yes, you can. – CommonsWare Mar 03 '13 at 21:28

3 Answers3

7

I assume you've already added android:hardwareAccelerated to your Manifest file?

<application android:hardwareAccelerated="true" ...>

That is what enables hardware acceleration within your application per the guide on hardware acceleration and should do exactly what forcing GPU does at a system level.

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • my app uses android 2.3 api 10, it doesn't have android:hardwareAccelerated, so its complaining about "No resource identifier found for attribute 'hardwareAccelerated' in package 'android'" – xiaowoo Mar 03 '13 at 21:15
  • 1
    You can build and target different API levels. Build against API 11+ and keep your minimum SDK at 10. – ianhanniballake Mar 03 '13 at 21:20
  • ianhanniballake, you are saying I can build my app using the latest api(11) and make it still runnable in lower api devices? Does this mean I just need to upgrade my android project target to the latest api? – xiaowoo Mar 03 '13 at 21:26
  • 3
    That is exactly correct. It is the android:minSdkVersion in your Manifest that controls what devices it will run on, not what you build on. This allows you to use new APIs while remaining backward compatible. Of course, you'd still want a version check before any method calls, but in this case the hardwareAccelerated XML attribute is just ignored on pre-Honeycomb devices. – ianhanniballake Mar 03 '13 at 21:28
  • ahh, i am gonna give that a try... and thanks for your comment – xiaowoo Mar 03 '13 at 21:32
4

Set minSdkVersion to 10 and targetSdkVersion to maximum

Like below

 <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="17" />

then

<application android:hardwareAccelerated="true" ...>

Now will work

And for particularities

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB){
     view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}

or

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB){
     view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
bmkay
  • 462
  • 6
  • 9
0

If you want to build your application using lower api level you can access the method via reflection:

    try {
        Method setLayerType = view.getClass().getMethod(
                "setLayerType", new Class[] { int.class, Paint.class });
        if (setLayerType != null)
            setLayerType.invoke(view, new Object[] { LAYER_TYPE_X, null });
    } catch (NoSuchMethodException e) {
    } catch (IllegalArgumentException e) {
    } catch (IllegalAccessException e) {
    } catch (InvocationTargetException e) {
    }

Where LAYER_TYPE_X is the constant integer value of wanted layer type:

LAYER_TYPE_NONE = 0
LAYER_TYPE_SOFTWARE = 1
LAYER_TYPE_HARDWARE = 2
Niko
  • 8,093
  • 5
  • 49
  • 85