/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Modifications:
* -Connect to VLC server instead of media service
* -Listen for VLC status events
* -Schedule status updates for time at which current track is expected to end
*/
package tof.cv.mpp.widget;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;
import java.util.Random;
import tof.cv.mpp.InfoTrainActivity;
import tof.cv.mpp.R;
import tof.cv.mpp.Utils.DbAdapterConnection;
import tof.cv.mpp.WelcomeActivity;
/**
* Our data observer just notifies an update for all weather widgets when it
* detects a change.
*/
class CopyOfTrainDataProviderObserver extends ContentObserver {
private AppWidgetManager mAppWidgetManager;
private ComponentName mComponentName;
CopyOfTrainDataProviderObserver(AppWidgetManager mgr, ComponentName cn, Handler h) {
super(h);
mAppWidgetManager = mgr;
mComponentName = cn;
}
@Override
public void onChange(boolean selfChange) {
// The data has changed, so notify the widget that the collection view
// needs to be updated.
// In response, the factory's onDataSetChanged() will be called which
// will requery the
// cursor for the new data.
mAppWidgetManager.notifyAppWidgetViewDataChanged(
mAppWidgetManager.getAppWidgetIds(mComponentName),
R.id.weather_list);
}
}
/**
* The weather widget's AppWidgetProvider.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class CopyOfTrainWidgetProvider extends AppWidgetProvider {
public static String REFRESH_ACTION = "tof.cv.mpp.widget.action.REFRESH";
public static String UPDATE_ACTION = "tof.cv.mpp.widget.action.UPDATE";
private static Handler sWorkerQueue;
private static TrainDataProviderObserver sDataObserver;
String tid;
String fromTo;
String updateTime = "xx:xx";
public CopyOfTrainWidgetProvider() {
// Start the worker thread
HandlerThread sWorkerThread = new HandlerThread(
"TrainWidgetProvider-worker");
sWorkerThread.start();
sWorkerQueue = new Handler(sWorkerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// display each item in a single line
// txt.setText(txt.getText()+"Item "+System.getProperty("line.separator"));
}
};
}
@Override
public void onEnabled(Context context) {
// Register for external updates to the data to trigger an update of the
// widget. When using
// content providers, the data is often updated via a background
// service, or in response to
// user interaction in the main app. To ensure that the widget always
// reflects the current
// state of the data, we must listen for changes and update ourselves
// accordingly.
final ContentResolver r = context.getContentResolver();
if (sDataObserver == null) {
final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
final ComponentName cn = new ComponentName(context,
CopyOfTrainWidgetProvider.class);
sDataObserver = new TrainDataProviderObserver(mgr, cn, sWorkerQueue);
r.registerContentObserver(TrainDataProvider.CONTENT_URI, true,
sDataObserver);
}
}
@Override
public void onReceive(final Context ctx, Intent intent) {
final String action = intent.getAction();
super.onReceive(ctx, intent);
Log.i("", "***INTENT+" + intent.getAction());
if (action.equals(REFRESH_ACTION) || action.equals(UPDATE_ACTION)) {
// BroadcastReceivers have a limited amount of time to do work, so
// for this sample, we
// are triggering an update of the data on another thread. In
// practice, this update
// can be triggered from a background service, or perhaps as a
// result of user actions
// inside the main application.
sWorkerQueue.removeMessages(0);
sWorkerQueue.post(new Runnable() {
@Override
public void run() {
DbAdapterConnection mDbHelper = new DbAdapterConnection(ctx);
mDbHelper.open();
Cursor mSTOPCursor = mDbHelper.fetchAllWidgetStops();
if (mSTOPCursor.getCount() > 1) {
mSTOPCursor.moveToPosition(0);
tid = mSTOPCursor.getString(mSTOPCursor
.getColumnIndex(DbAdapterConnection.KEY_STOP_NAME));
fromTo = mSTOPCursor.getString(mSTOPCursor
.getColumnIndex(DbAdapterConnection.KEY_STOP_STATUS));
updateTime = mSTOPCursor.getString(mSTOPCursor
.getColumnIndex(DbAdapterConnection.KEY_STOP_LATE));
if (action.equals(REFRESH_ACTION)) {
/*
UtilsWeb.Vehicle v = UtilsWeb.getAPIvehicle(tid,ctx, 0);
if (v.getVehicleStops().getVehicleStop().size() > 1) {
mDbHelper.deleteAllWidgetStops();
updateTime = Utils.formatDateWidget(new Date());
mDbHelper.createWidgetStop(tid, "1",
updateTime, fromTo);
for (UtilsWeb.VehicleStop stop : v
.getVehicleStops().getVehicleStop()) {
mDbHelper.createWidgetStop(
stop.getStation(),
"" + stop.getTime(),
stop.getDelay(), stop.getStatus());
}
}*/
}
}
mDbHelper.close();
final ContentResolver r = ctx.getContentResolver();
final Cursor c = r.query(TrainDataProvider.CONTENT_URI,
null, null, null, null);
final int count = c.getCount();
// We disable the data changed observer temporarily since
// each of the updates
// will trigger an onChange() in our data observer.
if (sDataObserver != null)
r.unregisterContentObserver(sDataObserver);
for (int i = 0; i < count; ++i) {
final Uri uri = ContentUris.withAppendedId(
TrainDataProvider.CONTENT_URI, i);
final ContentValues values = new ContentValues();
values.put(DbAdapterConnection.KEY_STOP_TIME,
new Random().nextInt(100));
r.update(uri, values, null, null);
}
if (sDataObserver != null)
r.registerContentObserver(
TrainDataProvider.CONTENT_URI, true,
sDataObserver);
Message msg = new Message();
Bundle b = new Bundle();
b.putString("My Key", "My Value: ");
msg.setData(b);
sWorkerQueue.sendMessage(msg);
}
});
}
final AppWidgetManager mgr = AppWidgetManager.getInstance(ctx);
final ComponentName cn = new ComponentName(ctx,
CopyOfTrainWidgetProvider.class);
Intent detailIntent = new Intent(ctx, WelcomeActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0,
detailIntent, PendingIntent.FLAG_UPDATE_CURRENT);
final RemoteViews rv = new RemoteViews(ctx.getPackageName(),
R.layout.widget_layout);
rv.setOnClickPendingIntent(R.id.icon, pendingIntent);
mgr.updateAppWidget(mgr.getAppWidgetIds(cn), rv);
mgr.notifyAppWidgetViewDataChanged(mgr.getAppWidgetIds(cn),
R.id.weather_list);
// Bind the click intent for the refresh button on the widget
final Intent refreshIntent = new Intent(ctx, CopyOfTrainWidgetProvider.class);
refreshIntent.setAction(CopyOfTrainWidgetProvider.REFRESH_ACTION);
final PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(
ctx, 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.refresh, refreshPendingIntent);
Log.i("", "HOPE");
int[] ids = mgr.getAppWidgetIds(
new ComponentName(ctx,
TrainAppWidgetProvider.class));
onUpdate(ctx, AppWidgetManager.getInstance(ctx), ids);
// else if (action.equals(CLICK_ACTION)) {
// Show a toast
// final int appWidgetId =
// intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
// AppWidgetManager.INVALID_APPWIDGET_ID);
// final String city = intent.getStringExtra(EXTRA_CITY_ID);
// Toast.makeText(ctx, city, Toast.LENGTH_SHORT).show();
// }
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Log.i("", "UPDATE");
DbAdapterConnection mDbHelper = new DbAdapterConnection(context);
mDbHelper.open();
Cursor mSTOPCursor = mDbHelper.fetchAllWidgetStops();
if (mSTOPCursor.getCount() > 1) {
mSTOPCursor.moveToPosition(0);
tid = mSTOPCursor.getString(mSTOPCursor
.getColumnIndex(DbAdapterConnection.KEY_STOP_NAME));
fromTo = mSTOPCursor.getString(mSTOPCursor
.getColumnIndex(DbAdapterConnection.KEY_STOP_STATUS));
updateTime = mSTOPCursor.getString(mSTOPCursor
.getColumnIndex(DbAdapterConnection.KEY_STOP_LATE));
}
mDbHelper.close();
// Update each of the widgets with the remote adapter
for (int appWidgetId : appWidgetIds) {
// for (int i = 0; i < appWidgetIds.length; ++i)
// Specify the service to provide data for the collection widget.
// Note that we need to
// embed the appWidgetId via the data otherwise it will be ignored.
final Intent intent = new Intent(context, TrainWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
final RemoteViews rv = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
rv.setRemoteAdapter(appWidgetId, R.id.weather_list, intent);
if (tid != null) {
Log.i("", "tid2: " + tid + " (" + updateTime + ")");
rv.setTextViewText(R.id.widget_title, fromTo);
rv.setTextViewText(R.id.widget_sub, tid + " (" + updateTime
+ ")");
}
// Set the empty view to be displayed if the collection is empty. It
// must be a sibling
// view of the collection view.
rv.setEmptyView(R.id.weather_list, R.id.empty_view);
// Bind the click intent for the refresh button on the widget
final Intent refreshIntent = new Intent(context,
CopyOfTrainWidgetProvider.class);
refreshIntent.setAction(CopyOfTrainWidgetProvider.REFRESH_ACTION);
final PendingIntent refreshPendingIntent = PendingIntent
.getBroadcast(context, 0, refreshIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.refresh, refreshPendingIntent);
// Bind the click intent for the icon button on the widget
Intent detailIntent = new Intent(context, WelcomeActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
detailIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (tid != null) {
detailIntent = new Intent(context, InfoTrainActivity.class);
detailIntent.putExtra("fromto", fromTo);
detailIntent.putExtra("Name", tid);
pendingIntent = PendingIntent.getActivity(context, 0,
detailIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
rv.setOnClickPendingIntent(R.id.icon, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, rv);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}