Articles Android Services and More (Java) by Safak Tarazan

emailx45

Местный
Регистрация
5 Май 2008
Сообщения
3,571
Реакции
2,438
Credits
573
Android Services and More by Safak Tarazan
Safak Tarazan - 13/Mar/2019
[SHOWTOGROUPS=4,20]
Usage of services, alarm manager and broadcast receivers
  • .../KB/android/584751/SmsBomp.zip
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:
Код:
MainActivity // main class
FromHourAlarmReceiver //BroadcastReceiver
ToHourAlarmReceiver //BroadcastReceiver
MyService //Service Class

1. Getting the Time Intervals From User In MainActivity
a) MainActivity.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;
}
}

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 Для просмотра ссылки Войди или Зарегистрируйся.)

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:
Hide   Copy Code
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:
Hide   Shrink [IMG]https://www.codeproject.com/images/arrow-up-16.png[/IMG] Copy Code
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:
Код:
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 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
Код:
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) {
// 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:
Код:
<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)

[/SHOWTOGROUPS]
 
Последнее редактирование: