[Android] [PATCH] recommandations on Android TV
Geoffrey Métais
geoffrey.metais at gmail.com
Wed Nov 19 13:31:48 CET 2014
---
.../vlc/gui/video/VideoPlayerActivity.java | 2 +-
vlc-android/tv/AndroidManifest.xml | 85 ++++++-----
.../org/videolan/vlc/gui/tv/BootupReceiver.java | 57 +++++++
.../vlc/gui/tv/RecommendationsService.java | 164 +++++++++++++++++++++
4 files changed, 271 insertions(+), 37 deletions(-)
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/BootupReceiver.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/RecommendationsService.java
diff --git a/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java b/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
index e0779cb..06b9f20 100644
--- a/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
+++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
@@ -124,7 +124,7 @@ public class VideoPlayerActivity extends Activity implements IVideoPlayer {
// Internal intent identifier to distinguish between internal launch and
// external intent.
- private final static String PLAY_FROM_VIDEOGRID = "org.videolan.vlc.gui.video.PLAY_FROM_VIDEOGRID";
+ public final static String PLAY_FROM_VIDEOGRID = "org.videolan.vlc.gui.video.PLAY_FROM_VIDEOGRID";
private SurfaceView mSurfaceView;
private SurfaceView mSubtitlesSurfaceView;
diff --git a/vlc-android/tv/AndroidManifest.xml b/vlc-android/tv/AndroidManifest.xml
index 8360431..426aa26 100644
--- a/vlc-android/tv/AndroidManifest.xml
+++ b/vlc-android/tv/AndroidManifest.xml
@@ -19,6 +19,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Needed for audio search on TV -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-feature
android:name="android.hardware.touchscreen"
@@ -36,49 +37,47 @@
android:logo="@drawable/ic_logo_w"
android:theme="@style/Theme.VLC.NoTitleBar" >
<activity
- android:name="org.videolan.vlc.gui.tv.MainTvActivity"
- android:label="@string/app_name"
- android:theme="@style/Theme.Leanback">
+ android:name="org.videolan.vlc.gui.tv.MainTvActivity"
+ android:label="@string/app_name"
+ android:theme="@style/Theme.Leanback" >
+ <intent-filter android:priority="5" >
+ <action android:name="android.intent.action.MAIN" />
- <intent-filter
- android:priority="5">
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
- </intent-filter>
- </activity>
-
- <activity android:name="org.videolan.vlc.gui.tv.DetailsActivity"
- android:exported="true"
- android:theme="@style/Theme.Leanback"/>
-
- <activity android:name="org.videolan.vlc.gui.tv.VerticalGridActivity"
- android:exported="true"
- android:theme="@style/Theme.Leanback"/>
-
- <activity android:name="org.videolan.vlc.gui.tv.SearchActivity"
- android:exported="true"
- android:theme="@style/Theme.Leanback"/>
-
- <activity android:name="org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity"
- android:exported="true"
- android:launchMode="singleInstance"
- android:theme="@style/Theme.Leanback"/>
-
- <activity android:name=".gui.CompatErrorActivity" />
- <activity android:name=".gui.PreferencesActivity" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="org.videolan.vlc.gui.tv.DetailsActivity"
+ android:exported="true"
+ android:theme="@style/Theme.Leanback" />
<activity
- android:name=".gui.BrowserActivity"
+ android:name="org.videolan.vlc.gui.tv.VerticalGridActivity"
+ android:exported="true"
+ android:theme="@style/Theme.Leanback" />
+ <activity
+ android:name="org.videolan.vlc.gui.tv.SearchActivity"
+ android:exported="true"
+ android:theme="@style/Theme.Leanback" />
+ <activity
+ android:name="org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity"
+ android:exported="true"
+ android:launchMode="singleInstance"
+ android:theme="@style/Theme.Leanback" />
+ <activity android:name="org.videolan.vlc.gui.CompatErrorActivity" />
+ <activity android:name="org.videolan.vlc.gui.PreferencesActivity" />
+ <activity
+ android:name="org.videolan.vlc.gui.BrowserActivity"
android:label="@string/mediafiles"
android:theme="@style/Theme.VLC.NoTitleBar" />
- <activity android:name=".gui.DebugLogActivity" />
+ <activity android:name="org.videolan.vlc.gui.DebugLogActivity" />
<activity
- android:name=".gui.NativeCrashActivity"
+ android:name="org.videolan.vlc.gui.NativeCrashActivity"
android:process=":NativeCrashActivity"
android:stateNotNeeded="true"
android:theme="@style/Theme.VLC" />
<activity
- android:name=".gui.video.VideoPlayerActivity"
+ android:name="org.videolan.vlc.gui.video.VideoPlayerActivity"
android:configChanges="orientation|screenSize"
android:theme="@style/Theme.VLC.Player" >
@@ -397,13 +396,13 @@
<service android:name="org.videolan.vlc.audio.AudioService" />
- <receiver android:name=".PhoneStateReceiver" >
+ <receiver android:name="org.videolan.vlc.PhoneStateReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<receiver
- android:name=".widget.VLCAppWidgetProvider"
+ android:name="org.videolan.vlc.widget.VLCAppWidgetProvider"
android:exported="false"
android:label="VLC mini player" >
<intent-filter>
@@ -414,6 +413,20 @@
android:name="android.appwidget.provider"
android:resource="@xml/vlcwidget" />
</receiver>
+
+ <service
+ android:name="org.videolan.vlc.gui.tv.RecommendationsService"
+ android:exported="false" >
+ </service>
+
+ <receiver
+ android:name="org.videolan.vlc.gui.tv.BootupReceiver"
+ android:enabled="true"
+ android:exported="true" >
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED"/>
+ </intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/BootupReceiver.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/BootupReceiver.java
new file mode 100644
index 0000000..689be57
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/BootupReceiver.java
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * BootupReceiver.java
+ *****************************************************************************
+ * Copyright © 2012-2014 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+package org.videolan.vlc.gui.tv;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class BootupReceiver extends BroadcastReceiver {
+ public BootupReceiver() {
+ }
+ private static final String TAG = "VLC/BootupReceiver";
+
+ private static final long INITIAL_DELAY = 5000;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().endsWith(Intent.ACTION_BOOT_COMPLETED)) {
+ Log.d(TAG, "ACTION_BOOT_COMPLETED ");
+ scheduleRecommendationUpdate(context);
+ }
+ }
+
+ private void scheduleRecommendationUpdate(Context context) {
+ AlarmManager alarmManager = (AlarmManager)context.getSystemService(
+ Context.ALARM_SERVICE);
+ Intent recommendationIntent = new Intent(context,
+ RecommendationsService.class);
+ PendingIntent alarmIntent = PendingIntent.getService(context, 0,
+ recommendationIntent, 0);
+
+ alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ INITIAL_DELAY,
+ AlarmManager.INTERVAL_HOUR,
+ alarmIntent);
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/RecommendationsService.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/RecommendationsService.java
new file mode 100644
index 0000000..e2df051
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/RecommendationsService.java
@@ -0,0 +1,164 @@
+/*****************************************************************************
+ * RecommendationsService.java
+ *****************************************************************************
+ * Copyright © 2012-2014 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+package org.videolan.vlc.gui.tv;
+
+import android.app.IntentService;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.os.Message;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.TaskStackBuilder;
+import android.util.Log;
+
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaDatabase;
+import org.videolan.vlc.MediaLibrary;
+import org.videolan.vlc.R;
+import org.videolan.vlc.gui.video.VideoPlayerActivity;
+import org.videolan.vlc.util.WeakHandler;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+
+
+/**
+ * An {@link IntentService} subclass for handling asynchronous task requests in
+ * a service on a separate handler thread.
+ * <p/>
+ * TODO: Customize class - update intent actions and extra parameters.
+ */
+public class RecommendationsService extends IntentService {
+
+ private static final String TAG = "VLC/RecommendationsService";
+ private static final int NUM_RECOMMANDATIONS = 10;
+
+ private static NotificationManager sNotificationManager;
+ private static MediaDatabase sMediaDatabase = MediaDatabase.getInstance();
+ private static Context sContext;
+
+ public RecommendationsService() {
+ super("RecommendationsService");
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ sContext = this;
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ if (intent != null) {
+ final String action = intent.getAction();
+ MediaLibrary.getInstance().addUpdateHandler(mHandler);
+ }
+ }
+ private static Notification buildRecommendation(Context context, Media movie)
+ throws IOException {
+
+ if (sNotificationManager == null) {
+ sNotificationManager = (NotificationManager)
+ sContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ Bundle extras = new Bundle();
+// if (mBackgroundUri != movie.getBackgroundUri()) {
+// extras.putString(EXTRA_BACKGROUND_IMAGE_URL, movie.getBackgroundUri());
+// }
+
+ // build the recommendation as a Notification object
+ Notification notification = new NotificationCompat.BigPictureStyle(
+ new NotificationCompat.Builder(sContext)
+ .setContentTitle(movie.getTitle())
+ .setContentText(movie.getDescription())
+ .setContentInfo("VLC")
+// .setSortKey("0.8")
+ .setPriority(7)
+// .setColor(Color.BLUE)
+ .setCategory("recommendation")
+ .setLargeIcon(sMediaDatabase.getPicture(sContext, movie.getLocation()))
+ .setSmallIcon(R.drawable.icon)
+ .setContentIntent(buildPendingIntent(movie))
+// .setExtras(extras))
+ ).build();
+
+ // post the recommendation to the NotificationManager
+ sNotificationManager.notify(0, notification);
+ sNotificationManager = null;
+ return notification;
+ }
+
+ private static PendingIntent buildPendingIntent(Media media) {
+
+ Intent intent = new Intent(sContext, VideoPlayerActivity.class);
+ intent.setAction(VideoPlayerActivity.PLAY_FROM_VIDEOGRID);
+ intent.putExtra("itemLocation", media.getLocation());
+ intent.putExtra("itemTitle", media.getTitle());
+ intent.putExtra("dontParse", false);
+ intent.putExtra("fromStart", false);
+ intent.putExtra("itemPosition", -1);
+
+ TaskStackBuilder stackBuilder = TaskStackBuilder.create(sContext);
+ stackBuilder.addParentStack(VideoPlayerActivity.class);
+ stackBuilder.addNextIntent(intent);
+
+ PendingIntent pi = stackBuilder.getPendingIntent(
+ 0, PendingIntent.FLAG_UPDATE_CURRENT);
+ return pi;
+ }
+
+ RecommendationsHandler mHandler = new RecommendationsHandler(this);
+
+ private static class RecommendationsHandler extends WeakHandler<RecommendationsService> {
+ public RecommendationsHandler(RecommendationsService owner) {
+ super(owner);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ ArrayList<Media> videoList = MediaLibrary.getInstance().getVideoItems();
+ ArrayList<Media> videos = new ArrayList<Media>(videoList.size());
+ Bitmap pic;
+ for (Media media : videoList){
+ pic = sMediaDatabase.getPicture(sContext, media.getLocation());
+ if (pic != null && pic.getByteCount() > 4 && media.getTime() == 0) {
+ videos.add(media);
+ }
+ }
+ if (!videos.isEmpty())
+ Collections.shuffle(videos);
+ videoList = null;
+ int size = Math.min(NUM_RECOMMANDATIONS, videos.size());
+ for (int i = 0 ; i < size ; ++i) {
+ try {
+ buildRecommendation(sContext, videos.get(i));
+ } catch (IOException e) {
+ Log.e(TAG, "failed notif for "+ videos.get(i).getTitle(), e);
+ }
+ }
+ }
+ }
+}
--
1.9.1
More information about the Android
mailing list