I have android background service to connect with my RabbitMQ server. My background service listen incoming rabbitmq message. Everything is working well but the problem is appear while screen goes off. My android client disconnect when phone screen goes off. What should I do to always connected with my android rabbitmq client and rabbitmq server ?
My code are below :
public class RabbitmqPushService extends Service{
private Thread subscribeThread;
private ConnectionFactory factory;
private Connection connectionSubscribe;
private Channel channelSubscribe;
private NotificationManager mNotificationManager;
public static int NOTIFICATION_ID = 0;
private static final String HOST_NAME = Constant.HOST_NAME; //Rabbitmq Host Name
private static final int PORT_ADDRESS = 5672;
private static final String EXCHANGE_NAME = "fanout_msg";
private static String QUEUE_NAME = Constant.phone_number+"_queue"; //Queue Name
private static String[] ROUTE_KEY = {"all", Constant.phone_number};
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
NOTIFICATION_ID = 0;
setupConnectionFactory();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(connectionSubscribe != null)
{
if(!connectionSubscribe.isOpen())
{
connect();
}
}
else
{
connect();
}
return Service.START_STICKY;
}
#Override
public void onDestroy() {
if(connectionSubscribe != null)
{
disconnectSubscribe();
}
NOTIFICATION_ID = 0;
}
private void setupConnectionFactory() {
factory = new ConnectionFactory();
factory.setHost(HOST_NAME);
factory.setPort(PORT_ADDRESS);
factory.setUsername(Constant.USERNAME);
factory.setPassword(Constant.PASSWORD);
factory.setRequestedHeartbeat(60);
}
private void connect()
{
final Handler incomingMessageHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String message = msg.getData().getString("msg");
try {
JSONObject jsonObject = new JSONObject(message);
BeepHelper.msgBeep(getApplicationContext());
sendNotification("From : " + jsonObject.getString("from"), jsonObject.getString("message"));
} catch (JSONException e) {
e.printStackTrace();
}
}
};
subscribe(incomingMessageHandler);
publishToAMQP();
}
private void disconnectSubscribe()
{
subscribeThread.interrupt();
try {
channelSubscribe.close();
connectionSubscribe.close();
} catch (IOException e) {
e.printStackTrace();
}
catch (TimeoutException e) {
e.printStackTrace();
}
}
void subscribe(final Handler handler)
{
subscribeThread = new Thread()
{
#Override
public void run() {
while(true) {
try {
connectionSubscribe = factory.newConnection();
channelSubscribe = connectionSubscribe.createChannel();
channelSubscribe.exchangeDeclare(EXCHANGE_NAME, "fanout");
channelSubscribe.queueDeclare(QUEUE_NAME, true, false, false, null);
for(int i = 0; i<ROUTE_KEY.length; i++)
{
channelSubscribe.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTE_KEY[i]);
}
QueueingConsumer consumer = new QueueingConsumer(channelSubscribe);
channelSubscribe.basicConsume(QUEUE_NAME, false, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
Message msg = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putString("msg", message);
msg.setData(bundle);
handler.sendMessage(msg);
channelSubscribe.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
} catch (InterruptedException e) {
break;
} catch (Exception e1) {
try {
Thread.sleep(4000); //sleep and then try again
} catch (InterruptedException e) {
break;
}
}
}
}
};
subscribeThread.start();
}
#Override
public void publishMessage(String message) {
try {
queue.putLast(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void sendNotification(String title, String msg) {
mNotificationManager = (NotificationManager)
getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0,
new Intent(getApplicationContext(), MainActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID++, mBuilder.build());
}
}
You need a Wake Lock to keep the phone running when screen is off. Wake locks allow your application to control the power state of the host device.
Add the WAKE_LOCK permission to your application's manifest file:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Then add the following in onCreate():
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakelock= pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getCanonicalName());
wakelock.acquire();
If your app includes a broadcast receiver that uses a service to do some work, you can manage your wake lock through a WakefulBroadcastReceiver. This is the preferred approach. If your app doesn't follow that pattern, you set a wake lock directly.
Related
I am using this source app to chat with other devices. But how to make it to start like a Service so I can to start foreground service.
Do I need MainFragment and LoginActivity rewrite in Service?
socket.io app socket.io-android-chat
I have tried something like that in class SocketService, what other I need to include in Service for App to get notification messages even if app is closed.
public class SocketService extends Service {
private Socket mSocket;
public static final String TAG = SocketService.class.getSimpleName();
private static final String NOTIFICATION_CHANNEL_ID_DEFAULT = "App running in background";
String GROUP_KEY_WORK_EMAIL = "com.android.example.WORK_EMAIL";
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "on created", Toast.LENGTH_SHORT).show();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setGroup(GROUP_KEY_WORK_EMAIL);
Notification notification = builder.build();
NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
// Set big text style.
builder.setStyle(bigTextStyle);
startForeground(3, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "start command", Toast.LENGTH_SHORT).show();
try {
mSocket = IO.socket(Constants.CHAT_SERVER_URL);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
mSocket.on("newMessageReceived", onNewMessage);
mSocket.connect();
return START_STICKY;
}
private Emitter.Listener onNewMessage = new Emitter.Listener() {
#Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
String username;
String message;
try {
username = data.getString("username");
message = data.getString("message");
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
return;
}
Log.d(TAG, "call: new message ");
setNotificationMessage(message, username);
}
};
public void setNotificationMessage(CharSequence message, CharSequence title) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle(title);
builder.setContentText(message);
NotificationManagerCompat nm = NotificationManagerCompat.from(this);
nm.notify(3, builder.build());
}
}
you shouldn't use a foreground service in order to get notification messages when your app is in the background
instead you should use firebase push notification
however if you still need to use the socket connection in your foreground service
just simply create a singleton class to handle all socket connection and use it your foreground service as shown below
public class SocketManger {
private static SocketManger socketManger;
Socket socket;
Callback<Boolean> onConnect;
public void init(Callback<Boolean> onConnect){
this.onConnect = onConnect;
connectToSocket();
listenToPublicEvents();
}
private void connectToSocket(){
try{
IO.Options opts = new IO.Options();
//optional parameter for authentication
opts.query = "token=" + YOUR_TOKEN;
opts.forceNew = true;
opts.reconnection = true;
opts.reconnectionDelay = 1000;
socket = IO.socket(YOUR_URL, opts);
socket.connect();
}
catch(URISyntaxException e){
throw new RuntimeException(e);
}
}
private void listenToPublicEvents(){
socket.on(Socket.EVENT_CONNECT, args -> {
if(onConnect!=null)
onConnect.onResult(true);
} );
socket.on(Socket.EVENT_DISCONNECT, args ->{
if(onConnect!=null)
onConnect.onResult(false);
});
}
public void emit(String event, JSONObject data, Ack ack){
socket.emit(event, new JSONObject[]{data}, ack);
}
public void on(String event, Emitter.Listener em){
socket.on(event, em);
}
public static SocketManger getSocketManger() {
if(socketManger == null){
socketManger = new SocketManger();
}
return socketManger;
}
public boolean isConnected(){
return socket!=null && socket.connected();
}
public void onDestroy() {
onConnect = null;
socket.disconnect();
}
public interface Callback<T> {
void onResult(T t);
}
}
and add this code to your foreground service
SocketManager socketManger = SocketManger.getSocketManger();
#Override
public void onCreate() {
socketManger.init(this::onSocketEvent);
}
public void onSocketEvent(boolean connect){
//your code when the socket connection connect or disconnect
}
and make sure to disconnect the socket when the service is destroyed
#Override
public void onDestroy() {
socketManger.onDestroy()
super.onDestroy();
}
You can start it from a custom Application class in onCreate method if you want the service to be started immediately after the app is launched.
Or you you can start it from any Activity eg. from onCreate method in case you want to start the service from certain activity.
Or you can start from BroadcastReceiver when device is booted. In this case use BOOT_COMPLETED action:
To start your service just use this code, anywhere you want to start your service:
Intent intent = new Intent(context, SocketService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
I have a drawerlayout and he call many fragments and they have asynctask within, also i have created a notification service, it's work very fine in api level < 11 but when the level is > 10 the asynctask of fragment only work when the service is not running, why?
My code of service is here
public class NotificationService extends Service {
MyTask myTask;
private final String url_notificaciones = "http://www.domain.com/domain/getNotificaciones.php";
private static final String TAG_TIPO_NOTIFICACION = "tipo_notificacion";
private static final String TAG_TITULO_NOTIFICACION= "titulo_notificacion";
private static final String TAG_DESCRIPCION_NOTIFICACION= "descripcion_notificacion";
private String jsonResult;
SessionManagement session;
boolean InitializeNotificationManager = true;
private HashMap<String, String> user;
private String id_datos_usuarios_session;
private JsonReadTask task;
private Handler handler = new Handler();
private TaskCanceler taskCanceler;
#Override
public void onCreate() {
super.onCreate();
try {
session = new SessionManagement(getApplication());
user = session.getUserDetails();
id_datos_usuarios_session = user.get(SessionManagement.KEY_ID_DATOS_USUARIOS).toString();
}catch (Exception e){
InitializeNotificationManager = false;
}
myTask = new MyTask();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
myTask.execute();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
myTask.cancel(true);
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
private class MyTask extends AsyncTask<String, String, String> {
private String date;
private boolean cent;
#Override
protected void onPreExecute() {
super.onPreExecute();
cent = true;
}
#Override
protected String doInBackground(String... params) {
while (cent) {
try {
if(isNetworkStatusAvialable (getApplication())) {
accessWebService();
}
// Stop 20s
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
//Toast.makeText(getApplicationContext(), "Hora actual: ", Toast.LENGTH_SHORT).show();
}
#Override
protected void onCancelled() {
super.onCancelled();
cent = false;
}
}
public void accessWebService(){
task = new JsonReadTask();
taskCanceler = new TaskCanceler(task);
handler.postDelayed(taskCanceler, 15*1000);
task.execute(new String[]{url_notificaciones});
}
private class JsonReadTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("get_app_id_datos_usuarios", id_datos_usuarios_session));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
jsonResult = inputStreamToString(
response.getEntity().getContent()).toString();
}
catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
} catch (IOException e) {
// e.printStackTrace();
Toast.makeText(getApplicationContext(),
"Error..." + e.toString(), Toast.LENGTH_LONG).show();
}
return answer;
}
#Override
protected void onPostExecute(String result) {
ListDrwaer();
}
// build hash set for list view
public void ListDrwaer() {
try {
JSONObject jsonResponse = new JSONObject(jsonResult);
JSONArray jsonMainNode = jsonResponse.optJSONArray("notification");
JSONObject jsonChildNode = jsonMainNode.getJSONObject(0);
String tipo_notificacion = jsonChildNode.getString(TAG_TIPO_NOTIFICACION);
String titulo_notificacion = jsonChildNode.getString(TAG_TITULO_NOTIFICACION);
String descripcion_notificacion = jsonChildNode.getString(TAG_DESCRIPCION_NOTIFICACION);
if(tipo_notificacion.equals("1")) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra("MenuNotificationFragment", "MyFriendsRequired");
PendingIntent pIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
// Creamos la notificación. Las acciones son de "mentirijilla"
Notification noti = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(titulo_notificacion)
.setContentText(descripcion_notificacion).setSmallIcon(R.mipmap.icon_app)
.setContentIntent(pIntent)
.setLights(0xffff00, 4000, 100)
/*.addAction(R.drawable.ic_arrow, "Llamada", pIntent)
.addAction(R.drawable.ic_arrow, "Más", pIntent)
.addAction(R.drawable.ic_arrow, "Mucho Más", pIntent)*/.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Ocultamos la notificación si ha sido ya seleccionada
noti.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, noti);
//Sound notification
try {
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
ringtone.play();
} catch (Exception e) {
}
//Vibrate notification
try {
// Get instance of Vibrator from current Context
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Start without a delay
// Vibrate for 100 milliseconds
// Sleep for 1000 milliseconds
long[] pattern = {0, 100, 2000};
// The '0' here means to repeat indefinitely
// '0' is actually the index at which the pattern keeps repeating from (the start)
// To repeat the pattern from any other point, you could increase the index, e.g. '1'
v.vibrate(pattern, -1);
} catch (Exception e) {
}
}else if(tipo_notificacion.equals("2")){
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra("MenuNotificationFragment", "MyBussinesRequired");
PendingIntent pIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
// Creamos la notificación. Las acciones son de "mentirijilla"
Notification noti = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(titulo_notificacion)
.setContentText(descripcion_notificacion).setSmallIcon(R.mipmap.icon_app)
.setContentIntent(pIntent)
.setLights(0xffff00, 4000, 100)
/*.addAction(R.drawable.ic_arrow, "Llamada", pIntent)
.addAction(R.drawable.ic_arrow, "Más", pIntent)
.addAction(R.drawable.ic_arrow, "Mucho Más", pIntent)*/.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Ocultamos la notificación si ha sido ya seleccionada
noti.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, noti);
//Sound notification
try {
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
ringtone.play();
} catch (Exception e) {
}
//Vibrate notification
try {
// Get instance of Vibrator from current Context
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Start without a delay
// Vibrate for 100 milliseconds
// Sleep for 1000 milliseconds
long[] pattern = {0, 100, 2000};
// The '0' here means to repeat indefinitely
// '0' is actually the index at which the pattern keeps repeating from (the start)
// To repeat the pattern from any other point, you could increase the index, e.g. '1'
v.vibrate(pattern, -1);
} catch (Exception e) {
}
}
} catch (JSONException e) {
}
}
}// end async task
//If the internet connection is ok
public static boolean isNetworkStatusAvialable (Context context) {
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
NetworkInfo netInfos = connectivityManager.getActiveNetworkInfo();
if (netInfos != null)
if (netInfos.isConnected())
return true;
}
}catch (Exception e){
return false;
}
return false;
}
public class TaskCanceler implements Runnable{
private AsyncTask taskR;
public TaskCanceler(AsyncTask task) {
this.taskR = task;
}
#Override
public void run() {
if (task.getStatus() == AsyncTask.Status.RUNNING ) {
task.cancel(true);
}
}
}
}
Starting on Android 11 AsyncTask objects shares a single thread. So your service is blocking that thread, and the fragments can't run. The easiest solution is pretty obvious here, don't use AsyncTask for the service. It doesn't even make sense to use it there because AsyncTask is meant to deliver results back on the UI thread, something your service doesn't need to do. Here is a possible solution:
public class MyService extends Service implements Runnable {
private HandlerThread = ht;
private Handler handler;
#Override
public void onCreate() {
super.onCreate();
try {
session = new SessionManagement(getApplication());
user = session.getUserDetails();
id_datos_usuarios_session = user.get(SessionManagement.KEY_ID_DATOS_USUARIOS).toString();
}catch (Exception e){
InitializeNotificationManager = false;
}
ht = new HandlerThread("MyService");
ht.start();
handler = new Handler(ht.getLooper());
handler.post(this);
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(this);
ht.quit();
ht = null;
handler = null;
}
#Override
public void run(){
if(isNetworkStatusAvialable (getApplication())) {
accessWebService();
}
handler.postDelayed(20000, this);
}
}
I code a service to subscribe message from mqtt server. Service auto reconnect when internet connection on/off.
This code:
public class NotificationService extends Service{
private Handler connectBrokerHandler;
private ConnectBrokerTimerTask connectBrokerTimerTask;
private Timer connectBrokerTimer;
private MqttAndroidClient androidClient;
private MqttConnectOptions connectOptions;
private MemoryPersistence memPer;
private IMqttToken connectToken;
private CustomActionListener customActionListener;
private Context context;
private String CLIENT_STATUS = CLIENT_INIT;
private static final String TAG = "NotificationService";
private static final String USER_NAME = "chuxuanhy";
private static final String PASS_WORD = "0936160721";
private static final String URL_BROKER = "tcp://ntm.diyoracle.com:1883";
private static final String TOPIC_STAFF = "PROSHIP_STAFF";
private static final String DEVICE_ID = "FUCKYOU_002";
private static final int CONNECTION_TIMEOUT = 60;
private static final int KEEP_ALIVE_INTERVAL = 60*60;
private static final int TRY_CONNECTION_DELAY = 30; //seconds
private static final String CLIENT_INIT = "CLIENT_INIT";
private static final String CLIENT_CONNECTION_BROKER_START = "CLIENT_CONNECTION_BROKER_START";
private static final String CLIENT_CONNECTION_BROKER_FAIL = "CLIENT_CONNECTION_BROKER_FAIL";
private static final String CLIENT_CONNECTION_BROKER_SUCCESS = "CLIENT_CONNECTION_BROKER_SUCCESS";
private static final String CLIENT_LOST_CONNECTION = "CLIENT_LOST_CONNECTION";
private static final String CLIENT_SUBSCRIBE_TOPIC_START = "CLIENT_SUBSCRIBE_TOPIC_START";
private static final String CLIENT_SUBSCRIBE_TOPIC_FAIL = "CLIENT_SUBSCRIBE_TOPIC_FAIL";
private static final String CLIENT_SUBSCRIBE_TOPIC_SUCCESS = "CLIENT_SUBSCRIBE_TOPIC_SUCCESS";
private IntentFilter FilterNetwork;
private BroadcastReceiver ReceiverCheckInternet = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(isOnline()){
if(CLIENT_STATUS == CLIENT_LOST_CONNECTION || CLIENT_STATUS == CLIENT_CONNECTION_BROKER_FAIL || CLIENT_STATUS == CLIENT_SUBSCRIBE_TOPIC_FAIL) {
ConnectBroker();
}
}
}
};
private class ConnectBrokerTimerTask extends TimerTask{
#Override
public void run() {
connectBrokerHandler.post(ConnectBrokerRunable);
}
}
private Runnable ConnectBrokerRunable = new Runnable() {
#Override
public void run() {
ConnectBroker();
}
};
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
public void RestartNotificationService(){
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent);
}
public void createNotification(String title, String body) {
Intent intent = new Intent(this, NotificationReceiver.class);
PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext());
Notification notification = mBuilder.setSmallIcon(R.drawable.train).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setStyle(new NotificationCompat.BigTextStyle().bigText(body))
.setContentIntent(pIntent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setVibrate(new long[]{1000, 1000})
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.ic_launcher))
.setContentText(body).build();
Random random = new Random();
int m = random.nextInt(9999 - 1000) + 1000;
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(m, notification);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
try{
RestartNotificationService();
}catch (Exception e){
e.printStackTrace();
}
super.onTaskRemoved(rootIntent);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(ReceiverCheckInternet);
Log.e(TAG, "onDestroy");
try{
if(androidClient.isConnected()){
this.androidClient.unsubscribe(TOPIC_STAFF);
this.androidClient.disconnect();
this.androidClient = null;
}
}catch (Exception e){
e.printStackTrace();
}
}
private void ConnectBroker(){
try {
CLIENT_STATUS = CLIENT_CONNECTION_BROKER_START;
connectToken = this.androidClient.connect(connectOptions,null,customActionListener);
}catch (Exception e){
//e.printStackTrace();
Log.e(TAG, "ConnectBroker Fail Exception");
}
}
private void SubscribeBrokerTopic(String topic){
try {
CLIENT_STATUS = CLIENT_SUBSCRIBE_TOPIC_START;
androidClient.subscribe(topic, 0, null, customActionListener);
} catch (Exception e) {
//e.printStackTrace();
Log.e(TAG, "SubscribeBrokerTopic Fail Exception");
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("NOTIFI","CALL ME onStartCommand");
this.connectBrokerHandler = new Handler();
this.connectBrokerTimer = new Timer();
this.connectBrokerTimerTask = new ConnectBrokerTimerTask();
this.customActionListener = new CustomActionListener();
this.memPer = new MemoryPersistence();
this.connectOptions = new MqttConnectOptions();
this.connectOptions.setCleanSession(true);
this.connectOptions.setUserName(USER_NAME);
this.connectOptions.setPassword(PASS_WORD.toCharArray());
this.connectOptions.setConnectionTimeout(CONNECTION_TIMEOUT);
this.connectOptions.setKeepAliveInterval(KEEP_ALIVE_INTERVAL);
this.androidClient = new MqttAndroidClient(getApplicationContext(),URL_BROKER,DEVICE_ID,memPer);
this.androidClient.setCallback(new CustomCallBack());
this.androidClient.setTraceCallback(new CustomTraceHandler());
//this.androidClient.
this.FilterNetwork = new IntentFilter();
this.FilterNetwork.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(ReceiverCheckInternet, FilterNetwork);
//this.androidClient.registerResources(getApplicationContext());
ConnectBroker();
return START_NOT_STICKY;
}
private class CustomTraceHandler implements MqttTraceHandler{
#Override
public void traceDebug(String source, String message) {
Log.e(TAG,"CustomConnectHandler - traceDebug\n"+source+" - "+message);
}
#Override
public void traceError(String source, String message) {
Log.e(TAG, "CustomConnectHandler - traceError\n" + source + " - " + message);
}
#Override
public void traceException(String source, String message, Exception e) {
Log.e(TAG, "CustomConnectHandler - traceException\n" + source + " - " + message);
e.printStackTrace();
}
}
private class CustomCallBack implements MqttCallback{
#Override
public void connectionLost(Throwable throwable) {
CLIENT_STATUS = CLIENT_LOST_CONNECTION;
if(!isOnline()){
Log.e(TAG, "ConnectCallBack connectionLost - No Internet Connection ");
}else {
//throwable.printStackTrace();
}
}
#Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
Log.e(TAG,"ConnectCallBack messageArrived\n"+s+" - "+mqttMessage.toString());
createNotification(s, mqttMessage.toString());
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
Log.e(TAG, "ConnectCallBack deliveryComplete");
}
}
private class CustomActionListener implements IMqttActionListener {
#Override
public void onSuccess(IMqttToken iMqttToken) {
if (CLIENT_STATUS == CLIENT_CONNECTION_BROKER_START) {
CLIENT_STATUS = CLIENT_CONNECTION_BROKER_SUCCESS;
if (iMqttToken.getTopics() == null) {
SubscribeBrokerTopic(TOPIC_STAFF);
}
Log.e(TAG, "CustomActionListener - CONNECT BROKER onSuccess");
} else if (CLIENT_STATUS == CLIENT_SUBSCRIBE_TOPIC_START) {
CLIENT_STATUS = CLIENT_SUBSCRIBE_TOPIC_SUCCESS;
Log.e(TAG, "CustomActionListener - SUBSCRIBE TOPIC onSuccess");
}
}
#Override
public void onFailure(IMqttToken iMqttToken, Throwable throwable) {
if (CLIENT_STATUS == CLIENT_CONNECTION_BROKER_START) {
CLIENT_STATUS = CLIENT_CONNECTION_BROKER_FAIL;
Log.e(TAG, "CustomActionListener - CONNECT BROKER onFailure ");
} else if (CLIENT_STATUS == CLIENT_SUBSCRIBE_TOPIC_START) {
CLIENT_STATUS = CLIENT_SUBSCRIBE_TOPIC_FAIL;
Log.e(TAG, "CustomActionListener - SUBSCRIBE TOPIC onFailure ");
}
if (isOnline()) {
throwable.printStackTrace();
//connectBrokerTimer.scheduleAtFixedRate(connectBrokerTimerTask, 5000, TRY_CONNECTION_DELAY * 1000);
}else {
Log.e(TAG, "CustomActionListener onFailure - No Internet Connection ");
}
}
}
}
But i have a problem, every time internet connection lost, i reconnect server, callback call again.
Example:
Log.e(TAG, "ConnectCallBack connectionLost - No Internet Connection ");
call twice, 3 time, 4 time every disconnect internet
Sorry my english not good, thank for help.
Don't handle the re-connection manually, newer version of paho has option to auto reconnect in MqttConnectOptions class.
compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.1'
compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
Suppose, Android app is detecting 3 beacons with in range with default UUID value. So, how can i set/change the name for each beacons in Anndroid (to identify each beacon)?
Appreciations for any suggestions... Thanks
Beacons are identified not only by UUID, but also by their major and minor values, and this whole set (UUID + Major + Minor) is how you can differentiate between them.
Moreover, these values are hierarchical in nature, which allows you to put some structure into your beacon deployment. Consider this example:
Whole Museum: UUID = B9407F30-F5F8-466E-AFF9-25556B57FE6D
North Wing: Major = 1
Exhibit A: Minor = 1
Exhibit B: Minor = 2
South Wing: Major = 2
This way, when your device comes in range of a beacon B9407F30-F5F8-466E-AFF9-25556B57FE6D:1:2, just by looking at it you'll know that it's at the North Wing, Exhibit B.
this is i got a solution to set different ids for different beacons. and also identifying differnet beacons and sending notifications to the user when app not in foreground.
I initially confused where to change Major and Minor values of beacons.
Simply, i installed Estimote Android app from Playstore
here,
1. Click on Beacons
2. Select one beacon and it displays one more detailed activity in that you can change Values (for me i changed Minor values for all beacon based on my requirement).
So, now Minor values for all beacons changed as per your requirement. After that find the below code
In this below code I am sending notification if App is in background or else i am dirctly updating statuses in Activity main class.
I changed Beacons values as 1,2,3,4.
public class BeaconMyService extends Service {
private static final String TAG = "BeaconMyService";
private final Handler handler = new Handler();
private BeaconManager beaconManager;
private NotificationManager notificationManager;
private static final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("rid",
null, null, null);
private static final int NOTIFICATION_ID = 123;
private Messenger messageHandler;
Bundle extras;
private String notifyMsg ="";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
extras = intent.getExtras();
messageHandler = (Messenger) extras.get("MESSENGER");
} catch (Exception e) {
// TODO: handle exception
}
Log.e(TAG, "Called=============");
if (beaconManager.isBluetoothEnabled()) {
connectToService();
}
return Service.START_NOT_STICKY;
}
private void connectToService() {
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
try {
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
} catch (RemoteException e) {
Log.e("Myservice",
"Cannot start ranging, something terrible happened");
Log.e("", "Cannot start ranging", e);
}
}
});
}
#Override
public void onCreate() {
super.onCreate();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
beaconManager = new BeaconManager(this);
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region region,
final List<Beacon> beacons) {
// Note that beacons reported here are already sorted by
// estimated
// distance between device and beacon.
for (int index = 0; index < beacons.size(); index++) {
Beacon beacon = beacons.get(index);
if (beacon != null) {
if (beacons.size() > 0) {
if (Utils.computeAccuracy(beacons.get(0)) < 1.0) {
try {
switch (beacons.get(0).getMinor()) {
case 1:
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = beacons.get(0)
.getMinor();
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
postNotification(beacons.get(0)
.getMinor()
+ ". Welcome to Media Lab");
}
break;
case 2:
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = beacons.get(0)
.getMinor();
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
postNotification(beacons.get(0)
.getMinor()
+ ". Welcome to Gaming Zone");
}
break;
case 3:
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = beacons.get(0)
.getMinor();
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
postNotification(beacons.get(0)
.getMinor()
+ ". Welcome to eLearing Education");
}
break;
case 4:
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = beacons.get(0)
.getMinor();
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
postNotification(beacons.get(0)
.getMinor()
+ ". Welcome to Retail Department");
}
break;
default:
break;
}
} catch (Exception e) {
// TODO: handle exception
}
}else{
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = 10;
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
// Utils.computeAccuracy(beacons.get(0))
}
}
}
}
}
});
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
// ---helper method to determine if the app is in
// the foreground---
public static boolean isAppInForeground(Context context) {
List<RunningTaskInfo> task = ((ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1);
if (task.isEmpty()) {
return false;
}
Log.e(TAG + "isAppInForeground-----",
""
+ task.get(0).topActivity.getPackageName()
.equalsIgnoreCase(context.getPackageName()));
return task.get(0).topActivity.getPackageName().equalsIgnoreCase(
context.getPackageName());
}
private void postNotification(String msg) {
if(!notifyMsg.equalsIgnoreCase(msg)){
notifyMsg = msg;
Intent notifyIntent = new Intent(BeaconMyService.this,
MainActivity.class);
notifyIntent.putExtra("content", msg);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivities(
BeaconMyService.this, 0, new Intent[] { notifyIntent },
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(
BeaconMyService.this).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Monitoring Region").setContentText(msg)
.setAutoCancel(true).setContentIntent(pendingIntent).build();
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_LIGHTS;
notificationManager.notify(NOTIFICATION_ID, notification);
}
}
}
Coming to Activity for updating status is this
package com.hcl.beacons_notification_ex;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
static TextView tv_items;
public static Handler messageHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_items = (TextView)findViewById(R.id.tv_items);
messageHandler = new MessageHandler();
}
public static class MessageHandler extends Handler {
#Override
public void handleMessage(Message message) {
int state = message.arg1;
switch (state) {
case 1:
tv_items.setText("Welcome to Media Lab");
break;
case 2:
tv_items.setText("Welcome to Gaming Zone");
break;
case 3:
tv_items.setText("Welcome to eLearing Education");
break;
case 4:
tv_items.setText("Welcome to Retail Department");
break;
default:
tv_items.setText("Going far to Range");
break;
}
}
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Intent i = new Intent(getApplicationContext(), BeaconMyService.class);
if(isMyServiceRunning(BeaconMyService.class)){
}else{
i.putExtra("MESSENGER", new Messenger(messageHandler));
startService(i);
// startService(i);
}
try {
if (getIntent().getExtras() != null) {
tv_items.setText(""
+ getIntent().getExtras().getString("content"));
}
} catch (Exception e) {
// TODO: handle exception
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
#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;
}
}
First of all you need estimote sdk
Then you can create a beaconDetection service something like this
public class BeaconMyService extends Service
{
private static final String TAG = "BeaconMyService";
private final Handler handler = new Handler();
private BeaconManager beaconManager;
private static final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("rid", null, null, null);
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
if (beaconManager.isBluetoothEnabled())
{
connectToService();
}
return Service.START_NOT_STICKY;
}
private void connectToService()
{
beaconManager.connect(new BeaconManager.ServiceReadyCallback()
{
#Override
public void onServiceReady()
{
try
{
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
}
catch (RemoteException e)
{
Log.e("Myservice", "Cannot start ranging, something terrible happened");
Log.e("", "Cannot start ranging", e);
}
}
});
}
#Override
public void onCreate()
{
super.onCreate();
beaconManager = new BeaconManager(this);
beaconManager.setRangingListener(new BeaconManager.RangingListener()
{
#Override
public void onBeaconsDiscovered(Region region, final List<Beacon> beacons)
{
// Note that beacons reported here are already sorted by
// estimated
// distance between device and beacon.
for (int index = 0; index < beacons.size(); index++)
{
Beacon beacon = beacons.get(index);
if (beacon != null)
{
Log.v("Beacon MacAddress", beacon.getMacAddress() + "");
if (!Constants.BEACONSDETECTEDLIST.containsKey(beacon.getMacAddress()))
{//Constants.BEACONSDETECTEDLIST is your list of beacon mac addresses
//public static HashMap<String, Long> BEACONSDETECTEDLIST = new HashMap<String, Long>();
//to check if beacon is detected for the first time
if (Constants.BEACON1.equalsIgnoreCase(beacon.getMacAddress()))
{//Constants.BEACON1 is mac address of beacon 1 assigned in constants
Constants.BEACONSDETECTEDLIST.put(beacon.getMacAddress(), System.currentTimeMillis());
handler.postDelayed(beacon1Detection, 2000);
}
else if (Constants.BEACON2.equalsIgnoreCase(beacon.getMacAddress()))
{
Constants.BEACONSDETECTEDLIST.put(beacon.getMacAddress(), System.currentTimeMillis());
handler.postDelayed(beacon2Detection, 2000);
}
}
else
{/*Do Nothing*/
}
}
}
}
});
}
private Runnable beacon1Detection = new Runnable()
{
public void run()
{
beacon1Info();
}
};
private Runnable beacon2Detection = new Runnable()
{
public void run()
{
beacon2Info();
}
};
private void beacon1Info()
{
Intent intent = new Intent(Constants.BEACON1BROADCAST_ACTION);
sendBroadcast(intent);
}//in Constants
//public static final String BEACON1BROADCAST_ACTION = "beacon1Action";
private void beacon2Info()
{
Intent intent = new Intent(Constants.BEACON2BROADCAST_ACTION);
sendBroadcast(intent);
}// in Constants
//public static final String BEACON2BROADCAST_ACTION = "beacon2Action";
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onDestroy()
{
handler.removeCallbacks(beacon1Detection);
handler.removeCallbacks(beacon2Detection);
super.onDestroy();
}
}
And then finally you need a BeaconBroadcastReceiver to receive the broadcasts in the service and open respective Activity
public class BeaconBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Constants.BEACON1BROADCAST_ACTION)) {
Intent intent2 = new Intent(context, Beacon1Layout.class);
context.startActivity(intent2);
} else if (intent.getAction().equals(Constants.BEACON2BROADCAST_ACTION)) {
Intent intent2 = new Intent(context, Beacon2Layout.class);
context.startActivity(intent2);
}
}
}
Hope this will help you, Good luck :)
I have the following Service that is meant to check a web API.
The Implementation is meant to retry the HTTP request 5 times before issuing a notification.
Anyway it seems that the service simply stops after the first attempt.
Please what is going on???
public class CreditcheckService extends IntentService {
public CreditcheckService() {
super("CreditcheckService");
}
#Override
protected void onHandleIntent(Intent intent) {
String phone = "";
phone = intent.getStringExtra("phone");
checkcreditonline(phone);
Log.e("inizio il service","inizio il service");
}
private void checkcreditonline(final String phone) {
final Handler h = new Handler();
final JsonHttpResponseHandler jsonHttpResponseHandler = new JsonHttpResponseHandler() {
private int counter = 0;
#Override
public void onSuccess(JSONObject arg0) {
int cazzo=0;
cazzo++;
try {
String status = arg0.getString("credit");
} catch (JSONException e) {
e.printStackTrace();
}
try {
String status = arg0.getString("error");
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
//IF FAILED SHOULD RETRY, BUT IT DOESN'T
if (counter < 5) {
//HERE THE SUCCESSIVE ATTEMPTS
h.postDelayed(new WebserviceRunnable(this, phone), 5000);
} else {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(CreditcheckService.this)
.setSmallIcon(R.drawable.icon)
.setContentTitle(getResources().getString(R.string.unable_to))
.setContentText(getResources().getString(R.string.please_connect));
mBuilder.setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), 0));
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(999, mBuilder.build());
}
counter++;
}
};
h.post(new WebserviceRunnable(jsonHttpResponseHandler, phone));
}
private class WebserviceRunnable implements Runnable {
private JsonHttpResponseHandler jsonHttpResponseHandler;
private String email;
public WebserviceRunnable(
JsonHttpResponseHandler jsonHttpResponseHandler, String aEmail) {
this.jsonHttpResponseHandler = jsonHttpResponseHandler;
this.email = aEmail;
}
public void run() {
try {
WebServiceApi.get(
"rest/credit/get/" + URLEncoder.encode(email, "utf-8"),
null, jsonHttpResponseHandler);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
onHandleIntent in IntentService is asynchronous.
When onHandleIntent exits, the Service is stopped.
So don't post a message to a Handler, instead do it directly in checkcreditonline().