/* Copyright by Stefan Lischke a.k.a Mister Schtief started in 2010 in Berlin Germany This file is part of PartyBolle. PartyBolle 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. PartyBolle 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 PartyBolle. If not, see <http://www.gnu.org/licenses/>. */ package org.schtief.partybolle.foursquare; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import org.schtief.partybolle.InfoActivity; import org.schtief.partybolle.PartyBolle; import org.schtief.partybolle.R; import org.schtief.util.json.JSONArray; import org.schtief.util.json.JSONObject; import org.schtief.util.json.JSONTokener; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; import com.joelapenna.foursquare.Foursquare; import com.joelapenna.foursquare.Foursquare.Location; import com.joelapenna.foursquare.types.CheckinResult; import com.joelapenna.foursquare.types.Venue; public class AutoCheckinService extends Service implements LocationListener{ private static final String LOG_TAG = "AutoCheckinService"; public final static int STATE_UNKNOWN=0; public final static int STATE_RUNNING=1; public final static int STATE_STOPPED=2; public final static int STATE_STANDSTILL=3; SharedPreferences preferences; private static AutoCheckinService instance = null; protected LocationManager myLocationManager = null; private int state = STATE_UNKNOWN; private Calendar started = null; private Foursquare foursquare; private List<Venue> venues; private List<Checkin> checkins; private long lastCheckin=0; private Venue lastVenue; private boolean inited; NotificationManager notificationManager; Notification notification; private int notificationId=1; public class Checkin{ public Venue venue; public CheckinResult checkinResult; public Checkin(Venue lastVenue, CheckinResult checkinResult2) { venue=lastVenue; checkinResult=checkinResult2; } } public static synchronized AutoCheckinService getInstance() { return instance; } public AutoCheckinService() { // Log.i(LOG_TAG,"AutoCheckinService intantiated "+toString()); instance = this; foursquare = new Foursquare(Foursquare.createHttpApi( "api.foursquare.com", false)); venues = new ArrayList<Venue>(); checkins = new ArrayList<Checkin>(); } /** not using ipc... dont care about this method */ public IBinder onBind(Intent intent) { return null; } @Override public void onStart(Intent intent,int i) { super.onStart(intent, i); if(state==STATE_RUNNING){ log(Log.INFO, "PartyBolle AutoCheckinService looft schon"); return; } notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // init the service here _startService(); state=STATE_RUNNING; started=Calendar.getInstance(); started.add(Calendar.HOUR, 1); log(Log.INFO, "PartyBolle AutoCheckinService jestartet"); loadFavorites(); } @Override public void onDestroy() { super.onDestroy(); // log(Log.INFO, "onDestroy "+toString()); _shutdownService(); state=STATE_STOPPED; instance=null; } private void _startService() { preferences = PreferenceManager.getDefaultSharedPreferences(this); this.myLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); final long MINIMUM_DISTANCECHANGE_FOR_UPDATE = 300; // in Meters final long MINIMUM_TIME_BETWEEN_UPDATE = 30000; // in Milliseconds this.myLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MINIMUM_TIME_BETWEEN_UPDATE, MINIMUM_DISTANCECHANGE_FOR_UPDATE, this); //static notification Intent notificationIntent = new Intent(this,AutoCheckinActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); // the next two lines initialize the Notification, using the configurations above notification = new Notification(R.drawable.bolle_25, "PartyBolle Service", System.currentTimeMillis()); notification.setLatestEventInfo(getApplicationContext(), "PartyBolle Service", "Klick Stop oderInfos", contentIntent); notification.flags |= Notification.FLAG_NO_CLEAR; notification.flags |= Notification.FLAG_ONGOING_EVENT; notificationManager.notify(1, notification); } private void _shutdownService() { this.myLocationManager.removeUpdates(this); log(Log.INFO,"PartyBolle AutoCheckinService jestopt"); notificationManager.cancel(1); } private void log(int level, String message) { Log.println(level, LOG_TAG, message); Toast.makeText(AutoCheckinService.this, message,Toast.LENGTH_LONG).show(); } public int getState() { return state; } public Calendar getStarted() { return started; } public void onLocationChanged(android.location.Location location) { Log.i(LOG_TAG, "onLocationChanged "+location.getLatitude()+":"+location.getLongitude()); float minDist = 300; Venue minVenue = null; for (Venue venue : venues) { android.location.Location loc = new android.location.Location(LocationManager.GPS_PROVIDER); loc.setLatitude(Double.parseDouble(venue.getGeolat())); loc.setLongitude(Double.parseDouble(venue.getGeolong())); float dist = location.distanceTo(loc); if(dist<minDist){ minDist=dist; minVenue = venue; } } if( null != minVenue && (null==lastVenue || !lastVenue.getId().equals(minVenue.getId())) && (System.currentTimeMillis()-lastCheckin > 1000*60*3)){ log(Log.INFO,"PartyBolle AutoCheckin "+minVenue.getName()+" distance "+minDist); if(!init()) return; try { final CheckinResult checkinResult = foursquare.checkin(minVenue.getId(), null,LocationUtils.createFoursquareLocation(location), null, false, false); lastVenue = minVenue; lastCheckin = System.currentTimeMillis(); Checkin c = new Checkin(lastVenue,checkinResult); checkins.add(0,c); log(Log.INFO, "PartyBolle checkin: "+checkinResult.getMessage()); notifyCheckin(c); } catch (Exception e) { CheckinResult checkinResult = new CheckinResult(); checkinResult.setMessage("PartyBolle Could not Checkin "+e.getMessage()); Checkin c = new Checkin(lastVenue,checkinResult); checkins.add(0,c); notifyCheckin(c); log(Log.ERROR,"PartyBolle Could not Checkin "+e.getMessage()); } } } private void notifyCheckin(Checkin checkin) { int icon = R.drawable.foursquare_28; // icon from resources CharSequence tickerText = checkin.venue.getName(); // ticker-text long when = System.currentTimeMillis(); // notification time Context context = getApplicationContext(); // application Context CharSequence contentTitle = "PartyBolle AutoCheckin"; // expanded message title CharSequence contentText = checkin.checkinResult.getMessage(); notificationId++; Intent notificationIntent = new Intent(this,AutoCheckinActivity.class); notificationIntent.putExtra(AutoCheckinActivity.EXTRA_NOTIFICATION_ID, notificationId); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); // the next two lines initialize the Notification, using the configurations above Notification notification = new Notification(icon, tickerText, when); notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); notificationManager.notify(notificationId, notification); } public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } private class LoadFavoritesThread extends Thread { @Override public void run() { venues.clear(); loadFavs(); } } public void loadFavorites() { new LoadFavoritesThread().start(); } public Venue getVenue(String id){ try { return foursquare.venue(id, new Location("52.4", "13.45")); } catch (Exception e) { Log.e(PartyBolle.LOG_TAG,"could not load venue "+id,e); return null; } } private void loadFavs() { try { FileInputStream fis = instance.openFileInput("favorites"); JSONObject jsonObject = new JSONObject(new JSONTokener( new InputStreamReader(fis,"ISO-8859-1"))); JSONArray favs = jsonObject.getJSONArray("favs"); for (int i = 0; i < favs.length(); i++) { JSONObject fav = favs.getJSONObject(i); //foursquare oder event? if("foursquare".equals(fav.getString("type"))){ Log.i(PartyBolle.LOG_TAG," favorite foursquare "+fav.getString("id")); Venue venue = getVenue(fav.getString("id")); if(null!=venue){ venues.add(venue); } } } } catch (Exception e) { Log.e(LOG_TAG, "coud not load favorites ",e); log(Log.ERROR,"coud not load favorites "+e.getClass().getName()+":"+e.getMessage()); } } public boolean init(){ if(inited) return true; String username = preferences.getString("foursquare_name", ""); String password = preferences.getString("foursquare_password", ""); if(null==username || username.length()==0 ||null==password|| password.length()==0) { log(Log.INFO,"PartyBolle foursquare nich konfijuriert"); return false; } else { foursquare.setCredentials(username, password); if (foursquare.hasLoginAndPassword()) { log(Log.INFO,"PartyBolle injeloggt"); inited=true; return true; } else { log(Log.INFO,"PartyBolle login jefailed"); return false; } } } public List<Checkin> getCheckins() { return checkins; } }