Merge "Auto Messaging API Sample First draft" into lmp-dev
diff --git a/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java b/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java
index 45275be..dc03f80 100644
--- a/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java
+++ b/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java
@@ -160,6 +160,7 @@
mStarted = false;
mController.unregisterCallback(mCb);
try {
+ mNotificationManager.cancel(NOTIFICATION_ID);
mService.unregisterReceiver(this);
} catch (IllegalArgumentException ex) {
// ignore if the receiver is not registered.
diff --git a/MusicDemo/src/main/java/com/example/android/musicservicedemo/MusicService.java b/MusicDemo/src/main/java/com/example/android/musicservicedemo/MusicService.java
index 1950cd6..e085275 100644
--- a/MusicDemo/src/main/java/com/example/android/musicservicedemo/MusicService.java
+++ b/MusicDemo/src/main/java/com/example/android/musicservicedemo/MusicService.java
@@ -17,6 +17,7 @@
package com.example.android.musicservicedemo;
import android.content.Context;
+import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaDescription;
import android.media.MediaMetadata;
@@ -32,6 +33,8 @@
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.service.media.MediaBrowserService;
@@ -107,6 +110,8 @@
// Action to thumbs up a media item
private static final String CUSTOM_ACTION_THUMBS_UP = "thumbs_up";
+ // Delay stopSelf by using a handler.
+ private static final int STOP_DELAY = 30000;
// The volume we set the media player to when we lose audio focus, but are
// allowed to reduce the volume instead of stopping playback.
@@ -136,6 +141,9 @@
private MediaNotification mMediaNotification;
+ // Indicates whether the service was started.
+ private boolean mServiceStarted;
+
enum AudioFocus {
NoFocusNoDuck, // we don't have audio focus, and can't duck
NoFocusCanDuck, // we don't have focus, but can play at a low volume
@@ -150,6 +158,19 @@
// Indicates if we should start playing immediately after we gain focus.
private boolean mPlayOnFocusGain;
+ private Handler mDelayedStopHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if ((mMediaPlayer != null && mMediaPlayer.isPlaying()) ||
+ mPlayOnFocusGain) {
+ LogHelper.d(TAG, "Ignoring delayed stop since the media player is in use.");
+ return;
+ }
+ LogHelper.d(TAG, "Stopping service with delay handler.");
+ stopSelf();
+ mServiceStarted = false;
+ }
+ };
/*
* (non-Javadoc)
@@ -217,6 +238,7 @@
// Service is being killed, so make sure we release our resources
handleStopRequest(null);
+ mDelayedStopHandler.removeCallbacksAndMessages(null);
// In particular, always release the MediaSession to clean up resources
// and notify associated MediaController(s).
mSession.release();
@@ -232,7 +254,8 @@
// To ensure you are not allowing any arbitrary app to browse your app's contents, you
// need to check the origin:
if (!ANDROID_AUTO_PACKAGE_NAME.equals(clientPackageName) &&
- !ANDROID_AUTO_EMULATOR_PACKAGE_NAME.equals(clientPackageName)) {
+ !ANDROID_AUTO_EMULATOR_PACKAGE_NAME.equals(clientPackageName) &&
+ !getApplication().getPackageName().equals(clientPackageName)) {
// If the request comes from an untrusted package, return null. No further calls will
// be made to other media browsing methods.
LogHelper.w(TAG, "OnGetRoot: IGNORING request from untrusted package " + clientPackageName);
@@ -568,6 +591,16 @@
private void handlePlayRequest() {
LogHelper.d(TAG, "handlePlayRequest: mState=" + mState);
+ mDelayedStopHandler.removeCallbacksAndMessages(null);
+ if (!mServiceStarted) {
+ LogHelper.v(TAG, "Starting service");
+ // The MusicService needs to keep running even after the calling MediaBrowser
+ // is disconnected. Call startService(Intent) and then stopSelf(..) when we no longer
+ // need to play media.
+ startService(new Intent(getApplicationContext(), MusicService.class));
+ mServiceStarted = true;
+ }
+
mPlayOnFocusGain = true;
tryToGetAudioFocus();
@@ -607,9 +640,9 @@
updatePlaybackState(null);
}
- /**
- * Handle a request to stop music
- */
+ /**
+ * Handle a request to stop music
+ */
private void handleStopRequest(String withError) {
LogHelper.d(TAG, "handleStopRequest: mState=" + mState + " error=", withError);
mState = PlaybackState.STATE_STOPPED;
@@ -623,6 +656,7 @@
// service is no longer necessary. Will be started again if needed.
stopSelf();
+ mServiceStarted = false;
}
/**
@@ -637,6 +671,10 @@
// stop being a foreground service
stopForeground(true);
+ // reset the delayed stop handler.
+ mDelayedStopHandler.removeCallbacksAndMessages(null);
+ mDelayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
+
// stop and release the Media Player, if it's available
if (releaseMediaPlayer && mMediaPlayer != null) {
mMediaPlayer.reset();
@@ -874,7 +912,6 @@
mAudioFocus = AudioFocus.Focused;
}
}
-
}
/**
diff --git a/MusicDemo/src/main/java/com/example/android/musicservicedemo/utils/LogHelper.java b/MusicDemo/src/main/java/com/example/android/musicservicedemo/utils/LogHelper.java
index 4c757f7..31f1aef 100644
--- a/MusicDemo/src/main/java/com/example/android/musicservicedemo/utils/LogHelper.java
+++ b/MusicDemo/src/main/java/com/example/android/musicservicedemo/utils/LogHelper.java
@@ -18,37 +18,37 @@
import android.util.Log;
public class LogHelper {
- public final static void v(String tag, Object... messages) {
+ public static void v(String tag, Object... messages) {
log(tag, Log.VERBOSE, null, messages);
}
- public final static void d(String tag, Object... messages) {
+ public static void d(String tag, Object... messages) {
log(tag, Log.DEBUG, null, messages);
}
- public final static void i(String tag, Object... messages) {
+ public static void i(String tag, Object... messages) {
log(tag, Log.INFO, null, messages);
}
- public final static void w(String tag, Object... messages) {
+ public static void w(String tag, Object... messages) {
log(tag, Log.WARN, null, messages);
}
- public final static void w(String tag, Throwable t, Object... messages) {
+ public static void w(String tag, Throwable t, Object... messages) {
log(tag, Log.WARN, t, messages);
}
- public final static void e(String tag, Object... messages) {
+ public static void e(String tag, Object... messages) {
log(tag, Log.ERROR, null, messages);
}
- public final static void e(String tag, Throwable t, Object... messages) {
+ public static void e(String tag, Throwable t, Object... messages) {
log(tag, Log.ERROR, t, messages);
}
- public final static void log(String tag, int level, Throwable t, Object... messages) {
+ public static void log(String tag, int level, Throwable t, Object... messages) {
if (messages != null && Log.isLoggable(tag, level)) {
- String message = null;
+ String message;
if (messages.length == 1) {
message = messages[0] == null ? null : messages[0].toString();
} else {
@@ -56,10 +56,12 @@
for (Object m: messages) {
sb.append(m);
}
+ if (t != null) {
+ sb.append("\n").append(Log.getStackTraceString(t));
+ }
message = sb.toString();
}
- Log.d(tag, message, t);
+ Log.println(level, tag, message);
}
}
-
}