/*
* Sonet - Android Social Networking Widget
* Copyright (C) 2009 Bryan Emmanuel
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Bryan Emmanuel piusvelte@gmail.com
*/
package com.piusvelte.sonet;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.RemoteViews;
import com.piusvelte.eidos.Eidos;
import com.piusvelte.sonet.loader.SMSLoader;
import com.piusvelte.sonet.loader.StatusesLoader;
import com.piusvelte.sonet.provider.Statuses;
import com.piusvelte.sonet.provider.WidgetAccounts;
import com.piusvelte.sonet.provider.Widgets;
import java.util.ArrayList;
import java.util.HashMap;
import static com.piusvelte.sonet.Sonet.ACTION_REFRESH;
import static com.piusvelte.sonet.Sonet.SMS_RECEIVED;
public class SonetService extends Service {
private static final String TAG = "SonetService";
public final static HashMap<Integer, StatusesLoader> mStatusesLoaders = new HashMap<>();
public final ArrayList<SMSLoader> mSMSLoaders = new ArrayList<>();
public AlarmManager mAlarmManager;
public ConnectivityManager mConnectivityManager;
public String mNotify = null;
public int mStartId = Sonet.INVALID_SERVICE;
@Override
public void onCreate() {
super.onCreate();
// handle version changes
int currVer = 0;
try {
currVer = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
if (!sp.contains(getString(R.string.key_version)) || (currVer > sp.getInt(getString(R.string.key_version), 0))) {
sp.edit().putInt(getString(R.string.key_version), currVer).apply();
Eidos.requestBackup(this);
}
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mConnectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
// check the instant upload settings
startService(new Intent(this, SonetUploader.class));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mStartId = startId;
start(intent);
return START_REDELIVER_INTENT;
}
@Override
public void onStart(Intent intent, int startId) {
mStartId = startId;
start(intent);
}
private void start(Intent intent) {
if (intent != null) {
String action = intent.getAction();
if (BuildConfig.DEBUG) Log.d(TAG, "action:" + action);
if (ACTION_REFRESH.equals(action)) {
if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS)) {
putValidatedUpdates(intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS),
1);
} else if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
putValidatedUpdates(new int[] { intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID) },
1);
} else if (intent.getData() != null) {
putValidatedUpdates(new int[] { Integer.parseInt(intent.getData().getLastPathSegment()) },
1);
} else {
putValidatedUpdates(null, 0);
}
} else if (SMS_RECEIVED.equals(action)) {
// parse the sms, and notify any widgets which have sms enabled
Bundle bundle = intent.getExtras();
Object[] pdus = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage msg = SmsMessage.createFromPdu((byte[]) pdus[i]);
SMSLoader smsLoader = new SMSLoader(this);
mSMSLoaders.add(smsLoader);
smsLoader.execute(msg);
}
} else {
// this might be a widget update from the widget refresh button
int appWidgetId;
try {
appWidgetId = Integer.parseInt(action);
putValidatedUpdates(new int[] { appWidgetId }, 1);
} catch (NumberFormatException e) {
Log.d(TAG, "unknown action:" + action);
}
}
}
}
public void putValidatedUpdates(int[] appWidgetIds, int reload) {
int[] awi = Sonet.getWidgets(getApplicationContext(), AppWidgetManager.getInstance(getApplicationContext()));
if ((appWidgetIds != null) && (appWidgetIds.length > 0)) {
// check for phantom widgets
for (int appWidgetId : appWidgetIds) {
// About.java will send an invalid appwidget id
if ((appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) || Sonet.arrayContains(awi, appWidgetId)) {
putNewUpdate(appWidgetId, reload);
} else {
// remove phantom widgets
getContentResolver().delete(Widgets.getContentUri(this),
Widgets.WIDGET + "=?",
new String[] { Integer.toString(appWidgetId) });
getContentResolver().delete(WidgetAccounts.getContentUri(this),
WidgetAccounts.WIDGET + "=?",
new String[] { Integer.toString(appWidgetId) });
getContentResolver().delete(Statuses.getContentUri(this),
Statuses.WIDGET + "=?",
new String[] { Integer.toString(appWidgetId) });
}
}
} else if ((awi != null) && (awi.length > 0)) {
for (int appWidgetId : awi) {
putNewUpdate(appWidgetId, reload);
}
}
}
protected void putNewUpdate(int widget, int reload) {
// if the widget is already loading, don't load another
if (mStatusesLoaders.isEmpty()
|| !mStatusesLoaders.containsKey(widget)
|| (reload == 1 && mStatusesLoaders.get(widget).cancel(true))) {
StatusesLoader loader = new StatusesLoader(this);
mStatusesLoaders.put(widget, loader);
loader.execute(widget, reload);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
if (!mStatusesLoaders.isEmpty()) {
for (StatusesLoader statusesLoader : mStatusesLoaders.values()) {
statusesLoader.cancel(true);
}
mStatusesLoaders.clear();
}
if (!mSMSLoaders.isEmpty()) {
for (SMSLoader smsLoader : mSMSLoaders) {
smsLoader.cancel(true);
}
mSMSLoaders.clear();
}
super.onDestroy();
}
public void buildWidgetButtons(Integer appWidgetId) {
final String widget = Integer.toString(appWidgetId);
// Push update for this widget to the home screen
// wrap RemoteViews for backward compatibility
RemoteViews views = new RemoteViews(getPackageName(), R.layout.widget);
views.setOnClickPendingIntent(R.id.button_post, PendingIntent.getActivity(this,
0,
new Intent(this, SonetCreatePost.class)
.setData(Uri.withAppendedPath(Widgets.getContentUri(this), widget)),
0));
views.setOnClickPendingIntent(R.id.button_configure, PendingIntent
.getActivity(this, 0, About.createIntent(this, About.DRAWER_SETTINGS), 0));
views.setOnClickPendingIntent(R.id.button_refresh, PendingIntent
.getService(this, 0, new Intent(this, SonetService.class).setAction(widget), 0));
final AppWidgetManager mgr = AppWidgetManager.getInstance(this);
try {
final Intent intent = new Intent(this, SonetRemoteViewsService.class)
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
views.setRemoteAdapter(appWidgetId, R.id.messages, intent);
views.setEmptyView(R.id.messages, R.id.empty_messages);
// Bind a click listener template for the contents of the message list
final Intent onClickIntent = new Intent(this, SonetComments.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP)
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
onClickIntent.setData(Uri.parse(onClickIntent.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent onClickPendingIntent = PendingIntent
.getActivity(this,
0,
onClickIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
views.setPendingIntentTemplate(R.id.messages, onClickPendingIntent);
} catch (NumberFormatException e) {
Log.e(TAG, e.toString());
} catch (IllegalArgumentException e) {
Log.e(TAG, e.toString());
}
mgr.updateAppWidget(appWidgetId, views);
mgr.notifyAppWidgetViewDataChanged(appWidgetId, R.id.messages);
}
}