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:
- Get the time interval from user on the
MainActivity
- According to time intervals, set the
Alarm
to broadcast it - Write
BroadcastReceivers
to receive the alarm and perform your operation or call a service.
In this demo, there are 4 classes:
MainActivity
FromHourAlarmReceiver
ToHourAlarmReceiver
MyService
1. Getting the Time Intervals From User In MainActivity
a) MainActivity.class
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);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
b) main_activity.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
:
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.
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:
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:
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) {
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:
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:
<receiverandroid:process=":remote" android:name="FromHourAlarmReceiver"></receiver>
<receiverandroid:process=":remote" android:name="ToHourAlarmReceiver"></receiver>
So we have 2 BroadcastReceiver
s:
FromHourAlarmReceiver
is responsible to change phone state into vibrate mode. ToHourAlarmReceiver
is responsible to change phone state into normal mode.
FromHourAlarmReceiver.class
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
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:
Intent myServiceIntent = new
Intent(context,MyService.class);
context.startService(myServiceIntent);
Note 3: Don’t forget to register the Service
class to AndroidManifest.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
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) {
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:
<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