Friday, March 1, 2013

Let Me Work

You just arm yourself with strong will and you just sit down in the office chair, ready to take profit of your time doing some important work you should do or studying something really relevant, but something distracts you...is that small device you have near you, someone speaking through an instante messaging program, or you just receive and email, even someone could call you...all that concentration crumbling up on every minute. No problem, download Let Me Work, and let yourself to have a really work time.

An Android application

Let Me Work is a free Android application which runs a count-down timer and activates Android's airplane mode automatically. You set a specific time, and when you push start the count-down begins and airplane mode is enabled untill the timer finishes; or untill you stop it. Also you can have a pause and recover the coverage. Let Me Work also can function without having to activate airplane mode, as a simple count-down app.

Friday, February 15, 2013

CountDownChronometer

While searching for a count-down chronometer in the android API, one finds that most resembles is the CountDownTimer class; but it only starts a count-down, and send an event on every predetermined time, and one event when finish, but, what if I want to pause it? I've create a CountDownChronometer class to manage this, and one interface that must implement the class which instantiates it:

CountDownChronometer

Use the constructor to set up the count-down, start() to start it or resume it after pause(), and stop() to cancel the count-down:
package reprom.blogspot.com;

import android.os.CountDownTimer;
import android.os.SystemClock;
import android.util.Log;

/**
 * @author David 'svprdga' Serrano Canales
 */
public class CountDownChronometer{
 
 // Set here the milliseconds interval for every tick.
 private long millisInterval = 500;
  
 private final static String TAG = "CountDownChronometer";
 private ICountDownChronometer handler;
 private boolean isPaused = false;
 private long initCountDownMillis;
 private long restartCountDownMillis;
 private long startCountDownMillis;
 private CountDownTimerImpl countDownTimerImpl;

 /**
  * CountDownChronometer's public constructor.
  * @param initCountDownMillis Milliseconds until the count-down ends.
  * @param handler Object which invoked this constructor, with ICountDownChronometer interface implemented.
  */
 public CountDownChronometer(long initCountDownMillis, ICountDownChronometer handler){
  this.initCountDownMillis = initCountDownMillis;
  this.handler = handler;
 }
 
 /**
  * Starts the count-down. Also used for restart after pause() call.
  */
 public void start(){
  long countDownMillis = 0;
  if (isPaused){
   countDownMillis = restartCountDownMillis;
   isPaused = false;
  } else {
   countDownMillis = initCountDownMillis;
  }
    
  countDownTimerImpl = new CountDownTimerImpl(countDownMillis);
  startCountDownMillis = SystemClock.elapsedRealtime();
  countDownTimerImpl.start();
 }
 
 /**
  * Pauses the count-down.
  */
 public void pause(){  
  isPaused = true;
  restartCountDownMillis = initCountDownMillis - (SystemClock.elapsedRealtime() - startCountDownMillis);
  initCountDownMillis = restartCountDownMillis;
  Log.d("countDown", "restartCountDownMillis: "+restartCountDownMillis);
  countDownTimerImpl.cancel();
 }
 
 /**
  * Stops and cancels the count-down.
  */
 public void stop(){
  countDownTimerImpl.cancel();
  countDownTimerImpl = null;
  isPaused = false;
  onCountDownFinish();
 }
 
 /**
  * Method which is invoked on every count-down tick.
  * @param millisUntilFinished
  */
 public void onCountDownTick(long millisUntilFinished){
  handler.onCountDownTimerTick(millisUntilFinished);
 }
 
 /**
  * Method which is invoked when the count-down finishes.
  */
 public void onCountDownFinish(){
  handler.onCountDownTimerFinish();
 }
 
 public class CountDownTimerImpl extends CountDownTimer{
  
  /**
   * CountDownTimerImpl constructor.
   * @param millisInFuture Time in milliseconds until the count-down ends.
   */
  public CountDownTimerImpl(long millisInFuture) {
   super(millisInFuture, millisInterval);
  }
  
  public void onTick(long millisUntilFinished) {
   onCountDownTick(millisUntilFinished);
  }
  
  public void onFinish() {
   onCountDownFinish();
  }

 }

}

ICountDownChronometer

This interface must be implemented for the objects that instantiates the CountDownChronometer, the implemented methos allows you to control the count-down tick events, and the finish event:
/**
 * @author David 'svprdga' Serrano Canales
 */
public interface ICountDownChronometer {
 
 /**
  * Method called on every CountDownTimer tick.
  */
 public void onCountDownTimerTick(long millisUntilFinished);
 
 /**
  * Method called when CountDownTimer finishes.
  */
 public void onCountDownTimerFinish();
}

Thursday, January 31, 2013

Android Processes

I've spent too many hours trying to understand the mechanic of processes in android; it's not difficult but it takes a while to see how to manage them, and pass information between them and activities; so I made this tutorial in order to clarify the very basics of processes:
  1. Start a process.
  2. Send data from activity to a process.
  3. Send data from process to activity.

Create a project in Eclipse

  • Application name: ProcessTest
  • Project name: ProcessTest
  • Package name: com.reprom.processtest
  • Min SDK: API 10
  • Target SDK: API 17
  • Compile with: API 10
  • Theme: None
Leave the rest of the settings to default values, and create one activity called MainActivity (Note: the activity layers in this tutorial are not important because we are going to work directly with logs, and watch the results in LogCat, so you can leave the default layer "activity_main" without changes).

Service class

Quoting the android developers official documentation "A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.", so, to say it simple, a service is a manner of performing operations outside our app, it means that if our app is opening or closing, that not affect the flux of our service (unless explicitly we close it). An example of that would be an app that needs to update some data with some server, and it's managed by a service (the service check for updates, no mather is the app is open or not), in that example, the app is not overloaded with such long-term operations; the user interface doesn't slow down, and when it's needed, the service notices the app with the correspondent information.
In this tutorial I'll show you how to create a service that runs a count-down timer in background, and notices our MainActivity ever 2 seconds and finally, when it's finished. First, create a class TestService, a service class must inherit from android.app.Service, put the following code:
package com.reprom.processtest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class TestService extends Service {

private final String TAG = "Service";
    Intent broadcastIntent = new Intent("testService"); 

 @Override
 public IBinder onBind(Intent arg0) {
  // TODO Auto-generated method stub
  return null;
 }

}
The method onBind must be overriden, but in this tutorial we are not going to talk about it. The TAG var I added is for identifying our logs, and broadcastIntent is an Intent object we'll need to broadcast data to our activity. Now, add an onCreate method to watch when our service is starting:
@Override
    public void onCreate() {
     super.onCreate();
        Log.d(TAG, "Service onCreate() running...");
    }
Now, we are going to see the "quid" of all this, the method onStartCommand(); which is invoked every time Context.startService() is called from an activity; performing the proper operations that the service is intended to do. Look at the code:
@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
     Bundle bundle = intent.getExtras();
     
     new CountDownTimer(
       bundle.getLong("millisUntilFinished"),
       bundle.getLong("countDownInterval")) {      

      public void onTick(long millisUntilFinished) {
        Log.d(TAG, "onTick from TestService");
        broadcastIntent.putExtra("action", "timerTick");
           broadcastIntent.putExtra("millisUntilFinished", millisUntilFinished);
           sendBroadcast(broadcastIntent);
      }
      
      public void onFinish() {
           Log.d(TAG, "onFinish from TestService");
           broadcastIntent.putExtra("action", "timerFinish");
           sendBroadcast(broadcastIntent);
         }
       }.start();

        return START_STICKY;
    }
First we retrieve the data that comes from the activity in a Bundle object, then create a new CountDownTimer, passing the time in milliseconds until it finishes and the interval time (onTick() will be called every interval). On ever onTick() we put the time left in our broadcastIntent object, and put a variable called "action" to notify the activity what is the kind of broadcasting it's receiving. In method onFinish() we do the same; then, sendBroadcast() will broadcast the message. (Note: I am not going to explain in this basic tutorial about the return value (Service.START_STICKY), see the android documentation for that.
The service won't start if we don't register it in the AndroidManifest file, inside "Application" tag:

        
Note the colon sign in process, it means that the process is private for our app and not shareable.

The activity

Ok, now we have the service; let's fill the activity:
package com.reprom.processtest;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;

public class MainActivity extends Activity {
 
 private final static String TAG = "MainActivity";
 private Intent serviceIntent;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  serviceIntent = new Intent(this.getApplicationContext(), TestService.class); 
     serviceIntent.putExtra("millisUntilFinished", 10000l); 
     serviceIntent.putExtra("countDownInterval", 2000l); 
     startService(serviceIntent);
 }

}
Declare a serviceIntent Intent which we'll use to send data to process. I onCreate() we put the milliseconds until the count-down finishes and the interval rate in a long type; and then call startService() with the Intent to star the service.
Create a BroadcastReceiver object in order to read the broadcast sent from service:
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
   
         @Override
         public void onReceive(Context context, Intent intent) {
          Bundle bundle = intent.getExtras();
          
          switch (bundle.getInt("action")){
          case 0:
           Log.d(TAG, "Time to finish: "+bundle.getLong("millisUntilFinished"));
           break;
          case 1:
           Log.d(TAG, "Timer finished.");
           break;
          default:
          }
         }
     };
Finally we need to register the BroadcastReceiver object in onResume(), and unnregister in onPause():
@Override
 public void onResume() {
  super.onResume();  
  registerReceiver(broadcastReceiver, new IntentFilter("testService"));
 }
 
 @Override
 public void onPause() {
  super.onPause();
  unregisterReceiver(broadcastReceiver);
 }