proximity alert does not fire and notify - android

Does anyone know what is the issue that cause fire alert not working when get into the proximity radius? I has been struggled for a week in solving this issue and I will really appreciated if anyone can help me out on this issue or give me some guide to complete it.
MainActivity.java
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
public class MainActivity extends Activity {
private static final long POINT_RADIUS = 150; // in Meters
private static final long PROX_ALERT_EXPIRATION = -1; // will not expire
private static final String PROX_ALERT_INTENT = "com.example.myalert";
private LocationManager locationManager;
double latitude = 2.81202, longitude = 101.75989;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Intent intent = new Intent(PROX_ALERT_INTENT);
PendingIntent proximityIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
locationManager.addProximityAlert(latitude, longitude, POINT_RADIUS, PROX_ALERT_EXPIRATION, proximityIntent);
}
}
ProximityReceiver.java
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.location.LocationManager;
import android.util.Log;
public class ProximityReceiver extends BroadcastReceiver{
private static final int NOTIFICATION_ID = 1000;
#SuppressWarnings("deprecation")
#Override
public void onReceive(Context context, Intent intent) {
String key = LocationManager.KEY_PROXIMITY_ENTERING;
Boolean entering = intent.getBooleanExtra(key, false);
if (entering) {
Log.d(getClass().getSimpleName(), "entering");
}else {
Log.d(getClass().getSimpleName(), "exiting");
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
Notification notification = createNotification();
notification.setLatestEventInfo(context, "Proximity Alert!", "You are near your point of interest.", pendingIntent);
notificationManager.notify(NOTIFICATION_ID, notification);
}
private Notification createNotification() {
Notification notification = new Notification();
notification.icon = R.drawable.ic_launcher;
notification.when = System.currentTimeMillis();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.defaults |= Notification.DEFAULT_VIBRATE;
notification.defaults |= Notification.DEFAULT_LIGHTS;
notification.ledARGB = Color.WHITE;
notification.ledOnMS = 1500;
notification.ledOffMS = 1500;
return notification;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myalert"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.myalert.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>
<activity
android:name="ProximityReceiver">
</activity>
</application>
</manifest>

you have not set the receiver in the manifest, "ProximityReceiver" is not an Activity but a receiver.
Try something like this.
<receiver android:name="ProximityReceiver" >
<intent-filter>
<action android:name="com.example.myalert" />
</intent-filter>
</receiver>
Cheers.

Related

Receive message from MQTT in android service

I have to create an Android app that can receive message from a sensor and send a notification to the user when a message is received. I have to do this with out using service like Google Firebase because all the system must run locally. I thought to use MQTT in a service, but when I kill the app, it disconnect from the broker. If the app is running in background this implementation works but I need to keep the connection alive also when app is killed.
This is my implementation of the service:
package it.unisalento.sonoff.helper;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.net.wifi.aware.AttachCallback;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.util.ArrayList;
import java.util.List;
import it.unisalento.sonoff.R;
import it.unisalento.sonoff.view.MainActivity;
public class Service extends android.app.Service {
private Looper serviceLooper;
private ServiceHandler serviceHandler;
private List ids = new ArrayList();
private MqttHelper mqttHelper;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
showNotification("Aggiornamento di stato", String.valueOf(msg.arg1));
}
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
mqttHelper = new MqttHelper(getApplicationContext());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
mqttHelper = new MqttHelper(getApplicationContext());
mqttHelper.setCallback(new MqttCallbackExtended() {
#Override
public void connectComplete(boolean reconnect, String serverURI) {
}
#Override
public void connectionLost(Throwable cause) {
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
serviceHandler.sendMessage(msg);
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
mqttHelper.connect();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
private void showNotification(String title, String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
String channelId = "notification_channel";
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setPriority(Notification.PRIORITY_MAX)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(getApplicationContext().NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, "lock", NotificationManager.IMPORTANCE_HIGH);
channel.enableVibration(true);
notificationManager.createNotificationChannel(channel);
}
int id;
if(ids.isEmpty()){
id=0;
}
else{
id = ids.size();
}
ids.add(id);
notificationManager.notify(id , notificationBuilder.build());
}
}
And here my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.unisalento.sonoff">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
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.FullScreen"
android:usesCleartextTraffic="true">
<!-- MqttService -->
<service android:name="org.eclipse.paho.android.service.MqttService" />
<service android:name=".helper.Service"
android:exported="false"
android:stopWithTask="false"/>
<activity android:name=".view.DashboardActivity"/>
<activity
android:name=".view.LoginActivity"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".view.MainActivity"/>
</application>
You need to use Foreground Services and pass the notification you built in startForeground method.

Why doesn't the notification appear?

I have made an app to test to show a foreground service and then tried to implement it in real app to close wifi after certain time, the code is the same as my test app but it doesn't show notification.
the service works fine but without notification
Main Activity
package com.example.countdownclosewifi.UI;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;
import com.example.countdownclosewifi.MyService;
import com.example.countdownclosewifi.R;
import com.example.countdownclosewifi.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private BroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
// Intent filter to set the same action of the broadcast sender
IntentFilter intentFilter_getRemainingTime = new IntentFilter();
intentFilter_getRemainingTime.addAction("Count");
// what will happen when the app receive a broadcast
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int i = intent.getIntExtra("Show", 0);
binding.timeLeft.setText(String.valueOf(i));
}
};
registerReceiver(receiver, intentFilter_getRemainingTime);
binding.start.setOnClickListener(view -> {
if (binding.setTime.getText().toString().isEmpty() || Long.parseLong(binding.setTime.getText().toString()) == 0) {
Toast.makeText(MainActivity.this, "Enter the duration", Toast.LENGTH_SHORT).show();
} else {
Intent serviceIntent = new Intent(this, MyService.class);
int time = Integer.parseInt(binding.setTime.getText().toString());
serviceIntent.putExtra("Time", time);
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){
startForegroundService(serviceIntent);
}
else {
startService(serviceIntent);
}
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}
Service class
package com.example.countdownclosewifi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
//import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import com.example.countdownclosewifi.UI.MainActivity;
import java.util.Timer;
import java.util.TimerTask;
public class MyService extends Service {
private WifiManager wifiManager;
private int timeRemaining;
private Timer timer;
// Intent intent;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
IntentFilter intentFilter_stop = new IntentFilter();
intentFilter_stop.addAction("Stop timer");
timeRemaining = intent.getIntExtra("Time", 0);
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (timeRemaining == 0) {
wifiManager.setWifiEnabled(false);
timer.cancel();
stopSelf();
}
setNotification(timeRemaining);
Intent intent = new Intent();
intent.setAction("Count");
intent.putExtra("Show", timeRemaining);
sendBroadcast(intent);
timeRemaining -= 1;
}
}, 0, 1000);
return START_STICKY;
}
public void setNotification(int timeRemaining) {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
String channel_id = "id";
Notification notification;
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.O) {
notification = new Notification.Builder(this, channel_id)
.setContentTitle("You are running out of time")
.setContentText(String.valueOf(timeRemaining))
.setSmallIcon(R.drawable.wifi_24)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true)
.build();
} else {
notification = new NotificationCompat.Builder(this, channel_id)
.setContentTitle("You are running out of time")
.setContentText(String.valueOf(timeRemaining))
.setSmallIcon(R.drawable.wifi_24)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true)
.build();
}
// Notification ID cannot be 0.
startForeground(1, notification);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String id = "Notification Channel";
CharSequence name = "notification";
NotificationChannel notificationChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
}
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.countdownclosewifi">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
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.CountDownCloseWIFI">
<activity android:name=".UI.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService"/>
</application>
</manifest>
it's so clear but i cant see what i am missing to show this notification.
use countdowntimer class instead of timerTask
and set the priority as MAX
NotificationManager.IMPORTANCE_HIGH
I Solved it, the problem was that the Notification ID was not the same as the Channel ID

Android local notification does not fire after system reboot

I implemented some notifications that fire on specific date and time. My code works if phone is not rebooted after app installation, but if I reboot the phone the notifiction does not fire. I tried many methods proposed by other developers, but nothing changed. Is it possible to restart notification service automatically on system reboot?
BootService.java
package com.example.is2_app.utility;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService;
import java.util.Calendar;
import static java.util.Calendar.APRIL;
public class BootService extends JobIntentService {
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intent = new Intent(this, ReminderBroadcast.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
calendar.add(Calendar.DAY_OF_YEAR,-1);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 9);
calendar.set(Calendar.SECOND, 40);
if(calendar.getTimeInMillis()>System.currentTimeMillis()) {
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
protected void onHandleWork(#NonNull Intent intent) {
}
}
ReminderBroadcast.java
package com.example.is2_app.utility;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import androidx.core.app.NotificationCompat;
import com.example.is2_app.MainActivity;
import com.example.is2_app.R;
public class ReminderBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
showNotification(context);
}
void showNotification(Context context) {
String CHANNEL_ID = "your_name";// The id of the channel.
CharSequence name = context.getResources().getString(R.string.app_name);// The user-visible name of the channel.
NotificationCompat.Builder mBuilder;
Intent notificationIntent = new Intent(context, MainActivity.class);
long when = System.currentTimeMillis();
Bundle bundle = new Bundle();
notificationIntent.putExtras(bundle);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startService(notificationIntent);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= 26) {
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH);
mNotificationManager.createNotificationChannel(mChannel);
mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher_candida)
.setLights(Color.RED, 300, 300)
.setChannelId(CHANNEL_ID);
} else {
mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher_candida)
.setPriority(Notification.PRIORITY_DEFAULT);
}
mBuilder.setContentTitle(context.getString(R.string.spazzatura));
mBuilder.setContentIntent(contentIntent);
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(context.getString(R.string.spazzatura_residuo)));
mBuilder.setContentText(context.getString(R.string.spazzatura_residuo));
mBuilder.setAutoCancel(true).setWhen(when);
mNotificationManager.notify(1, mBuilder.build());
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.is2_app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".global.Global"
android:allowBackup="true"
android:configChanges="locale|orientation|keyboardHidden|screenSize"
android:icon="#mipmap/ic_launcher_candida"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_candida_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:usesCleartextTraffic="true">
<service
android:name=".utility.BootService"
android:enabled="true"
android:exported="true" />
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".utility.ReminderBroadcast"
android:permission = "android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
</application>
</manifest>

How can I start android application on device boot?

I have need to start android foreground service, and launch activity from that service on device boot. I have extensively searched web and stackoverflow and tried different suggestions but it is very strange that I can not make this functionality work.
I can not understand what I am doing wrong.
Below is the code from my project and the content of manifest file.
what I am doing wrong and how to solve it, the functionality to work on most android devices?
This is my AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="kor.location.tracker">
<uses-permission android:name="android.permission.INTERNET" ></uses-permission>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
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">
<receiver android:name="kor.location.tracker.AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:enabled="true"
android:name="kor.location.tracker.WorkerService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"
/>
</application>
</manifest>
This is my Austostart.java:
package kor.location.tracker;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
public class AutoStart extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent arg1)
{
try {
System.out.println("test1");
if (Intent.ACTION_BOOT_COMPLETED.equals(arg1.getAction())) {
System.out.println("test2");
WorkerService.enqueueWork(context, new Intent());
System.out.println("test3");
}
}catch(Exception ex) {
Toast.makeText(context, ex.getMessage(), Toast.LENGTH_LONG).show();
}
/*
Intent intent = new Intent(context, WorkerService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
Log.i("Autostart", "started");
*/
}
}
This is my service class WorkerService.java:
package kor.location.tracker;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService;
public class WorkerService extends JobIntentService
{
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, WorkerService.class, 104501, work);
}
/*
private static final String TAG = "MyService";
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
}
*/
#Override
protected void onHandleWork(#NonNull Intent intent) {
Intent intents = new Intent(getBaseContext(),MainActivity.class);
intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intents);
//Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
//Log.d(TAG, "onStart");
}
/*
#Override
public void onStart(Intent intent, int startid)
{
final LocationListener mLocationListener = new LocationListener() {
#Override
public void onLocationChanged(final Location location) {
//your code here
String kuku = location.getLatitude() + "=" + location.getLongitude();
Toast.makeText(WorkerService.this, kuku, Toast.LENGTH_LONG).show();
Log.d(TAG, kuku);
;
;
location.getAltitude();
location.getSpeed();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
LocationManager mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000,
1, mLocationListener);
}catch (SecurityException ex){
Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show();
Log.d(TAG, ex.getMessage());
}
Intent intents = new Intent(getBaseContext(),MainActivity.class);
intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intents);
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
}
*/
}
And this is my activity that is not getting launched:
package kor.location.tracker;
import android.Manifest;
import android.content.pm.PackageManager;
import android.nfc.Tag;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
Toast.makeText(getBaseContext(), "Hello........", Toast.LENGTH_LONG).show();
List<String> permissions = new ArrayList<String>();
if(getApplicationContext().checkCallingOrSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.INTERNET);
}
if(getApplicationContext().checkCallingOrSelfPermission(Manifest.permission.RECEIVE_BOOT_COMPLETED) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.RECEIVE_BOOT_COMPLETED);
}
if(getApplicationContext().checkCallingOrSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if(getApplicationContext().checkCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if(getApplicationContext().checkCallingOrSelfPermission(Manifest.permission.FOREGROUND_SERVICE) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.FOREGROUND_SERVICE);
}
if(permissions.size()>0) {
String[] arr = new String[permissions.size()];
permissions.toArray(arr);
//System.out.println();
ActivityCompat.requestPermissions(this, arr, 1);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
1- For Problem Starting Activity From Background
in API29 Android restricted, starting an activity from the background. The foreground service is also considered a background process. Your activity can be affected by this restriction if you test it in Android 10.
Android Q Restrictions: https://developer.android.com/guide/components/activities/background-starts
Possible solution:
https://stackoverflow.com/a/59421118/11982611
2- Some brands limits applications to start in the boot to boost start up time of the device. So applications need exclusive permission to start in the boot.
Possible Solution (Programmatically) :
https://stackoverflow.com/a/49167712/11982611
For Xiaomi, enabling Autostart from settings
https://dontkillmyapp.com/xiaomi
After I added the boot permissions in manifest file (see code below), BroadcastReceiver started to get boot completed event and the service is starting successfully. For the solution to work (as suggested by #Eren Tüfekçi) I had to enable auto start permission in phone settings for my application. If anyone has a solution, how to enable it programmatically, please let us know. Thank you.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="kor.location.tracker">
<uses-permission android:name="android.permission.INTERNET" ></uses-permission>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
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">
<receiver android:name="kor.location.tracker.AutoStart"
android:enabled="true"
android:exported="true">
<intent-filter android:directBootAware="true">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.REBOOT"/>
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:enabled="true"
android:name="kor.location.tracker.WorkerService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"
/>
</application>
</manifest>
Check this. In this way what you want to achieve should work. If you can not, logs should be followed to find out the problem.
public class AutoStart extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent arg1)
{
try {
Intent intent = new Intent(context, WorkerService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
}catch(Exception ex) {
Toast.makeText(context, ex.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
In Service
public class WorkerService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
public static final String NEW_CHANNEL_ID = "AndroidForegroundServiceChannel";
Notification notification;
#Override
public void onCreate() {
super.onCreate();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{createNotificationChannel(); //for Android Oreo above notification channel mandatory }
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{// if Android 10 create a pending intent and a full screen notification
Intent fullScreenIntent = new Intent(this, "Your Activity".class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 2022,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT); // For the activity opening when notification cliced
notification= new NotificationCompat.Builder(this, NEW_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("Notification title")
.setContentText("Notification Text")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_REMINDER)
.setFullScreenIntent(fullScreenPendingIntent, true)
.build();
startForeground(2, notification);
}
else
{
//if below Android 10 created a notification for foreground service because it is mandatory
Intent notificationIntent = new Intent(this, Your Activity.class);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this, 0022,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentText("Foreground Service")
.setSmallIcon(R.drawable.ic_notification)
.setSound(null)
.setContentIntent(pendingNotificationIntent)
.build();
//for below Android 10 started activity
Intent i = new Intent(getApplicationContext(), Your Activity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
getApplicationContext().startActivity(i);
}
startForeground(1, notification);
}
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(), "Foreground Service fault", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
return START_NOT_STICKY;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
NotificationChannel serviceChannel = new NotificationChannel(
NEW_CHANNEL_ID,
"Android Foreground Service Channel",
NotificationManager.IMPORTANCE_HIGH
);
serviceChannel.setSound(null,null);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
serviceChannel.setSound(null,null);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
I can still start the app on Boot. (Targeting API 29). By using broadcast receiver with intent ACTION_BOOT_COMPLETED.
The problem I faced after updating my android to version 9 on Honor brand of phone was introduction of advance app management for probably battery preservation which prevented my app from receiving the broadcast in the first place.
Go to Settings > Battery > App Launch > Go to your app and uncheck "Manage Automatically" > And make sure "Auto-launch", "Secondary launch", "Run in background" is checked and select "OK"
Reboot your phone and check if the app starts on boot or not. Hope this helps someone else.

Start a service in android

I have this service class
package com.example.test43;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class ProximityService extends Service {
private String PROX_ALERT_INTENT = "com.example.proximityalert";
private BroadcastReceiver locationReminderReceiver;
private LocationManager locationManager;
private PendingIntent proximityIntent;
//#override
public void onCreate() {
locationReminderReceiver = new ProximityIntentReceiver();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Toast.makeText(this, "created", Toast.LENGTH_LONG).show();
double lat = 55.586568;
double lng = 13.0459;
float radius = 1000;
long expiration = -1;
IntentFilter filter = new IntentFilter(PROX_ALERT_INTENT);
registerReceiver(locationReminderReceiver, filter);
Intent intent = new Intent(PROX_ALERT_INTENT);
intent.putExtra("alert", "Test Zone");
proximityIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
locationManager.addProximityAlert(lat, lng, radius, expiration, proximityIntent);
}
// #override
public void onDestroy() {
Toast.makeText(this, "Proximity Service Stopped", Toast.LENGTH_LONG).show();
try {
unregisterReceiver(locationReminderReceiver);
} catch (IllegalArgumentException e) {
Log.d("receiver", e.toString());
}
}
// #override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "Proximity Service Started", Toast.LENGTH_LONG).show();
}
//#override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public class ProximityIntentReceiver extends BroadcastReceiver {
private static final int NOTIFICATION_ID = 1000;
//#suppressWarnings("deprecation")
//#override
public void onReceive(Context arg0, Intent arg1) {
String place = arg1.getExtras().getString("alert");
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent pendingIntent = PendingIntent.getActivity(arg0, 0, arg1, 0);
Notification notification = createNotification();
notification.setLatestEventInfo(arg0, "Entering Proximity!", "You are approaching a " + place + " marker.", pendingIntent);
notificationManager.notify(NOTIFICATION_ID, notification);
locationManager.removeProximityAlert(proximityIntent);
}
private Notification createNotification() {
Notification notification = new Notification();
notification.icon = R.drawable.ic_launcher;
notification.when = System.currentTimeMillis();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.defaults |= Notification.DEFAULT_VIBRATE;
notification.defaults |= Notification.DEFAULT_SOUND;
return notification;
}
}
}
Here manifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test43"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service android:enabled="true" android:name="com.example.ProximityService" />
<activity
android:name="com.example.test43.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>
</application>
</manifest>
Main
package com.example.test43;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, ProximityService.class));
}
#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;
}
}
I want to know how do I start the service? I put a toast in the on create when the service starts just to know when starts but I don't see it. Am I doing something wrong here?
Any help would be appreciated
Your package name is incorrect when defining the service. Change you Service declaration in Androidmanifest.xml as below:
<service android:enabled="true"
android:name="com.example.test43.ProximityService" />

Categories

Resources