How to make Android app operational while it is closed? - android

I have an app that is supposed to intercept incoming calls, compare phone number with list created by the user and make silent mode if the caller is in this list, so I need my app to work always even if it was not launched by user. I tried a Service which is starting in my App class, I also call startForeground method within onStartCommand section and return START_STICKY. However, swiping away my app in app manager completely kills it without any allusion on recreating or background work, all functions that were working on app being launched or in "hide" state are not working anymore (until I tap on service notification, it opens the app again). What am I missing? I need my app to remain functional even if it is not launched so app could always compare incoming calls and decide to switch to "Do not disturb" mode.
Here is the my Service class code:
class BackgroundWorkService : Service() {
private val NOTIF_ID = 1
private val NOTIF_CHANNEL_ID = "CHANNEL_ID"
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
initChannel(this)
startServiceForeground()
return START_STICKY
}
private fun initChannel(context: Context) {
if (Build.VERSION.SDK_INT < 26) { return }
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(
NOTIF_CHANNEL_ID,
"Channel for service",
NotificationManager.IMPORTANCE_DEFAULT
)
channel.description = "Channel description"
notificationManager.createNotificationChannel(channel)
}
private fun startServiceForeground() {
val notificationIntent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0)
startForeground(
NOTIF_ID, NotificationCompat.Builder(
this,
NOTIF_CHANNEL_ID
)
.setOngoing(true)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle(getString(R.string.app_name))
.setContentText("Service is running background")
.setContentIntent(pendingIntent)
.build()
)
}
Here is where I'm starting the service:
class App : Application() {
override fun onCreate() {
super.onCreate()
startService(Intent(this, BackgroundWorkService::class.java))
}
}
EDIT:
Manifest is also updated:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.donotbotherme">
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".app.App"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.DoNotBotherMe">
<service
android:name=".app.BackgroundWorkService"
android:enabled="true"
android:exported="true" />
<activity android:name=".view.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

I have found a solution for this case after some more searches and conversations. The main fact I missed is that Android does not permit any app to work in background, instead you can create BroadcastReceiver, register it in Manifest and determine its intent-filter, then simply place the code you want to be executed in onReceive method of your BroadcastReceiver class. When the intent-filter is triggered your app will launch, execute the code and then kill itself.
Summarizing, to make you app to do some of its functions even while closed, you need to:
Create your BroadcastReceiver class (simply inherit your class from BroadcastReceiver);
Register it in your Manifest (here is my example):
<receiver android:name=".viewmodel.CallListener"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Place the code you want to execute in onReceive body in your BroadcastReceiver class.
Hope this solution will help somebody.

Related

Alarm with Broadcast not working in my android compose application

I have a android compose application and broadcast not working with alarm.
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<receiver android:name=".broadcast.EventAlarmBroadcastReceiver"
android:exported="false"
android:process=":remote"
android:enabled="true">
<intent-filter>
<action android:name="com.zxy.control_time.app.REMIND_ACTION"/>
</intent-filter>
</receiver>
kotlin code , setExact function is not working
val intent = Intent(context,EventAlarmBroadcastReceiver::class.java)
intent.`package` = BuildConfig.APPLICATION_ID
val pendingIntent = PendingIntent.getService(
context,
EventAlarmBroadcastReceiver.REMIND_INTENT_ID_BASIC_NUMBER + this.id,
intent,
0
)
// alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + 5 * 1000,pendingIntent) not working
// context.sendBroadcast(intent) working fine

Service not get called in android

I'm building a simple reminder application that will remind you of your events.
I've just used "Alarm Manager" with "Broadcast Receiver " to trigger my service at a certain time in the future. The purpose of the service is to vibrate the device when the notification arrives. Notification is working fine but, the Service isn't working as expected. I know that I can simply put the code for vibration inside the "Broadcast Receiver" but NEED TO KNOW ABOUT THE SERVICE. Don't know what's wrong with my code help me out guys, THANKS in advance.
Broadcast Receiver as follows:
public class NotificationSetter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("AlarmTriggered", "Alarm is triggered to start background service");
Intent serviceVibes = new Intent(context,BackgroundService.class);
context.startService(serviceVibes);
Toast.makeText(context, String.valueOf(Build.VERSION.SDK_INT), Toast.LENGTH_SHORT).show();
//creating the Notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "Notify");
builder.setSmallIcon(R.drawable.reminder);
builder.setContentTitle("Reminding of your event");
builder.setContentText("Time to play Cricket");
builder.setAutoCancel(true);
NotificationManagerCompat compat = NotificationManagerCompat.from(context);
compat.notify(3000, builder.build());
}
}
My service class:
public class BackgroundService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ServiceStarted", "Service is started using NotificationSetter");
Vibrator vibes = (Vibrator) getSystemService(VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
vibes.vibrate(VibrationEffect.createOneShot(2000,200));
}else {
vibes.vibrate(2000);
}
Toast.makeText(getApplicationContext(), String.valueOf(Build.VERSION.SDK_INT), Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
The Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.remindme">
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name="com.example.remindme.MyContext"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".StopAlarm"></activity>
<activity android:name=".GetEvent" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.remindme.BackgroundService"
android:enabled="true"
android:exported="true">
</service>
<receiver android:name=".NotificationSetter"
android:enabled="true"
android:exported="true"/>
</application>
</manifest>
According to documentation, since Android 8.0 afterwards, an app cannot start a foreground service unless in a few conditions:
https://developer.android.com/about/versions/oreo/background
Check if your service is triggered when you have your app in foreground, meaning that your app has a visible Activity to user. If it works in this condition, then it means your problem lies in background execution limits introduced in Android 8.0. So to make your service work, you can start it as a foreground service by calling this line of code:
ContextCompat.startForegroundService(context, new Intent(context, YourBackgroundService.class));
A foreground service needs a notification to be shown at status bar. You can either grab an instance of your alarm notification and use it as the foreground service notification or create a new notification.

Broadcast Receiver for DATE_CHANGED not Working Only for TIMEZONE_CHANGED

I can't get my BroadcastReciever() to work for DATE_CHANGED, but works just fine for TIMEZONE_CHANGED.
class DateChangeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("my broadcast","works")
if (intent.action == Intent.ACTION_DATE_CHANGED ||
intent.action == Intent.ACTION_TIMEZONE_CHANGED) {
var netUtils = NetUtils(context)
netUtils.mainStack()
}
}
}
Here is my Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<application
android:allowBackup="true"
android:icon="#drawable/castle"
android:roundIcon="#drawable/castle"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>
<receiver android:name=".DateChangeReceiver">
<intent-filter>
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
</intent-filter>
</receiver>
</application>
</manifest>
Here is my function in my main activity:
fun keepAlive() {
//KEEP RUNNING IN BACKGROUND TO UPDATE WALLPAPER AT CHANGE OF DAY
val component = ComponentName(this#MainActivity, DateChangeReceiver::class.java)
packageManager.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
Log.d("KEEPALIVE FUN","works")
}
keepAlive()
I get nothing in logcat when I change my date manually or if I set the time to 11:59 and wait a minute.
A couple of errors I do have in logcat that show up before I added the Reciever are:
2019-03-05 11:48:01.884 29176-29202/com.test E/libc: Access denied finding property "vendor.debug.egl.profiler"
2019-03-05 11:48:07.616 29176-29234/com.test E/libc: Access denied finding property "ro.vendor.graphics.memory"
2019-03-05 11:48:07.665 29176-29234/com.test E/libc: Access denied finding property "vendor.gralloc.enable_ahardware_buffer"
Is it possible these are effecting my BroadcastReciever? I've tested this on 3 devices so far.
Solved the issue by switching to the AlarmManager. Here's the code if anyone's curious:
val calendar: Calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, 3)
}
This method worked better for me as it keeps all devices with my app updating at the same time apposed to start of new day.
val alarmMgr = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val broadcastIntent = Intent(this, DateChangeReceiver::class.java)
val pIntent = PendingIntent.getBroadcast(this,0,broadcastIntent,0)
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pIntent
I registered broacastreceiver for date change implicitly..this worked for me.
registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_DATE_CHANGED));
According to this question, there could be a bug. It is obsolete now, but you can try to submit new issue.
Also this question may help you.
They using
ACTION_TIME_TICK
ACTION_TIMEZONE_CHANGED
ACTION_TIME_CHANGED
private final BroadcastReceiver m_timeChangedReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_TIME_CHANGED) ||
action.equals(Intent.ACTION_TIMEZONE_CHANGED))
{
doWorkSon();
}
}
};

GCM push notification is not showing in some devices when app is not running

I am implement GCM Push Notification in my app and its successfully done but in some devices it not show notification when app is close.
List of device which notication is not show:
Redmi-2
lenovo
Gionee
Can anyone explain me what is problem and how i solve its.
here my manifest:-
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent.Controller"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/MyMaterialTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Login"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
</activity>
<activity
android:name=".ListOfClass"
android:screenOrientation="portrait">
</activity>
<activity
android:name=".EditProfile"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
</activity>
<activity
android:name=".ShowStudentList"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
</activity>
<receiver
android:name="student.skoolstar.android.catalyst.com.schoolstar.skoolstarstudent.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="schoolstar.com.catalyst.android.skoolstar" />
</intent-filter>
</receiver>
<service android:name=".GCMNotificationIntentService" />
<activity
android:name=".Message"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
</activity>
<activity
android:name=".Attendance"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
</activity>
<activity
android:name=".NewMessage"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
</activity>
<activity
android:name=".GroupMessage"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
</activity>
<activity
android:name=".Test_Chat"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
</activity>
</application>
</manifest>
here my service name GCMNotificationIntentService:-
public class GCMNotificationIntentService extends GCMBaseIntentService {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
Database db;
private Controller aController = null;
public GCMNotificationIntentService() {
// Call extended class Constructor GCMBaseIntentService
super(Constants.GOOGLE_SENDER_ID);
}
public static final String TAG = "GCMNotificationIntentService";
#Override
protected void onRegistered(Context context, String registrationId) {
}
#Override
protected void onUnregistered(Context context, String registrationId) {
Log.d("unref",registrationId);
if(aController == null)
aController = (Controller) getApplicationContext();
Toast.makeText(getApplicationContext(),"hello no",Toast.LENGTH_LONG).show();
aController.displayMessageOnScreen(context,
getString(R.string.gcm_unregistered));
aController.unregister(context, registrationId);
}
#Override
public void onError(Context context, String errorId) {
Log.d("error","");
if(aController == null)
aController = (Controller) getApplicationContext();
aController.displayMessageOnScreen(context,
getString(R.string.gcm_error, errorId));
}
#Override
protected void onMessage(Context context, Intent intent) {
if(aController == null)
aController = (Controller) getApplicationContext();
aController.acquireWakeLock(getApplicationContext());
String message = intent.getExtras().getString("message");
String formuser = intent.getExtras().getString("formuser");
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+5:30"));
Date currentLocalTime = cal.getTime();
DateFormat date = new SimpleDateFormat("HH:mm a");
date.setTimeZone(TimeZone.getTimeZone("GMT+5:30"));
String localTime = date.format(currentLocalTime);
db = new Database(context);
int from_id = 0;
List<FetchData> fetchdata = db.getAllContacts();
for (FetchData fd : fetchdata)
{
from_id=fd.getID();//get ser no
}
db.storeMessage(420, formuser, from_id + "", message, "text", localTime, "F", "ST", "R");
aController.displayMessageOnScreen(context, message);
// notifies user
sendNotification(context,message);
}
private void sendNotification(Context context,String msg) {
String app_name = context.getResources().getString(R.string.app_name);
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, ListOfClass.class), 0);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this).setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(app_name)
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText("New Message")
.setSound(alarmSound);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
wl.acquire(15000);
// Log.d(TAG, "Notification sent successfully.");
}
}
When I am see the whatsapp, hike and others notification app he will always run in background thread but my app is not running always in background. So may be this reason be also.
I am recently working on android please help me.Thanks in advance!
I faced similar issue with Redmi-2. There is no problem in the code but it is due to Custom UI provided by the Manufacturer like MIUI 6.
So to enable GCM notifications
Go to Security App >> Tap on permissions >> Tap on Auto Start and enable auto start for your App.
There are two major reasons for that
1 - Some devices does not allow you to run a service on background like redmi-2 ( almost on all xiaomi device ). Even whats app could not work properly on them unless user allow them by going to Security App >> Tap on permissions >> Tap on Auto Start and enable auto start for whatsapp etc. In this case all you can do is to show the details of this to user on application start up. And open that screen and guide user ( if possible ) like clean master.
2- Second reason is that it didn't work on one of those phone whose Google Play Services app wasn't installed correctly(and its essential for GCM). You can not do anything on these devices also. The only thing you can do in this case is just show some message to user about this.
So from my experience there always be a number of users(but very small percentage) who wont receive GCM push.
There is concept of whitelisting in Xiaomi's phone. So, if you put log in onReceive of gcm, you will notice that gcm is receiving but it's not processing further. Its cause your app is not whitelisted.
Xiaomi for security purposes disables the Notification for each Application. Follow these steps to receive messages in background once they quit the app using cleaner.
Enable Autostart
Enable Floating and Lock Screen Notification
Enable AutoStart
Open Security App.
Got to Permissions, then Click on Auto Start Management.
Add/Enable auto start apps (e.g. Whatsapp).
Enable Floating and Lock Screen Notification
Open Settings App.
Click on Notifications, then click on Manage Notifications.
Tap on the App which you are looking for (e.g. WhatsApp).
Enable Show in notification shade / Show on lockscreen and in drop down option.
For Reference check this out : http://support.hike.in/entries/55998480-I-m-not-getting-notification-on-my-Xiaomi-Phone-For-MIUI-6-
i got success with this.. Hope it helps..
Facing the same issue, the only things we did are to educate xiaomi users to do the steps as #anup-dasari mentioned, and set the gcm priority to high, with possibility to have persistent service in the future

Good practice for Android services?

I want to create an independent service of my main activity. This service is started at boot my phone and retrieves information via webservice every x minutes.
What are the best practices to do this?
Launch a service with BOOT_COMPLETED action?
There he other actions to launch a service without launching the main activity?
Another design or best practice?
I want a service with the same behavior as Facebook for example. This service is active all the time and displays a notification when you receive a message. If you click on the notification, it opens the Facebook application. But that kills the application, served remains active for receiving new messages.
My first test kills my service when I want to kill my main activity.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fr.mrbmx"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- The following two permissions are not required to use
Google Maps Android API v2, but are recommended. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="fr.mr.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="fr.mr.service.MyReceiver"
android:enabled="true"
android:exported="false"
android:label="OnBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name="fr.mr.service.LocalService"
android:enabled="true"
android:exported="false"
android:label="LocalService" />
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="#string/mapKey"/>
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
</application>
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = MyReceiver.class.getName();
#Override
public void onReceive( Context ctx, Intent i ) {
Log.d( TAG, "MyReceiver.onReceive : " + i.getAction() );
ctx.startService(new Intent().setComponent(new ComponentName(
ctx.getPackageName(), LocalService.class.getName())));
}
}
public class LocalService extends Service{
private static final String TAG = LocalService.class.getName();
private NotificationManager mNM;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
private int NOTIFICATION = 1332;
private Timer timer ;
private int mId;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Log.i(TAG, "onCreate");
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
timer = new Timer();
Notification note = new Notification( 0, null, System.currentTimeMillis() );
note.flags |= Notification.FLAG_NO_CLEAR;
startForeground( 0, note );
/*
Notification.Builder mBuilder =
new Notification.Builder(this)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("test title")
.setContentText("test content")
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
startForeground(1, mBuilder.getNotification());*/
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Received start id " + startId + ": " + intent);
mId = startId;
new Thread(new Runnable() {
public void run() {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
showNotification();
}
}, 0, 60000);
}
}).start();
return START_STICKY;
}
#Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
mNM.cancel(NOTIFICATION);
}
/**
* Show a notification while this service is running.
*/
private void showNotification() {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(getString(fr.mrbmx.R.string.notification_title))
.setContentText(getString(fr.mrbmx.R.string.notification_text))
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, MainActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());
}
}
Your service does not need to be active all the time to receive messages. Facebook, along with just about every other push based system, use Google Cloud Messaging (GCM) to wake up your device and send a message to your application from the remote server.
Of course, if you only need to periodically check (rather than be pushed information in near real time), then you can schedule an alarm to start your service every X minutes or build a Sync Adapter - an Android component specifically built to periodically load data from a remote server.
Note that many applications combine the two approaches and run a sync adapter in response to a GCM push.
I want to create an independent service of my main activity. This
service is started at boot my phone and retrieves information via
webservice every x minutes.
You can certainly do this by registering a BroadcastReceiver on your AndroidManifest.xml that responds to BOOT_COMPLETED and launch the Service from it. Your app will need to be ran at least once for BOOT_COMPLETED to be delivered (before API 11 it wasn't the case). Also, consider the implications of pulling data from a server too often (i.e. battery, etc).
I want a service with the same behavior as facebook for example. This
service is active all the time and displays a notification when you
receive a message. If you click on the nitification, it opens the
facebook application. But that kills the application, served remains
active for receiving new messages.
At least for their chat application, Facebook uses MQTT, which is a M2M publish/subscribe asynchronous mechanism. They do not pull data from the server every X minutes. They just listen to incoming data when it is broadcasted. If you want to use MQTT there is an open source project called Eclipse Paho that you might be interested in.

Categories

Resources