Pages

Showing posts with label Applications. Show all posts
Showing posts with label Applications. Show all posts

Sunday 24 March 2013

Backward compatibility for Android applications

Android 1.5 introduced a number of new features that application developers can take advantage of, like virtual input devices and speech recognition. As a developer, you need to be aware of backward compatibility issues on older devices—do you want to allow your application to run on all devices, or just those running newer software? In some cases it will be useful to employ the newer APIs on devices that support them, while continuing to support older devices.

If the use of a new API is integral to the program—perhaps you need to record video—you should add a manifest entry to ensure your app won't be installed on older devices. For example, if you require APIs added in 1.5, you would specify 3 as the minimum SDK version:

  ...  ... 

If you want to add a useful but non-essential feature, such as popping up an on-screen keyboard even when a hardware keyboard is available, you can write your program in a way that allows it to use the newer features without failing on older devices.

Using reflection

Suppose there's a simple new call you want to use, like android.os.Debug.dumpHprofData(String filename). The android.os.Debug class has existed since the first SDK, but the method is new in 1.5. If you try to call it directly, your app will fail to run on older devices.

The simplest way to call the method is through reflection. This requires doing a one-time lookup and caching the result in a Method object. Using the method is a matter of calling Method.invoke and un-boxing the result. Consider the following:

public class Reflect { private static Method mDebug_dumpHprofData; static { initCompatibility(); }; private static void initCompatibility() { try { mDebug_dumpHprofData = Debug.class.getMethod( "dumpHprofData", new Class[] { String.class } ); /* success, this is a newer device */ } catch (NoSuchMethodException nsme) { /* failure, must be older device */ } } private static void dumpHprofData(String fileName) throws IOException { try { mDebug_dumpHprofData.invoke(null, fileName); } catch (InvocationTargetException ite) { /* unpack original exception when possible */ Throwable cause = ite.getCause(); if (cause instanceof IOException) { throw (IOException) cause; } else if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } else { /* unexpected checked exception; wrap and re-throw */ throw new RuntimeException(ite); } } catch (IllegalAccessException ie) { System.err.println("unexpected " + ie); } } public void fiddle() { if (mDebug_dumpHprofData != null) { /* feature is supported */ try { dumpHprofData("/sdcard/dump.hprof"); } catch (IOException ie) { System.err.println("dump failed!"); } } else { /* feature not supported, do something else */ System.out.println("dump not supported"); } }}

This uses a static initializer to call initCompatibility, which does the method lookup. If that succeeds, it uses a private method with the same semantics as the original (arguments, return value, checked exceptions) to do the call. The return value (if it had one) and exception are unpacked and returned in a way that mimics the original. The fiddle method demonstrates how the application logic would choose to call the new API or do something different based on the presence of the new method.

For each additional method you want to call, you would add an additional private Method field, field initializer, and call wrapper to the class.

This approach becomes a bit more complex when the method is declared in a previously undefined class. It's also much slower to call Method.invoke() than it is to call the method directly. These issues can be mitigated by using a wrapper class.

Using a wrapper class

The idea is to create a class that wraps all of the new APIs exposed by a new or existing class. Each method in the wrapper class just calls through to the corresponding real method and returns the same result.

If the target class and method exist, you get the same behavior you would get by calling the class directly, with a small amount of overhead from the additional method call. If the target class or method doesn't exist, the initialization of the wrapper class fails, and your application knows that it should avoid using the newer calls.

Suppose this new class were added:

public class NewClass { private static int mDiv = 1; private int mMult; public static void setGlobalDiv(int div) { mDiv = div; } public NewClass(int mult) { mMult = mult; } public int doStuff(int val) { return (val * mMult) / mDiv; }}

We would create a wrapper class for it:

class WrapNewClass { private NewClass mInstance; /* class initialization fails when this throws an exception */ static { try { Class.forName("NewClass"); } catch (Exception ex) { throw new RuntimeException(ex); } } /* calling here forces class initialization */ public static void checkAvailable() {} public static void setGlobalDiv(int div) { NewClass.setGlobalDiv(div); } public WrapNewClass(int mult) { mInstance = new NewClass(mult); } public int doStuff(int val) { return mInstance.doStuff(val); }}

This has one method for each constructor and method in the original, plus a static initializer that tests for the presence of the new class. If the new class isn't available, initialization of WrapNewClass fails, ensuring that the wrapper class can't be used inadvertently. The checkAvailable method is used as a simple way to force class initialization. We use it like this:

public class MyApp { private static boolean mNewClassAvailable; /* establish whether the "new" class is available to us */ static { try { WrapNewClass.checkAvailable(); mNewClassAvailable = true; } catch (Throwable t) { mNewClassAvailable = false; } } public void diddle() { if (mNewClassAvailable) { WrapNewClass.setGlobalDiv(4); WrapNewClass wnc = new WrapNewClass(40); System.out.println("newer API is available - " + wnc.doStuff(10)); } else { System.out.println("newer API not available"); } }}

If the call to checkAvailable succeeds, we know the new class is part of the system. If it fails, we know the class isn't there, and adjust our expectations accordingly. It should be noted that the call to checkAvailable will fail before it even starts if the bytecode verifier decides that it doesn't want to accept a class that has references to a nonexistent class. The way this code is structured, the end result is the same whether the exception comes from the verifier or from the call to Class.forName.

When wrapping an existing class that now has new methods, you only need to put the new methods in the wrapper class. Invoke the old methods directly. The static initializer in WrapNewClass would be augmented to do a one-time check with reflection.

Testing is key

You must test your application on every version of the Android framework that is expected to support it. By definition, the behavior of your application will be different on each. Remember the mantra: if you haven't tried it, it doesn't work.

You can test for backward compatibility by running your application in an emulator from an older SDK, but as of the 1.5 release there's a better way. The SDK allows you to specify "Android Virtual Devices" with different API levels. Once you create the AVDs, you can test your application with old and new versions of the system, perhaps running them side-by-side to see the differences. More information about emulator AVDs can be found in the SDK documentation and from emulator -help-virtual-device.


Learn about Android 1.5 and more at Google I/O. Members of the Android team will be there to give a series of in-depth technical sessions and to field your toughest questions.

Wednesday 20 March 2013

Android Market update: support for priced applications

I'm pleased to announce that Android Market is now accepting priced applications from US and UK developers. Developers from these countries can go to the publisher website at http://market.android.com/publish to upload their application(s) along with end user pricing for the apps. Initially, priced applications will be available to end users in the US starting mid next week. We will add end user support for additional countries in the coming months.

We will also enable developers in Germany, Austria, Netherlands, France, and Spain to offer priced applications later this quarter. By the end of Q1 2009, we will announce support for developers in additional countries. Developers can find more information about priced applications in Android Market at http://market.android.com/support/

Google Checkout will serve as the payment and billing mechanism for Android Market. Developers who do not already have a Google Checkout merchant account can easily sign up for one via the publisher website.

Also, Android Market for free applications will become available to users in Australia starting February 15th Pacific Time and in Singapore in the coming weeks. Developers can now make their applications available in these countries via the publisher website at http://market.android.com/publish.

We look forward to seeing more great applications on Android Market.

Android Market update: priced applications for US users

Last Friday, we enabled developers to upload priced apps and saw a flurry of activity in the days that followed. Today, it is my pleasure to let you know that we have begun the phased rollout of priced applications to T-Mobile G1 users in the US. Once the service is enabled on their devices, T-Mobile G1 users will be able to see the priced apps immediately without the need to reboot. For more details on this update to Android Market, please see last week's blogpost.

Tuesday 12 March 2013

Allowing applications to play nice(r) with each other: Handling remote control buttons

[This post is by Jean-Michel Trivi, an engineer working on the Android Media framework, whose T-shirt of the day reads “all your media buttons are belong to you”. — Tim Bray]

Many Android devices come with the Music application used to play audio files stored on the device. Some devices ship with a wired headset that features transport control buttons, so users can for instance conveniently pause and restart music playback, directly from the headset.

But a user might use one application for music listening, and another for listening to podcasts, both of which should be controlled by the headset remote control.

If your media playback application creates a media playback service, just like Music, that responds to the media button events, how will the user know where those events are going to? Music, or your new application?

In this article, we’ll see how to handle this properly in Android 2.2. We’ll first see how to set up intents to receive “MEDIA_BUTTON” intents. We’ll then describe how your application can appropriately become the preferred media button responder in Android 2.2. Since this feature relies on a new API, we’ll revisit the use of reflection to prepare your app to take advantage of Android 2.2, without restricting it to API level 8 (Android 2.2).

An example of the handling of media button intents

In our AndroidManifest.xml for this package we declare the class RemoteControlReceiver to receive MEDIA_BUTTON intents:

   

Our class to handle those intents can look something like this:

public class RemoteControlReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) { /* handle media button intent here by reading contents */ /* of EXTRA_KEY_EVENT to know which key was pressed */ } }}

In a media playback application, this is used to react to headset button presses when your activity doesn’t have the focus. For when it does, we override the Activity.onKeyDown() or onKeyUp() methods for the user interface to trap the headset button-related events.

However, this is problematic in the scenario we mentioned earlier. When the user presses “play”, what application should start playing? The Music application? The user’s preferred podcast application?

Becoming the “preferred” media button responder

In Android 2.2, we are introducing two new methods in android.media.AudioManager to declare your intention to become the “preferred” component to receive media button events: registerMediaButtonEventReceiver() and its counterpart, unregisterMediaButtonEventReceiver(). Once the registration call is placed, the designated component will exclusively receive the ACTION_MEDIA_BUTTON intent just as in the example above.

In the activity below were are creating an instance of AudioManager with which we will register our component. We therefore create a ComponentName instance that references our intended media button event responder.

public class MyMediaPlaybackActivity extends Activity { private AudioManager mAudioManager; private ComponentName mRemoteControlResponder; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); mRemoteControlResponder = new ComponentName(getPackageName(), RemoteControlReceiver.class.getName());}

The system handles the media button registration requests in a “last one wins” manner. This means we need to select where it makes sense for the user to make this request. In a media playback application, proper uses of the registration are for instance:

  • when the UI is displayed: the user is interacting with that application, so (s)he expects it to be the one that will respond to the remote control,

  • when content starts playing (e.g. content finished downloading, or another application caused your service to play content)

Registering is here performed for instance when our UI comes to the foreground:

 @Override public void onResume() { super.onResume(); mAudioManager.registerMediaButtonEventReceiver( mRemoteControlResponder); }

If we had previously registered our receiver, registering it again will push it up the stack, and doesn’t cause any duplicate registration.

Additionally, it may make sense for your registered component not to be called when your service or application is destroyed (as illustrated below), or under conditions that are specific to your application. For instance, in an application that reads to the user her/his appointments of the day, it could unregister when it’s done speaking the calendar entries of the day.

 @Override public void onDestroy() { super.onDestroy(); mAudioManager.unregisterMediaButtonEventReceiver( mRemoteControlResponder); }

After “unregistering”, the previous component that requested to receive the media button intents will once again receive them.

Preparing your code for Android 2.2 without restricting it to Android 2.2

While you may appreciate the benefit this new API offers to the users, you might not want to restrict your application to devices that support this feature. Andy McFadden shows us how to use reflection to take advantage of features that are not available on all devices. Let’s use what we learned then to enable your application to use the new media button mechanism when it runs on devices that support this feature.

First we declare in our Activity the two new methods we have used previously for the registration mechanism:

 private static Method mRegisterMediaButtonEventReceiver; private static Method mUnregisterMediaButtonEventReceiver;

We then add a method that will use reflection on the android.media.AudioManager class to find the two methods when the feature is supported:

private static void initializeRemoteControlRegistrationMethods() { try { if (mRegisterMediaButtonEventReceiver == null) { mRegisterMediaButtonEventReceiver = AudioManager.class.getMethod( "registerMediaButtonEventReceiver", new Class[] { ComponentName.class } ); } if (mUnregisterMediaButtonEventReceiver == null) { mUnregisterMediaButtonEventReceiver = AudioManager.class.getMethod( "unregisterMediaButtonEventReceiver", new Class[] { ComponentName.class } ); } /* success, this device will take advantage of better remote */ /* control event handling */ } catch (NoSuchMethodException nsme) { /* failure, still using the legacy behavior, but this app */ /* is future-proof! */ }}

The method fields will need to be initialized when our Activity class is loaded:

 static { initializeRemoteControlRegistrationMethods(); }

We’re almost done. Our code will be easier to read and maintain if we wrap the use of our methods initialized through reflection by the following. Note in bold the actual method invocation on our AudioManager instance:

 private void registerRemoteControl() { try { if (mRegisterMediaButtonEventReceiver == null) { return; } mRegisterMediaButtonEventReceiver.invoke(mAudioManager, mRemoteControlResponder); } catch (InvocationTargetException ite) { /* unpack original exception when possible */ Throwable cause = ite.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } else { /* unexpected checked exception; wrap and re-throw */ throw new RuntimeException(ite); } } catch (IllegalAccessException ie) { Log.e(”MyApp”, "unexpected " + ie); } }  private void unregisterRemoteControl() { try { if (mUnregisterMediaButtonEventReceiver == null) { return; } mUnregisterMediaButtonEventReceiver.invoke(mAudioManager, mRemoteControlResponder); } catch (InvocationTargetException ite) { /* unpack original exception when possible */ Throwable cause = ite.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } else { /* unexpected checked exception; wrap and re-throw */ throw new RuntimeException(ite); } } catch (IllegalAccessException ie) { System.err.println("unexpected " + ie);  } }

We are now ready to use our two new methods, registerRemoteControl() and unregisterRemoteControl() in a project that runs on devices supporting API level 1, while still taking advantage of the features found in devices running Android 2.2.

Sunday 3 March 2013

How to Remove Default ROM applications on Android Phones?

How to Remove Default ROM applications


How to Remove Default ROM applications on Android Phones


Are you wondering how to remove an application that has been bundling with congenital ROM that you install on an Android phone? Take it easy, because on this occasion I will discuss about it, How to Remove Default ROM applications on Android phones?

Perhaps you are tired of looking at applications that are not useful in our part of the Android menu, or you do not know the function of the menu? Surely you will remove the application, but do not know how to Delete Applications are? Or would you even let menu of the application remains on the menu your Android phone? That will make your Android phone to be wasteful of memory. We better remove the application by following the steps - the steps below:

1. Prepare rootex (Root Explorer) as a tool of our time fighting this. If you do not already have it, please download here and then install.
2. Then open the application rootex already was installed.
3. Go to the directory system / app / (this is the application). Do not remove all of it? Delete that you think are not necessary.
4. If you can not remove it and display a warning “….apk cannot be deleted because the file system is read-only”, do not panic. Navigate your views into the upper right corner and click the box that says Mount R / O to Mount R / W.
5. Then repeat the process of elimination.
6. Click Yes to remove it. Completed.
7. Reboot to see changes.

Easy is not it? Using only one application we can remove all the applications on our Android phones. But do not remove all, if cleared of all or any of the deletion could be your Android phone will be the error. So please be careful.

Note: Any damage caused is your own responsibility, and is not my responsibility. So please be - careful

Sunday 24 February 2013

Android Applications That Contains a Virus

Android-logo-with-Virus-Bug
Android Applications That Contains a Virus

Symantec has just released a list of applications that contain a virus. Some of them are still circulating widely in the Android Market. One type of virus that has just detected is counterclank, these malicious programs have the ability to spy on his victim and sends a number of important data to the creator. Counterclank virus spread was quite rapid. Because, in addition made ??by the three developers, the virus can also spread through the android market, as released BlogSymantec.

At least, there are 13 applications that contain viruses were identified by Symantec in the Android Market.

List of applications should not be downloaded:
1. Counter Elite Force
2. Conter Strike Ground Force
3. Counter Strike Hit Enemy
4. Heart Live Wallpaper
5. Hit Counter Terrorist
6. Stripper Touch Girl
7. Balloon Game
8. Deal & Be Millionaire
9. Wild Man
10. Pretty Women Lingerie Puzzle
11. Sexy Girls Photo Game
12. Sexy Girls Puzzle
13. Sexy Women Puzzle