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 not need user interaction while they are being processing.
In this article, with the help of the pre-defined Android Alarm Service, we will create an application that’s 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:
To understand this article, reader should know the Java and Android platform.
Before start coding, the structure of the application should be clear on coder’s mind. For this demo application we may follow the simple steps shown below:
MainActivity
BroadcastReceivers
In this demo, there are 4 classes:
MainActivity // main calss FromHourAlarmReceiver //BroadcastReceiver ToHourAlarmReceiver //BroadcastReceiver MyService //Service Class
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; } }
<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>
Before creating the Alarm Manager we need to create our intents to call them by AlarmManager:
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 and etc. For this reason we need to send the context by the Intent object [1].
FromHourAlarmReceiver
There is another term called PendingIntent here and this has 2 important points. The first one indicates that the intent that 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 info please check http://developer.android.com/reference/android/app/PendingIntent.html)
PendingIntent
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) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
In android platform almost all the actions that performed in device are broadcasted. It can be imagined as a pool. Whatever an action does, it is information 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 is going on and to catch this alert, we need to write a BroadcastReceiver as shown below:
BroadcastReceiver
public class FromHourAlarmReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { } }
The desired operations can be performed in tie onReceive() method.
onReceive()
Note: When a BroadcastReceiver is added to project, it is needed to be registered in to 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 BroadcastReceivers:
ToHourAlarmReceiver
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(); } }
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 received by a BroadCastReceiver, you may call your own service class as shown below:
BroadCastReceiver
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>
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; } }
As known, AndroidManifest.xml is responsible for all permissions, services, intents, and so on. So the service is that we wrote must be known by AndroidManifest.xml. To do that, the following code should be added to AndroidManifes.xml:
Note 4: If a service is called when it is already running, probably it will crash. To prevent this kind of errors, please check the flag types of the onStartCommand method.
onStartCommand
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.
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.