Android Open Source - Gamework Game Service






From Project

Back to project page Gamework.

License

The source code is released under:

Apache License

If you think the Android project Gamework listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package cz.robyer.gamework.game;
/*w w w.j a  va  2  s.  c  o m*/
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import cz.robyer.gamework.constants.Constants;
import cz.robyer.gamework.game.GameEvent.EventType;
import cz.robyer.gamework.scenario.Scenario;
import cz.robyer.gamework.scenario.parser.XmlScenarioParser;
import cz.robyer.gamework.utils.Log;
import cz.robyer.gamework.utils.Utils;

/**
 * Main service object representing whole game.
 * @author Robert P?sel
 */
public abstract class GameService extends Service implements GameEventListener, LocationListener {    
  private static final String TAG = GameService.class.getSimpleName();
  
  /** signalize that instance of GameService exists */
  private static boolean running;
  private static GameService instance;
  
  private Scenario scenario;
  private GameStatus status = GameStatus.GAME_NONE;
  protected final GameHandler gameHandler = new GameHandler(this);
  
  private Timer timer;
  private long start, time;
  
  private LocationManager locationManager;
  private Location location;
  
  /** help variable for incrementing time value. */
  private long lastTime;
  
  /**
   * Shortcut for registering {@link GameEventListener}s.
   */
  public final boolean registerListener(GameEventListener listener) {
      return gameHandler.addListener(listener);
    }
    
  /**
   * Shortcut for unregistering {@link GameEventListener}s.
   */
    public final boolean unregisterListener(GameEventListener listener) {
      return gameHandler.removeListener(listener);
    }
    
    @Override
    public final void onCreate() {
        // The service is being created      
      Log.i(TAG, "onCreate()");
      
      instance = this;
      running = true;
      locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    }
      
    @Override
    public final int onStartCommand(Intent intent, int flags, int startId) {
      Log.i(TAG, "onStartCommand()");

    // TODO: allow starting new game also when in GAME_WON, GAME_LOST status?
      if (status != GameStatus.GAME_NONE) {
        // game is already running, do nothing
        Log.i(TAG, "Game is already running");
        // inform about game was already started
        onGameStart(false, intent);
        return 0;        
      }
      
      status = GameStatus.GAME_LOADING;
      scenario = loadScenario(intent);
      if (scenario == null) {
        Log.e(TAG, "Scenario wasn't loaded");
        status = GameStatus.GAME_NONE;
        return 0;
      }
      
      Log.i(TAG, "Scenario '" + scenario.getInfo().title + "' was loaded");

      scenario.setHandler(gameHandler);
      registerListener(this);
      
      start = System.currentTimeMillis();
      lastTime = SystemClock.uptimeMillis();
      time = 0;
      
      status = GameStatus.GAME_WAITING;
            
      // make this service foreground and show notification
      startForeground(Constants.NOTIFICATION_GAMEPLAY, getGameNotification());
      
      // register getting location updates
      startLocationUpdates();
    
      // inform about game starting
    onGameStart(true, intent);
      
      // service is starting, due to a call to startService()
        return START_NOT_STICKY; // or START_REDELIVER_INTENT?
    }
    
    /**
     * Default method for load scenario from assets.
     * @param intent which was used with startService
     * @return scenario or null if error occurs
     */
    protected Scenario loadScenario(Intent intent) {
      String filename = intent.getStringExtra("filename");
      Scenario scenario = XmlScenarioParser.fromAsset(getApplicationContext(), filename);
    return scenario;
  }

  @Override
    public final IBinder onBind(Intent intent) {
      Log.i(TAG, "onBind()");
      return null; // we don't support binding
    }

    @Override
    public final void onDestroy() {
        // service is no longer used and is being destroyed
      Log.i(TAG, "onDestroy()");
      
      running = false;
      instance = null;
      
      gameHandler.clearListeners();
      stopAllUpdates();
    }
    
    /**
     * Returns info whether instance of service exists or not.
     * @return true if instance of GameService exists, false otherwise.
     */
    public static final boolean isRunning() {
    return running;
  }
    
    /**
     * Returns last saved location of user.
     */
    public final Location getLocation() {
      return location;
    }
    
    /**
     * Returns actual {@link Scenario}.
     */
    public final Scenario getScenario() {
      return scenario;
    }

    /**
     * Returns time when game started.
     * @return
     */
    public final long getStartTime() {
      return start;
    }
    
    /**
     * Returns actual game time in milliseconds.
     */
    public final long getTime() {
      return time;
    }
    
    /**
     * Returns actual status of game.
     */
    public final GameStatus getStatus() {
      return status;
    }
    
    /**
     * Returns instance of this game.
     */
    public static final GameService getInstance() {
      return instance;
    }
    
    /**
   * Calculate and update actual game time.
   * @return time - actual game time
   */
  private final long updateGameTime() {
    long now = SystemClock.uptimeMillis();
    time += now - lastTime;
    lastTime = now;
    return time;
  }
  
  /**
   * Gets and broadcasts new user location.
   */
    @Override
    public final void onLocationChanged(Location location) {
      this.location = location;
      gameHandler.broadcastEvent(new GameEvent(EventType.UPDATED_LOCATION, location));
    }

  @Override public final void onProviderDisabled(String provider) {}
  @Override public final void onProviderEnabled(String provider) {}
  @Override public final void onStatusChanged(String provider, int status, Bundle extras) {}
  
  /**
   * Returns game notification to show when game is running.
   */
  protected abstract Notification getGameNotification();
  
  /**
   * This is called after receiving new startService intent.
   * @param starting means that {@link GameService} was just started for first time (true)
   * or that new intent was received when game is running (false).
   * @param intent which was used when starting this service
   * @see #startService(Intent)
   */
  protected abstract void onGameStart(boolean starting, Intent intent);
  
  /**
   * This method is called every time when there was new event received.
   * @param event
   */
  protected abstract void onEvent(GameEvent event);
  
  /**
   * Show or update this service's notification.
   * This method uses {@link #getGameNotification()} to get notification.
   */
  public final void refreshNotification(boolean foreground) {
    if (foreground) {
      startForeground(Constants.NOTIFICATION_GAMEPLAY, getGameNotification());
    } else {
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
         mNotificationManager.notify(Constants.NOTIFICATION_GAMEPLAY, getGameNotification());
      }
  }
  
  /**
   * Starts requesting location updates.
   */
  private final void startLocationUpdates() {
    if (locationManager != null) {        
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
      }
  }
  
  /**
   * Creates and starts timer (if not exists already) for getting time updates.
   */
  private final void startTimeUpdates() {
    if (timer == null) {
        timer = new Timer();
          timer.schedule(new TimerTask() {
            @Override
            public void run() {
              long time = updateGameTime();
              gameHandler.broadcastEvent(new GameEvent(EventType.UPDATED_TIME, time));
            }
          }, 1000, 1000);
    }
  }
  
  /**
   * Stops location and time updates.
   */
  private final void stopAllUpdates() {
    if (locationManager != null)
      locationManager.removeUpdates(this);
    
    if (timer != null) {
      timer.cancel();
      timer.purge();
      timer = null;
    }
  }

  /**
   * Received game event handling.
   */
    @Override
  public final void receiveEvent(GameEvent event) {
      
      switch (event.type) {
      case GAME_START:
        if (status != GameStatus.GAME_WAITING && status != GameStatus.GAME_PAUSED) {
          Log.w(TAG, "Game can't be started in '" + status + "' state. Only GAME_WAITING and GAME_PAUSED allowed");
          break;
        }
        lastTime = SystemClock.uptimeMillis();
        
        startTimeUpdates();
          
          // requesting location updates was already done if game service is in waiting state
          if (status != GameStatus.GAME_WAITING)
            startLocationUpdates();
          
          status = GameStatus.GAME_RUNNING;
        break;
      
      case GAME_PAUSE:
      case GAME_WIN:
      case GAME_LOSE:
        if (status != GameStatus.GAME_RUNNING) {
          Log.w(TAG, "Game can't be paused/won/lost in '" + status + "' state. Only GAME_RUNNING allowed");
          break;
        }        
        stopAllUpdates();

        if (event.type == EventType.GAME_WIN)
          status = GameStatus.GAME_WON;
        else if (event.type == EventType.GAME_LOSE)
          status = GameStatus.GAME_LOST;
        else
          status = GameStatus.GAME_PAUSED;
        
           break;
           
      case GAME_QUIT:
        stopSelf();
        status = GameStatus.GAME_NONE;
        break;
           
      case UPDATED_LOCATION:
        if (status == GameStatus.GAME_RUNNING && location != null) {
          Location loc = event.value != null ? (Location)event.value : location;
          scenario.onLocationUpdate(loc.getLatitude(), loc.getLongitude());
        }
        break;
        
      case UPDATED_TIME:
        if (status == GameStatus.GAME_RUNNING) {
          long t = event.value != null ? (Long)event.value : time;
          scenario.onTimeUpdate(t);
        }
        break;
        
      case CUSTOM:
        if (status == GameStatus.GAME_RUNNING && event.value != null)
          scenario.onCustomEvent(event.value);
        break;
        
      case SCANNED_CODE:
        if (status == GameStatus.GAME_RUNNING && event.value != null)
          scenario.onScanned(event.value);
        break;

      default:
        break;
      }
      
      onEvent(event);
  }
    
    /**
     * Starts scanner activity or show alert dialog asking for download scanner application first.
     * @param activity which will wait for result.
     * @see GameService#onActivityResult(int, int, Intent)
     */
    public void startScanner(final Activity activity) {
      Intent intent = new Intent(Constants.SCANNER_SCAN);

      if (Utils.isIntentCallable(getApplicationContext(), intent)) {
        activity.startActivityForResult(intent, Constants.SCANNER_CODE);
      } else {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setMessage(Constants.SCANNER_MISSING)
          .setCancelable(true)
          .setPositiveButton("Google Play", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
              Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.SCANNER_URL_MARKET));
              activity.startActivity(intent);
            }
          })
          .setNeutralButton("Web browser", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
              Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.SCANNER_URL_DIRECT));
              activity.startActivity(intent);
            }
          })
          .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
              dialog.cancel();
            }
          });

        builder.create().show();        
      }
    }

    /**
     * Process activity result to handle scanned data. This must be called from Activity, which started {@link #startScanner(Activity)}. 
     * @param requestCode
     * @param resultCode
     * @param data
     * @return true if code was properly scanned, false otherwise.
     * @see Activity#onActivityResult(int, int, Intent)
     * @see GameService#startScanner(Activity)
     */
    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
      if (requestCode == Constants.SCANNER_CODE && data != null && data.getExtras() != null) {
      String result = data.getExtras().getString(Constants.SCANNER_RESULT);
        gameHandler.broadcastEvent(new GameEvent(EventType.SCANNED_CODE, result));
        return true;
      }
      return false;
    }

}




Java Source Code List

cz.robyer.gamework.app.activity.BaseActivity.java
cz.robyer.gamework.app.activity.BaseGameActivity.java
cz.robyer.gamework.app.activity.GameInventoryActivity.java
cz.robyer.gamework.app.activity.GameMapActivity.java
cz.robyer.gamework.app.activity.GameMessagesActivity.java
cz.robyer.gamework.app.activity.GameObjectivesActivity.java
cz.robyer.gamework.app.activity.GameToolsActivity.java
cz.robyer.gamework.app.activity.HelpActivity.java
cz.robyer.gamework.app.activity.MainActivity.java
cz.robyer.gamework.app.activity.MessageActivity.java
cz.robyer.gamework.app.game.GameService.java
cz.robyer.gamework.app.service.JavaScriptHandler.java
cz.robyer.gamework.app.service.MessageAdapter.java
cz.robyer.gamework.constants.Constants.java
cz.robyer.gamework.game.GameEventBroadcaster.java
cz.robyer.gamework.game.GameEventListener.java
cz.robyer.gamework.game.GameEvent.java
cz.robyer.gamework.game.GameHandler.java
cz.robyer.gamework.game.GameService.java
cz.robyer.gamework.game.GameStatus.java
cz.robyer.gamework.scenario.BaseObject.java
cz.robyer.gamework.scenario.HookableObject.java
cz.robyer.gamework.scenario.IdentificableObject.java
cz.robyer.gamework.scenario.ScenarioInfo.java
cz.robyer.gamework.scenario.Scenario.java
cz.robyer.gamework.scenario.area.Area.java
cz.robyer.gamework.scenario.area.MultiPointArea.java
cz.robyer.gamework.scenario.area.PointArea.java
cz.robyer.gamework.scenario.area.SoundArea.java
cz.robyer.gamework.scenario.helper.EventHookable.java
cz.robyer.gamework.scenario.helper.ScannerHookable.java
cz.robyer.gamework.scenario.helper.TimeHookable.java
cz.robyer.gamework.scenario.hook.Condition.java
cz.robyer.gamework.scenario.hook.Hook.java
cz.robyer.gamework.scenario.message.Message.java
cz.robyer.gamework.scenario.parser.XmlScenarioParser.java
cz.robyer.gamework.scenario.reaction.ActivityReaction.java
cz.robyer.gamework.scenario.reaction.EventReaction.java
cz.robyer.gamework.scenario.reaction.MessageReaction.java
cz.robyer.gamework.scenario.reaction.MultiReaction.java
cz.robyer.gamework.scenario.reaction.Reaction.java
cz.robyer.gamework.scenario.reaction.ReferenceReaction.java
cz.robyer.gamework.scenario.reaction.SoundReaction.java
cz.robyer.gamework.scenario.reaction.VariableReaction.java
cz.robyer.gamework.scenario.reaction.VibrateReaction.java
cz.robyer.gamework.scenario.variable.BooleanVariable.java
cz.robyer.gamework.scenario.variable.DecimalVariable.java
cz.robyer.gamework.scenario.variable.Variable.java
cz.robyer.gamework.utils.GPoint.java
cz.robyer.gamework.utils.Log.java
cz.robyer.gamework.utils.Utils.java