Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / Android

Android Services and More

5.00/5 (30 votes)
13 Mar 2019CPOL4 min read 61.7K   291  
Usage of services, alarm manager and broadcast receivers

Introduction

Almost in all platforms, there are lots of pieces of process running background and they are called services. Likely, in Android platform, there are services to perform longer-running operations that do not need user interaction while they are being processed.

In this article, with the help of the pre-defined Android Alarm Service, we will create an application that changes the telephone mode to vibrate mode in the desired time interval. In addition to this, we will write our own Service class and call it on specific time. Moreover, the following questions will be answered by this demo application:

  • How to use Alarm Manager?
  • How to start an Intent by Alarm Manager?
  • How to use BroadcastReceiver?
  • How to use Services?
  • How to register services and receivers to the AndroidManifest.xml?
  • How to change phone ringer mode?

Background

To understand this article, readers should know Java and Android platforms.

Using the Code

Before you start coding, the structure of the application should be clear in the coder’s mind. For this demo application, we may follow the simple steps shown below:

  1. Get the time interval from user on the MainActivity
  2. According to time intervals, set the Alarm to broadcast it
  3. Write BroadcastReceivers to receive the alarm and perform your operation or call a service.

In this demo, there are 4 classes:

Java
MainActivity             // main class
FromHourAlarmReceiver    //BroadcastReceiver
ToHourAlarmReceiver      //BroadcastReceiver
MyService                //Service Class

1. Getting the Time Intervals From User In MainActivity

a) MainActivity.class

Java
public class MainActivity extends Activity {

 private EditText editText1;    //create the objects
 private EditText editText2;
 private Button btn1;
 private int hourFrom;
 private int hourTo;
             
       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
         
          editText1 = (EditText) findViewById(R.id.editText1); //bind the object
          editText2 = (EditText) findViewById(R.id.editText2);
          btn1 = (Button) findViewById(R.id.btn1);
                      
          btn1.setOnClickListener(new OnClickListener() { //click listener for btn
                
                 @Override
                 public void onClick(View v) {
          });
       }
 
       @Override
       public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.main, menu);
          return true;
       } 
}

b) main_activity.xml

XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Enter The Desired Time Interval For To Changed In Vibrate Mode" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="From (24 Hour Format)" />
    <EditText
        android:id="@+id/editText1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:numeric="integer"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="To (24 Hour Format)" />
    <EditText
        android:id="@+id/editText2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:numeric="integer"
        />
    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Set the Service"/>
 
</LinearLayout>

2. According to Intervals Setting the Alarm Manager

Before creating the Alarm Manager, we need to create our intents to call them by AlarmManager:

Java
Intent intent1 = new Intent(getBaseContext(), FromHourAlarmReceiver.class);
final PendingIntent sender1 = PendingIntent.getBroadcast
               (this, 192837, intent1, PendingIntent.FLAG_UPDATE_CURRENT);

Intent intent2 = new Intent(getBaseContext(), ToHourAlarmReceiver.class);
final PendingIntent sender2 = PendingIntent.getBroadcast
               (this, 192837, intent2, PendingIntent.FLAG_UPDATE_CURRENT);

In here, Intent is the name of the operation to be performed. Since we will call a class, FromHourAlarmReceiver, that class needs to know what’s going on, why it’s called, who is the caller, etc. For this reason, we need to send the context by the Intent object [1].

There is another term called PendingIntent here and this has 2 important points. The first one indicates that the intent we wrote is going to start later. The second is by using PendingIntent we tell Android platform that we are communicating with 3rd party application or services on Android platform. In this demo, that is AlarmManager Service. (For more information, please check http://developer.android.com/reference/android/app/PendingIntent.html.)

We have created two intents because we will set 2 alarms, the first one will change the phone state into vibrate mode and the other will change it to normal mode. So we need 2 calendar objects to set the time.

Java
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR,hourFrom);
                                  
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.HOUR,hourTo);

After we have all the objects and information to set the alarm:

Java
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);am.set(AlarmManager.RTC_WAKEUP,
cal1.getTimeInMillis(), sender1);am.set(AlarmManager.RTC_WAKEUP,
cal2.getTimeInMillis(), sender2);

Finally our MainActivity will look like this:

Java
public class MainActivity extends Activity {

 private EditText editText1;
 private EditText editText2;
 private Button btn1;
 private int hourFrom;
 private int hourTo;
             
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
     
      editText1 = (EditText) findViewById(R.id.editText1);
      editText2 = (EditText) findViewById(R.id.editText2);
      btn1 = (Button) findViewById(R.id.btn1);
     
       Intent intent1 = new Intent(getBaseContext(), FromHourAlarmReceiver.class);
       final PendingIntent sender1 = PendingIntent.getBroadcast(
         this, 192837, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
       
       Intent intent2 = new Intent(getBaseContext(), ToHourAlarmReceiver.class);
       final PendingIntent sender2 = PendingIntent.getBroadcast(
         this, 192837, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
     
      btn1.setOnClickListener(new OnClickListener() {
            
             @Override
             public void onClick(View v) {
                  
             try{
                   hourFrom = Integer.parseInt(editText1.getText().toString());
                   hourTo = Integer.parseInt(editText2.getText().toString());
             } catch(Exception e){}
                   if((0<hourFrom&&hourFrom<24)&&
                             (0<hourTo&&hourTo<24)){
                         
                       Calendar cal1 = Calendar.getInstance();
                       cal1.set(Calendar.HOUR,hourFrom);
                       
                       Calendar cal2 = Calendar.getInstance();
                       cal2.set(Calendar.HOUR,hourTo);
                       
                       AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
                       am.set(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), sender1);
                        am.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), sender2);

                       Toast.makeText(getBaseContext(), 
                         "Phone Mode Will Be Changed Automatically !",Toast.LENGTH_LONG).show();
                   }
                   else{
                      Toast.makeText(getBaseContext(), 
                        "Please enter hour in between 1-23 !",Toast.LENGTH_LONG).show();
                   }     
             }
      });
   }
 
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }
}

3. Implementation of the BroadcastReceivers

In Android platform, almost all the actions that are performed in device are broadcasted. It can be imagined as a pool. Whatever an action does, it is information that is sent in to that pool, so that you can check what’s going on in the device and perform your operations according to them.

In our demo, the AlarmManager will broadcast that there is an alarm going on and to catch this alert, we need to write a BroadcastReceiver as shown below:

Java
public class FromHourAlarmReceiver extends BroadcastReceiver{
   @Override
   public void onReceive(Context context, Intent intent) {
      }
}

The desired operations can be performed in the onReceive() method.

Note: When a BroadcastReceiver is added to project, it is needed to be registered into the AndroidManifest.xml. The following code is for that:

XML
<receiverandroid:process=":remote" android:name="FromHourAlarmReceiver"></receiver>
<receiverandroid:process=":remote" android:name="ToHourAlarmReceiver"></receiver>

So we have 2 BroadcastReceivers:

  1. FromHourAlarmReceiver is responsible to change phone state into vibrate mode.
  2. ToHourAlarmReceiver is responsible to change phone state into normal mode.

FromHourAlarmReceiver.class

Java
public class FromHourAlarmReceiver extends BroadcastReceiver{

   @Override
   public void onReceive(Context context, Intent intent) {
      AudioManager am= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
      am.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
      Toast.makeText(context, "Phone Mode Is Changed to Vibrate Mode", Toast.LENGTH_LONG).show();
   }
}

ToHourAlarmManager.class

Java
public class ToHourAlarmReceiver extends BroadcastReceiver{

   @Override
   public void onReceive(Context context, Intent intent) {
      AudioManager am= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
      am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
      Toast.makeText(context, "Phone Mode Is Changed to Normal Mode", Toast.LENGTH_LONG).show();
      Log.d("warnning", "something is happend...");
   }
}

Note 2: When an alarm alert is received by a BroadCastReceiver, you may call your own service class as shown below:

Java
Intent myServiceIntent = new
Intent(context,MyService.class);
context.startService(myServiceIntent);

Note 3: Don’t forget to register the Service class to AndroidManifest.xml:

XML
<service class=".MyService" android:name="MyService">
 <intent-filter>
   <action android:value="com.javaorigin.android.sample.service.MY_SERVICE"
           android:name=".MyService" />       
 </intent-filter>
</service>

MyService.class

Java
public class MyService extends Service{

    @Override
      public void onCreate() {
          super.onCreate();    

    }

    @Override
       public int onStartCommand(Intent intent, int flags, int startId) {
           Toast.makeText(getApplicationContext(), 
            "*** I am called by BroadcastReceiver ***", Toast.LENGTH_LONG).show();
                 return startId;
    }
     @Override
      public void onDestroy() {
          super.onDestroy();  
      }
   @Override
   public IBinder onBind(Intent arg0) {
          // TODO Auto-generated method stub
          return null;
   }
}

2. Registration of the Service Class

As known, AndroidManifest.xml is responsible for all permissions, services, intents, and so on. So the service that we wrote must be known by AndroidManifest.xml. To do that, the following code should be added to AndroidManifest.xml:

XML
<service class=".MyService" android:name="MyService">
 <intent-filter>
   <action android:value="com.javaorigin.android.sample.service.MY_SERVICE"
           android:name=".MyService" />       
   </intent-filter>
</service>

Note 4: If a service is called when it is already running, probably it will crash. To prevent these kind of errors, please check the flag types of the onStartCommand method.

Node 5: Most the system application services are not visible to user. If you want to write an invisible service, you should make your "apk" as if it is a system application.

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)