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
Related
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.
I have used Service to keep my scan for android mobiles even when the app is closed. I used Broadcast receiver to restart my service when killed. It restarts the scanning and it works only for some 15 seconds and then stops
When i click button1 in {MainActivity} I started the service and have called startdiscovery() in startCommand method in {ExampleService}
Please Help me in running the app in background
MainActivity.java
import android.Manifest;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.bluetooth.le.ScanResult;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.FirebaseFirestore;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
ListView scanListView;
ArrayList<String> stringArrayList = new ArrayList<String>();
ArrayAdapter<String> arrayAdapter;
static BluetoothAdapter myAdapter = BluetoothAdapter.getDefaultAdapter();
FirebaseFirestore db = FirebaseFirestore.getInstance();
static int count=0;
ScanResult sc;
String Uuid;
Date currentTime;
private LocationSettingsRequest.Builder builder;
private final int REQUEST_CHECK_CODE=8989;
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
LocationManager locationm;
String provider;
Button button1;
BluetoothAdapter bluetoothAdapter;
Intent btEnablingIntent;
int requestCodeForEnable;
Button button;
Button scanButton1;
RegisterActivity registerActivity=new RegisterActivity();
String email ;
String phone ;
///
Intent discoverableIntenet = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
Intent mServiceIntent;
private ExampleService mYourService;
Context ctx;
public Context getCtx() {
return ctx;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
currentTime = Calendar.getInstance().getTime();
setContentView(R.layout.activity_main);
checkLocationPermission();
btEnablingIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
requestCodeForEnable=1;
discoverableIntenet.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 3000);
startActivity(discoverableIntenet);
button=(Button) findViewById(R.id.button4);
Intent intent = new Intent(MainActivity.this,ble.class);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,ble.class);
MainActivity.this.startActivity(intent);
}
});
button=(Button) findViewById(R.id.button6);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
open(view);
}
});
button=(Button) findViewById(R.id.button3);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pdfs(view);
}
});
button=(Button) findViewById(R.id.button5);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
myths(view);
}
});
button1=(Button) findViewById(R.id.button2);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
analytics(view);
}
});
scanListView = (ListView) findViewById(R.id.scannedListView);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
scanButton1=(Button) findViewById(R.id.Button1);
scanButton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("disc","discoveeery!");
Log.i("hiiiiiii", String.valueOf(myAdapter.isDiscovering()));
Intent serviceIntent = new Intent(MainActivity.this, ExampleService.class);
serviceIntent.putExtra("inputExtra", "hi");
// startService( serviceIntent);
mYourService = new ExampleService();
mServiceIntent = new Intent(MainActivity.this, mYourService.getClass());
if (!isMyServiceRunning(mYourService.getClass())) {
startService(mServiceIntent);
}
}
});
bluetoothOnMethod();
BluetoothFunctions();
}
public void BluetoothFunctions(){
Log.d("disc", "discovery!");
IntentFilter intentFilter;
intentFilter=new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(myreceiver, intentFilter);
intentFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(myreceiver, intentFilter);
arrayAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, stringArrayList);
scanListView.setAdapter(arrayAdapter);
Uuid="02.020202.020.02";
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == requestCodeForEnable) {
if (resultCode == RESULT_OK) {
Toast.makeText(getApplicationContext(), "Bluetooth is enabled", Toast.LENGTH_LONG).show();
}
else if(resultCode==RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Bluetooth enabling cancelled", Toast.LENGTH_LONG).show();
}
}
}
final BroadcastReceiver myreceiver = new BroadcastReceiver() {
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getName() == null) {
return;
}
String address = device.getName();
int N = 2;
float type = intent.getFloatExtra((BluetoothDevice.EXTRA_UUID),Float.MIN_VALUE);
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
String rssi_val = String.valueOf(rssi);
String data = device.getAddress() + " " + rssi_val;
Vibrator v1 = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
stringArrayList.add(data);
if (rssi >= -50) {
v1.vibrate(VibrationEffect.createOneShot(1000, VibrationEffect.DEFAULT_AMPLITUDE));
count++;
if (device.getAddress() != null) {
Firebasepush(device.getAddress(), rssi_val);
}
}
Log.i("lll", device.getAddress());
Log.i("lll", device.getName());
Log.i("+>>>>>>>>>>>>>", BluetoothDevice.EXTRA_UUID);
Log.i("lll", rssi_val);
arrayAdapter.notifyDataSetChanged();
// Toast.makeText(getApplicationContext()," TX power: " +sc.getTxPower() + "dBm", Toast.LENGTH_SHORT).show();
//startThread();
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.v("ggggggggg", "Entered the Finished ");
myAdapter.startDiscovery();
}
}
};
public void Firebasepush(String uuid,String rrsi){
Map<String, Object> updateMap = new HashMap();
updateMap.put("RSSI", rrsi);
updateMap.put("time", currentTime);
Map<String, Object> countMap = new HashMap();
countMap.put("Count", count);
countMap.put("time", currentTime);
countMap.put("Name",registerActivity.NameString);
countMap.put("Email",registerActivity.EmailId);
countMap.put("Phone Number",registerActivity.PhoneNumber);
// Add a new document with a generated ID
db.collection("users").document(Uuid).collection("contacts").document(uuid)
.set(updateMap);
db.collection("users").document(Uuid).
set(countMap);
}
void bluetoothOnMethod() {
if(bluetoothAdapter==null){
Toast.makeText(getApplicationContext(), "Bluetooth does not support ",Toast.LENGTH_LONG).show();
}
else {
if(!bluetoothAdapter.isEnabled()){
startActivityForResult(btEnablingIntent,requestCodeForEnable);
}
}
}
public boolean checkLocationPermission() {
LocationRequest request = new LocationRequest()
.setFastestInterval(1500)
.setInterval(3000)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
builder = new LocationSettingsRequest.Builder()
.addLocationRequest(request);
Task<LocationSettingsResponse> result = LocationServices.getSettingsClient( this).checkLocationSettings(builder.build());
result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
#Override
public void onComplete(#NonNull Task<LocationSettingsResponse> task) {
try{
task.getResult(ApiException.class);
}catch (ApiException e){
switch (e.getStatusCode())
{
case LocationSettingsStatusCodes
.RESOLUTION_REQUIRED:
try {
ResolvableApiException resolvableApiException= (ResolvableApiException) e;
resolvableApiException.startResolutionForResult(MainActivity.this,REQUEST_CHECK_CODE);
} catch (IntentSender.SendIntentException ex) {
ex.printStackTrace();
}catch (ClassCastException ex){
}break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
{ break;}
}
}
}
});
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
new AlertDialog.Builder(this)
.setTitle(R.string.title_location_permission)
.setMessage(R.string.text_location_permission)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.create()
.show();
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Request location updates:
// locationm.requestLocationUpdates(provider, 400, 1,this);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.i ("Service status", "Running");
return true;
}
}
Log.i ("Service status", "Not running");
return false;
}
#Override
protected void onDestroy() {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, Restarter.class);
this.sendBroadcast(broadcastIntent);
super.onDestroy();
// Don't forget to unregister the ACTION_FOUND receiver.
// unregisterReceiver(myreceiver);
}
public void openservices(){
Intent intnt=new Intent(this ,Services.class);
startActivity(intnt);
}
public void open(View view)
{
Intent browserIntent=new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.hogist.com/#/"));
startActivity(browserIntent);
}
public void pdfs(View view)
{
Intent browserIntent=new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.mohfw.gov.in/pdf/Illustrativeguidelineupdate.pdf"));
startActivity(browserIntent);
}
public void myths(View view)
{
Intent browserIntent=new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.mohfw.gov.in/pdf/Illustrativeguidelineupdate.pdf"));
startActivity(browserIntent);
}
public void analytics(View view){
final Intent intent1 = new Intent(MainActivity.this, Analytics.class);
startActivity(intent1);
}
}
ExampleService.java
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import java.util.Timer;
import java.util.TimerTask;
public class ExampleService extends Service {
BluetoothAdapter myAdapter = BluetoothAdapter.getDefaultAdapter();
MainActivity mainActivity=new MainActivity();
public int counter=0;
#Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
}
#RequiresApi(Build.VERSION_CODES.O)
private void startMyOwnForeground()
{
String NOTIFICATION_CHANNEL_ID = "example.permanence";
String channelName = "Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
// startTimer();
myAdapter.startDiscovery();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// stoptimertask();
myAdapter.cancelDiscovery();
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, Restarter.class);
this.sendBroadcast(broadcastIntent);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}```
Restarter.java
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 Restarter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Broadcast Listened", "Service tried to stop");
Toast.makeText(context, "Service restarted", Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.i(Restarter.class.getSimpleName(), "Service Stops! Oooooooooooooppppssssss!!!!");
context.startForegroundService(new Intent(context, ExampleService.class));
} else {
context.startService(new Intent(context, ExampleService.class));
}
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hogist_social_distancing">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".App"
android:fullBackupContent="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=".Analytics"
android:screenOrientation="portrait" />
<activity
android:name=".Services"
android:screenOrientation="portrait" />
<activity
android:name=".Permissions"
android:screenOrientation="portrait" />
<activity
android:name=".MainActivity"
android:screenOrientation="portrait" />
<activity android:name=".RegisterActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".OTPActivity" />
<activity android:name=".ble" />
<service
android:name=".ExampleService"
android:enabled="true" />
<receiver
android:name="Restarter"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="restartservice" />
</intent-filter>
</receiver>
</application>
</manifest>```
Android strives to save the battery, so it's expected that your service is stopped, especially if it runs battery draining operations such as Bluetooth scans.
Also, bare in mind that starting from Android 7, an app cannot start the BLE scan more than 5 times per 30 seconds, as mentioned here. Other issues related to BLE scanning are listed here.
If you do want to run Bluetooth scans in the background, I suggest you use a JobIntentService, in which you start BLE scan for a few seconds.
JobIntentService is very similar to IntentService but with few benefits like holding a wake lock which prevents the CPU to go to sleep
Also, this type of service does not require displaying a notification to your user. For more info: https://developer.android.com/reference/androidx/core/app/JobIntentService
are you sure your bluetooth code can work well on activity (without service)?
you can not restart your service by call Broadcast when you service was killed, because when your service was killed by OS system, it will kill your application process so your broadcast will not work. When you call return START_STICKY; it means system will automatic restart your service when it have available resource
I have an app (activity). I want it to stay running even if screen goes off, but older solution don't work. As i understand the only solution is to make a service. But is it easy to transform an activity to service?The method with wake lock can't be used any more, as it is deprecated.
Create Foreground Service as below.
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
public class ForegroundService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentIntent(pendingIntent)
.build();
startForeground(1001, notification);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
Dont forget to declarer the service in manifest.
I am creating an android app that consists of android push notifications.Here i need the push notifications that will run even when the app was closed. I had achieved it by calling the notification in a service. But here when i was running the code in the android >5.x devices my code was running perfectly even when app was closed notification was coming for every 5 sec but when i was running app on devices <5.x notifications was displaying only when the app was opened or when it was minimised not receiving any notifications when app was closed can any one help me what my mistake is and this is my code
SERVICE:
package com.example.servicesandroid;
import java.util.Timer;
import java.util.TimerTask;
import com.example.servicesandroid.MainActivity.MyTimerTask;
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.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
public class Androidservice extends Service {
final static String ACTION = "NotifyServiceAction";
final static String STOP_SERVICE = "";
final static int RQS_STOP_SERVICE = 1;
NotifyServiceReceiver notifyServiceReceiver;
private static final int MY_NOTIFICATION_ID = 1;
private NotificationManager notificationManager;
private Notification myNotification;
Timer timer;
TimerTask timer_task;
Handler handler;
#Override
public void onCreate() {
// TODO Auto-generated method stub
notifyServiceReceiver = new NotifyServiceReceiver();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyTimerTask myTask = new MyTimerTask();
Timer myTimer = new Timer();
myTimer.schedule(myTask, 5000, 1500);
// TODO Auto-generated method stub
return Service.START_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
this.unregisterReceiver(notifyServiceReceiver);
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public class NotifyServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
int rqs = arg1.getIntExtra("RQS", 0);
if (rqs == RQS_STOP_SERVICE) {
stopSelf();
}
}
}
class MyTimerTask extends TimerTask {
public void run() {
generateNotification(getApplicationContext(), "Hello");
}
}
private void generateNotification(Context context, String message) {
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
String appname = context.getResources().getString(R.string.app_name);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
Notification notification;
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
// To support 2.3 os, we use "Notification" class and 3.0+ os will use
// "NotificationCompat.Builder" class.
if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
notification = new Notification(icon, message, 0);
notification.setLatestEventInfo(context, appname, message,
contentIntent);
notification.flags = Notification.FLAG_AUTO_CANCEL;
notificationManager.notify((int) when, notification);
} else {
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context);
notification = builder.setContentIntent(contentIntent)
.setSmallIcon(icon).setTicker(appname).setWhen(0)
.setAutoCancel(true).setContentTitle(appname)
.setContentText(message).build();
notificationManager.notify((int) when, notification);
}
}
}
This is my activity:
package com.example.servicesandroid;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent serviceIntent = new Intent(MainActivity.this,Androidservice.class);
startService(serviceIntent);
}
This is my Broadcast receiver when device reboots:
package com.example.servicesandroid;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class Boot_Completed extends BroadcastReceiver {
private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if(intent.getAction().equals(BOOT_COMPLETED_ACTION)){
Intent myIntent = new Intent(context, Androidservice.class);
context.startService(myIntent);
}
}
}
This is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicesandroid"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.WAKE_LOCK" />
<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" >
<activity
android:name=".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>
<service android:name=".Androidservice"/>
<receiver android:name=".Boot_Completed" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
Please any one help me with this
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" />