Android, BroadcastReceiver, headset controls

Power to opensource!

Because of it I could personalize an app by adding a few lines of code, without reinventing the wheel.

Goal: improve a mediaplayer app to handle headset controls events, even if the screen is off or I’m using another app (there it goes the broadcast receiver functionality).

First, main activity must implement OnKeyListener

...
import .........
...
public class MPlayer extends Activity implements OnKeyListener {...

Second, implement the method OnKeyDown

public ImageButton playButton;
public ImageButton stopButton;
public ImageButton skipButton;
 ....
  oncreate method that instantiates those buttons, by findviewbyid for example
  ....
@Override
public boolean onKey(View arg0, int arg1, KeyEvent arg2) {
// TODO Auto-generated method stub
	return false;
}

/* media controls */
public boolean onKeyDown(int keyCode, KeyEvent event) {
super.onKeyDown(keyCode, event);
switch (keyCode) {
	case KeyEvent.KEYCODE_MEDIA_NEXT:
		skipButton.performClick();
		return true;
	case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
		stopButton.performClick();
		return true;
	case KeyEvent.KEYCODE_HEADSETHOOK:
		playButton.performClick();
		return true;
		}
		return false;
}

Third, create the receiver

/* creating an intent filter */
private final BroadcastReceiver headsetReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
	String intentAction = intent.getAction();
	if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction))
		return;
	KeyEvent event = (KeyEvent) intent
			.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
	int keycode = event.getKeyCode();
	int action = event.getAction();
	Log.i("keycode", String.valueOf(keycode));
	Log.i("action", String.valueOf(action));
                 //onKeyDown(keyCode, event)
	if (keycode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
			|| keycode == KeyEvent.KEYCODE_HEADSETHOOK)
			if (action == KeyEvent.ACTION_DOWN)
				playButton.performClick();
	if (keycode == KeyEvent.KEYCODE_MEDIA_NEXT)
			if (action == KeyEvent.ACTION_DOWN)
				skipButton.performClick();
	if (keycode == KeyEvent.KEYCODE_MEDIA_PREVIOUS)
			if (action == KeyEvent.ACTION_DOWN)
				stopButton.performClick();

		}

};

/* unregistering intent receiver */

public void onDestroy() {
	super.onDestroy();
	unregisterReceiver(headsetReceiver);
}

Last, registering the intent receiver in onCreate method

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);
		/* creating and registering intent receiver */
	IntentFilter mediaFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
	mediaFilter.setPriority(1000);
	registerReceiver(headsetReceiver, mediaFilter);
         ....
         ....

Last but not least, even if you declare and register the intent receiver via code, you can also add a couple of lines of code in your app manifest

<activity android:name=".MPlayer" android:label="@string/app_name">
	<intent-filter>
		<action android:name="android.intent.action.MAIN" />
		<category android:name="android.intent.category.LAUNCHER" />
	</intent-filter>
	<intent-filter android:priority="1000000000">
		<action android:name="android.intent.action.MEDIA_BUTTON" />
	</intent-filter>
</activity>
 
 
 
 

Sources: various( I mean VARIOUS, like ALOT) android articles, android developers docs and google results and my working app. Headset finally plugged in and controls being used!

Experiencing with kSoap 2 and complex objects

As usual, I stumbled upon a problem, but this time during application development for Android.(Jump right into the problem explanation)

Imagine having to develop the application so that it can communicate with a webservice that you have already built some sort of programming language, such as in Java by using Axis2 (maybe in version 1.5.1) and a tomcat server (maybe in version 6).

kSoap 2 is an API designed to enable communication between mobile applications programmed in Java and web services.

I’m not very experienced in the use of this API, but it seemed a common problem of many people who use it, the impossibility of working with a list of objects, or rather with arrays of objects coming back as a result of a method of ur webservice.

Since my problem was a ClassCastException, due to the impossibility of casting the type ‘anyType‘ into something useful, like an object of my creation, or maybe an array of my objects, the solution was found using a method similar to Russian dolls.

Now let me explain better.

In the side of the web service application, you use data types that you created through the classes, but maybe you should call them by their name objects.

These objects are Java Beans suitably designed to be serialized into SOAP messages through the use of Axis2.

Axis2 supports the return lists of objects, so that through the use of SoapUI you can read the SOAP message response from the webservice and note the list of returned items. Even more, in the WSDL file that describes the web service, the return value of this method is marked as ‘sequence‘ object of our type.

The problem is kSoap that fails to convert and manage complex data type as the array of our objects, declaring it as ‘anyType‘.

Fortunately it is possible to decompose the object ‘anyType‘ for extracting fields(actually is a SoapObject, and we can use his methods like .getProperty(index) and .getPropertyCount() ).

The problem is that it does not handle arrays, it only returns the first object instead of the whole list. At this point I had to create an additional class that enclose my array of objects and then I edited the method of the webservice to return this new ‘wrapper‘ object.

kSoap doing so receives a single object that contains within it a sequence of objects that make up the array correctly serialized by Axis2. Here is an explanation of the Russian dolls.A big complex and custom object that include small complex objects.

Is our task in the client side of android, provide to the unwrapping of the object, that is remapped into the corresponding complex-object instances.
This is not a solution but a patch to the problem, a patch that I decided to take as we have upcoming deadlines on the development/deployment of the application.

Here is a picture to express a thousand words I wrote and made you read so far.

Drawing done with Balsamiq Mockups (for Desktop [demo]).

Here is a sample of code that unwraps soapObjects using .getProperty(index) and .getPropertyCount().

http://pastebin.com/JMpeYFK5

 

 

Recap:

webservice-side:

first I create my array of AccessoBean objects, then I give it to  the

.setListaAccesso(AccessoBean[] list)

method of my ArrayOfAccessoBean wrapper object.

My object  ‘AccessoBean’

http://pastebin.com/85dhXXsf

My wrapper object for an array of  ‘AccessoBean’ (how to do a simple wrapper class)

http://pastebin.com/eTBzap3x

So, instead of returning an array( ‘list’ of objects ), I’m returning a single object that contains my array of objects.

Please let me know if you solved this problem in another and/or more elegant way!

3d Graffiti – 3d tag : a concept of augmented reality for mobile devices

On scribd

On slideshare

Creative Commons License
3D graffiti – augmented reality for mobile devices + georeferentiated data by Pier Giuliano Nioi is licensed under a Creative Commons Attribuzione-Non commerciale-Condividi allo stesso modo 2.5 Italia License.
Based on a work at piergiu.wordpress.com.
Permissions beyond the scope of this license may be available at https://piergiu.wordpress.com/2010/05/02/3d-graffiti-3d-tag-a-concept-of-augmented-reality-for-mobile-devices/.