CatalogService.java

package com.spawnlabs.endpoint.gamestick.player.service.catalog; 
 
import android.app.Service; 
import android.content.Context; 
import android.content.Intent; 
import android.net.ConnectivityManager; 
import android.os.AsyncTask; 
import android.os.Handler; 
import android.os.HandlerThread; 
import android.os.IBinder; 
import android.os.Looper; 
import android.os.Message; 
import android.util.Log; 
import com.spawnlabs.endpoint.gamestick.player.Constants; 
import com.spawnlabs.endpoint.gamestick.player.R; 
import com.spawnlabs.endpoint.gamestick.player.db.CatalogDatabase; 
import com.spawnlabs.endpoint.gamestick.player.model.catalog.CatalogPackage; 
import com.spawnlabs.endpoint.gamestick.player.model.catalog.Game; 
import com.spawnlabs.endpoint.gamestick.player.service.spawnrest.SpawnRestException; 
import com.spawnlabs.endpoint.gamestick.player.util.CatalogSeedUtil; 
import com.spawnlabs.endpoint.gamestick.player.util.HttpUtil; 
import com.spawnlabs.endpoint.gamestick.player.util.JsonUtil; 
 
import java.io.IOException; 
import java.util.Calendar; 
import java.util.GregorianCalendar; 
import java.util.List; 
import java.util.Map; 
import java.util.TimeZone; 
 
import static android.os.Process.THREAD_PRIORITY_BACKGROUND; 
 
/** 
 * 
 * 
 */ 
public class CatalogService 
        extends Service { 
 
    private static final String TAG = "GS-" + CatalogService.class.getSimpleName(); 
 
    public static final String PATH_GENRES = "/genres"; 
    public static final String PATH_GAMES = "/games"; 
    private static final String QUERY_DETAIL = "detail=true"; 
 
    private static final long ten_min = 600000; 
 
    private static final String ACTION_SCHEDULE_CHECK = "schedule"; 
 
    private CatalogServiceHandler catalogServiceHandler; 
    private String catalogServiceGamesUrl; 
    private String catalogServiceGenresUrl; 
 
 
    // ================================================================================================================================================================ 
    // Lifecycle / Service 
    // ================================================================================================================================================================
@Override
public IBinder onBind(Intent intent) { return null; }
@Override
public void onCreate() { String serviceUrl = getString(R.string.spawnRestApirul); catalogServiceGamesUrl = serviceUrl + PATH_GAMES; catalogServiceGenresUrl = serviceUrl + PATH_GENRES; // Handler ============================================================== HandlerThread thread = new HandlerThread(getClass().getName() + "-PollThread", THREAD_PRIORITY_BACKGROUND); thread.start(); catalogServiceHandler = new CatalogServiceHandler(thread.getLooper()); // Check catalog seed =================================================== if (!CatalogSeedUtil.isSeedReady()) { // The seed files are missing. Try to get them from - tho, strictly-speaking, // this is not a scenario we support. This is more just to help in dev environment. Log.w(TAG, "Seed files missing. Updating catalog..."); forceUpdateCatalog(); } // Start update timer =================================================== scheduleNextTimeCheck(); }
@Override
public int onStartCommand(Intent intent, int flags, int startId) { String intentExtra = intent.getStringExtra(Constants.KEY_ACTION); Log.v(TAG, "onStartCommand() intent: " + intentExtra); if (ACTION_SCHEDULE_CHECK.equals(intentExtra)) { scheduleNextTimeCheck(); } else if (Constants.ACTION_INIT.equals(intentExtra)) { // Only force an update check on *later* calls to startService(). Not the init one. // So do nothing here; we're just starting it up. } else /*if (all other cases / null intent)*/ { forceUpdateCatalog(); } return START_STICKY; } // ================================================================================================================================================================ // Internal methods // ================================================================================================================================================================
private void scheduleNextTimeCheck() { catalogServiceHandler.sendEmptyMessageDelayed(CatalogServiceHandler.CATALOG_SERVICE_HANDLER_CHECK_FOR_UPDATE, ten_min); }
private void forceUpdateCatalog() { Log.i(TAG, "forceUpdateCatalog()"); catalogServiceHandler.sendEmptyMessage(CatalogServiceHandler.CATALOG_SERVICE_HANDLER_FORCE_UPDATE); }
/** * Call only from within Handler */ private void updateCatalog() { Log.v(TAG, "updateCatalog()"); new GetCatalogAsyncTask().execute(); }
private boolean isWifiConnected() { return ((ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE)).getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected(); } // ============================================================================================================================================================ // Inner classes // ============================================================================================================================================================
class CatalogServiceHandler extends Handler { static final int CATALOG_SERVICE_HANDLER_CHECK_FOR_UPDATE = 0; static final int CATALOG_SERVICE_HANDLER_FORCE_UPDATE = 1;
public CatalogServiceHandler(Looper looper) { super(looper); }
@Override
public void handleMessage(Message msg) { switch (msg.what) { case (CATALOG_SERVICE_HANDLER_CHECK_FOR_UPDATE): try { if (timeIsGoodForUpdate()) { updateCatalog(); } } finally { // Even if something fails, trigger the next poll scheduleNextTimeCheck(); } break; case (CATALOG_SERVICE_HANDLER_FORCE_UPDATE): updateCatalog(); break; } }
/** * Call only on worker thread */ private boolean timeIsGoodForUpdate() { // Create time markers every time we check. TimeZone cst = TimeZone.getTimeZone("CST"); Calendar twoAM = new GregorianCalendar(cst); twoAM.set(GregorianCalendar.HOUR_OF_DAY, 2); twoAM.set(GregorianCalendar.MINUTE, 0); twoAM.set(GregorianCalendar.SECOND, 0); Calendar twoTenAM = new GregorianCalendar(cst); twoTenAM.set(GregorianCalendar.HOUR_OF_DAY, 2); twoTenAM.set(GregorianCalendar.MINUTE, 10); twoTenAM.set(GregorianCalendar.SECOND, 0); Calendar now = Calendar.getInstance(cst); return now.after(twoAM) && now.before(twoTenAM); } }
private class GetCatalogAsyncTask extends AsyncTask<Void, Integer, CatalogPackage> { private final String TAG = "GS-" + CatalogService.GetCatalogAsyncTask.class.getSimpleName();
@Override
protected CatalogPackage doInBackground(Void... params) { if (!isWifiConnected()) { Log.e(TAG, "Wifi not connected. Will try again later.");// todo -EJT decide Not sure how this works with OOBE. startService(new Intent(CatalogService.this, CatalogService.class).putExtra(Constants.KEY_ACTION, ACTION_SCHEDULE_CHECK)); return null; } // --- games // Get json Log.v(TAG, "Getting catalog..."); String jsonCatalog = getGamesJsonFromCatalogService(); if (jsonCatalog == null) { return null; } // make games from json List<Game> games = JsonUtil.gamesFrom(jsonCatalog); if (games != null) {// if that succeeds... // write json to seed file Log.v(TAG, "Writing json to catalog seed file"); try { CatalogSeedUtil.overwriteJsonCatalogSeed(jsonCatalog); } catch (IOException e) { Log.e(TAG, "Exception writing new Game Catalog to file.", e); } } else { Log.e(TAG, "Exception updating Catalog games. (games = null)"); return null; } // --- genres // Get json Log.v(TAG, "Getting genres..."); String jsonGenres = getGenresJsonFromCatalogService(); // Get genres from json Map<String, String[]> genres = JsonUtil.genresFrom(jsonGenres); // make persistable string from json String genresString = CatalogPackage.staticGetGenresAsString(genres.keySet()); int size = genres.keySet().size(); if (size != 0 && genresString.split(",").length == size) {// if that succeeds... // write json to seed file Log.v(TAG, "Writing json to genre seed file"); try { CatalogSeedUtil.overwriteJsonGenreSeed(jsonGenres); } catch (IOException e) { Log.e(TAG, "Exception writing new genre list to file.", e); } } else { Log.e(TAG, "Exception updating Catalog genres. " + size + " : " + genresString.split(",").length); return null; } CatalogPackage catalogPackage = new CatalogPackage(games, genres); // Update the CatalogDatabase CatalogDatabase.getCatalogDatabase().repopulateDatabase(catalogPackage); return catalogPackage; }
@Override
protected void onPostExecute(CatalogPackage catalogPackage) { }
private String getGamesJsonFromCatalogService() { try { return HttpUtil.httpGet(catalogServiceGamesUrl + "?" + QUERY_DETAIL); } catch (SpawnRestException e) { Log.wtf(TAG, "Failed to get games from Catalog Service.", e); return null; } }
private String getGenresJsonFromCatalogService() { try { return HttpUtil.httpGet(catalogServiceGenresUrl); } catch (SpawnRestException e) { Log.wtf(TAG, "Failed to get genres from Catalog Service.", e); return null; } } } }