There are a million and five questions on SO about this, but I've tried sorting through them all, and can not get it working. I know that AppWidgetProvider just extends BroadcastReceiver so I think I can just do everything within my AppWidgetProvider. I've read that the intent filter ACTION_HEADSET_PLUG is Intent.FLAG_RECEIVER_REGISTERED_ONLY and tried following this: Detecting whether a headset is plugged into an Android device or not. to set my filter in code, but it was pretty mish-mash and I couldn't wrap my head around it.
I've toasted out intent.getAction() in my onReceive method and when I plug or unplug my headphones, nothing gets shown. When I press buttons though, I see the int constant associated with them. I'm assuming this is because it's being blocked by the registered only thing.
I also read about some sticky-something-or-other and forked around with that for a while, all to no avail.
here is my AppWidgetManager:
package com.example.musicplayerforburrito;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.widget.RemoteViews;
import android.widget.Toast;
public class MyWidgetProvider extends AppWidgetProvider {
public static String WIDGET_PLAY_BUTTON = "android.appwidget.action.PLAY_PAUSE_WIDGETS";
public static String NEXT_BUTTON = "android.appwidget.action.NEXT_WIDGETS";
public static String PREVIOUS_BUTTON = "android.appwidget.action.PREVIOUS_WIDGETS";
public static String RELOAD_BUTTON = "android.appwidget.action.RELOAD_WIDGETS";
static MusicPlayerClass mpc;
static String CurrentlyPlayingSong = "";
static Context cont;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
mpc = new MusicPlayerClass(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
ComponentName watchWidget = new ComponentName(context, MyWidgetProvider.class);
remoteViews.setOnClickPendingIntent(R.id.playpausewidget, getPendingSelfIntent(context, WIDGET_PLAY_BUTTON));
remoteViews.setOnClickPendingIntent(R.id.forwardwidget, getPendingSelfIntent(context, NEXT_BUTTON));
remoteViews.setOnClickPendingIntent(R.id.backwidget, getPendingSelfIntent(context, PREVIOUS_BUTTON));
remoteViews.setOnClickPendingIntent(R.id.reloadwidget, getPendingSelfIntent(context, RELOAD_BUTTON));
appWidgetManager.updateAppWidget(watchWidget, remoteViews);
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
super.onReceive(context, intent);
//if(intent.hasExtra("state"))
// Toast.makeText(context, "hi jimmy", 2000).show();
Toast.makeText(context, intent.getAction(), 2000).show();
try
{
String b = mpc.currentlyPlayingSong;
}
catch(Exception e)
{
mpc = new MusicPlayerClass(context);
}
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews( context.getPackageName(), R.layout.widget_layout );
ComponentName watchWidget = new ComponentName(context, MyWidgetProvider.class);
cont = context;
if (WIDGET_PLAY_BUTTON.equals(intent.getAction())) {
if(!mpc.hasFolders)
{
mpc.Initialize();
mpc.mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
public void onCompletion(MediaPlayer mp)
{
mpc.songIndex++;
CurrentlyPlayingSong = mpc.StartSong();
UpdateTitle(cont);
}
});
}
if(mpc.isPlaying)
{
mpc.isPlaying = false;
mpc.PauseMusic();
remoteViews.setImageViewResource(R.id.playpausewidget, R.drawable.play);
}
else if(mpc.currentPosition != 0)
{
mpc.isPlaying = true;
mpc.ResumeMusic();
remoteViews.setImageViewResource(R.id.playpausewidget, R.drawable.pause);
}
else
{
remoteViews.setTextViewText(R.id.mp3filename, mpc.StartSong());
remoteViews.setImageViewResource(R.id.playpausewidget, R.drawable.pause);
}
}
else if (NEXT_BUTTON.equals(intent.getAction())) {
mpc.songIndex++;
remoteViews.setTextViewText(R.id.mp3filename, mpc.StartSong());
}
else if (PREVIOUS_BUTTON.equals(intent.getAction())) {
mpc.songIndex--;
remoteViews.setTextViewText(R.id.mp3filename, mpc.StartSong());
}
else if (RELOAD_BUTTON.equals(intent.getAction())) {
mpc.Reload();
mpc.mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
public void onCompletion(MediaPlayer mp)
{
mpc.songIndex++;
CurrentlyPlayingSong = mpc.StartSong();
UpdateTitle(cont);
}
});
remoteViews.setTextViewText(R.id.mp3filename, mpc.StartSong());
remoteViews.setImageViewResource(R.id.playpausewidget, R.drawable.pause);
}
appWidgetManager.updateAppWidget(watchWidget, remoteViews);
}
private void UpdateTitle(Context context)
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews( context.getPackageName(), R.layout.widget_layout );
ComponentName watchWidget = new ComponentName(context, MyWidgetProvider.class);
remoteViews.setTextViewText(R.id.mp3filename, CurrentlyPlayingSong);
appWidgetManager.updateAppWidget(watchWidget, remoteViews);
}
protected PendingIntent getPendingSelfIntent(Context context, String action) {
Intent intent = new Intent(context, getClass());
intent.setAction(action);
return PendingIntent.getBroadcast(context, 0, intent, 0);
}
}
here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.musicplayerforburrito"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name="MyWidgetProvider" >
<intent-filter >
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.PLAY_PAUSE_WIDGETS" />
<action android:name="android.appwidget.action.NEXT_WIDGETS" />
<action android:name="android.appwidget.action.PREVIOUS_WIDGETS" />
<action android:name="android.appwidget.action.RELOAD_WIDGETS" />
<action android:name="android.appwidget.action.ACTION_HEADSET_PLUG" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.ACTION_HEADSET_PLUG"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />
</receiver>
<activity
android:name="com.example.musicplayerforburrito.MusicPlayer"
android:label="@string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I've been fighting with this for literally hours which seems really stupid because it's not even that big of a "feature" to pause the music when the headphones are unplugged. Any guidance you can share would be greatly appreciated.
TIA
The answer at https://stackoverflow.com/a/9682818/1682419 quotes Dianne Hackborn (who's in the core Android team). You'll need a Service or Activity that stays running as long as you're interested in these broadcast messages, and it needs to call
registerReceiver()
to register for these messages.Note 1: When you invent Intent actions, you're supposed to use your own package name, not
android.intent.action
, to avoid name conflicts.Note 2: The widget provider's
<intent-filter>
should only list the public actionandroid.appwidget.action.APPWIDGET_UPDATE
. There's no benefit in including the private on-click actions andandroid.intent.action.ACTION_HEADSET_PLUG
.