TileService not working, tile becomes unresponsive - android

I've made a tileService which triggers a foreground service when clicked. I have taken the battery optimisation permission from settings and set it on don't optimise. However after 3 days the tile becomes unresponsive.
public class QSIntentService
extends TileService {
String TAG = getClass().getSimpleName();
Context context;
boolean isTileActive;
#Override
public void onStartListening() {
super.onStartListening();
Log.e(TAG, "-----onStartListening Tile--");
if (isServiceRunning(getApplicationContext())) {
isTileActive = true;
updateTile();
} else {
isTileActive = false;
updateTile();
}
}
#Override
public void onClick() {
context = getApplicationContext();
Log.e(TAG, "-----onClick --- ");
Tile tile = getQsTile();
isTileActive = (tile.getState() == Tile.STATE_ACTIVE);
Intent serviceIntent = new Intent(context,
ForegroundService.class);
if (isServiceRunning(context)) {
isTileActive = false;
Utils.setBooleanFromPref(context,
context.getString(R.string.widgetStop), true);
if (ShareIBeaconInfo.INSTANCE.getForegroundService() != null) {
ForegroundService foregroundService =
ShareIBeaconInfo.INSTANCE.getForegroundService();
if (foregroundService.scanDevice != null) {
foregroundService.stopForegroundService();
}
}
context.stopService(serviceIntent);
} else {
isTileActive = true;
Utils.setBooleanFromPref(context,
context.getString(R.string.widgetStop), false);
Log.e(TAG, "service is not running");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent service = new Intent(context,
ForegroundService.class);
ContextCompat.startForegroundService(context, service);
} else {
Intent service = new Intent(context, ForegroundService.class);
context.startService(service);
}
}
updateTile();
}
private void updateTile() {
Tile tile = super.getQsTile();
int activeState = isTileActive ?
Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
tile.setState(activeState);
tile.updateTile();
}
private boolean isServiceRunning(Context context) {
try {
final ActivityManager manager;
manager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager
.getRunningServices(Integer.MAX_VALUE)) {
if ("com.foregroundscan.service.ForegroundService"
.equalsIgnoreCase(service.service.getClassName())) {
return true;
}
}
} catch (NullPointerException ex) {
} catch (Exception e) {
}
return false;
}
}
My test device is OnePlus 6T running over android 9. Also is there a way to push a dialogue if the tile is unresponsive? So that I can restart the service?
I received a log when I click on a tile when it is unresponsive
2-08 16:34:56.710 1831-2154/? E/MdmLogger: Cannot get tag from tileTag
: Tile.CustomTile

Related

Converting my Background Service to Android Oreo 8.0 Compatible

I have a service in my App which handles number of things. Sometimes when device is idle, the app crashes. And I know about the new Android 8.0 guidelines but I am not sure If I should convert my service to JobScheduler or take any other correct way. I can use some suggestions on which will be the best way to convert this service. Here is the code
HERE IS THE SERVICE :
public class ConnectionHolderService extends Service {
private static final String LOG_TAG = ConnectionHolderService.class.getSimpleName();
private SensorManager mSensorManager;
private static ConnectionHolderService instance = null;
public static ConnectionHolderService getInstanceIfRunningOrNull() {
return instance;
}
private class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
//some code
}
}
private Messenger mMessenger = new Messenger(new IncomingHandler());
public ConnectionHolderService() {
}
#Override
public void onCreate() {
super.onCreate();
instance = this;
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, Intent intent) {
//some code
}
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
private void startListeningForShake() {
mShakeEnabled = true;
startServiceToAvoidStoppingWhenNoClientBound(ACTION_STOP_SHAKE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
mSensorManager.registerListener(mSensorListener,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
}
}
private void startServiceToAvoidStoppingWhenNoClientBound(String action) {
registerReceiver(mReceiver, new IntentFilter(action));
startService(new Intent(this, ConnectionHolderService.class));
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
lock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ":Doze lock");
if (!lock.isHeld()) {
lock.acquire();
}
// When the Shake is active, we should not stop when UI unbinds from this service
startNotification();
}
private Notification getShakeServiceForegroundNotification() {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
if (mShakeEnabled) {
notificationBuilder.addAction(0, getString(R.string.shake_turn_off),
PendingIntent.getBroadcast(this,
REQ_CODE_STAY_ON,
new Intent(ACTION_STOP_SHAKE),
PendingIntent.FLAG_UPDATE_CURRENT));
}
if (mPollingEnabled) {
// notificationBuilder.addAction(0, getString(R.string.stop_smart_home_integration),
// PendingIntent.getBroadcast(this,
// REQ_CODE_STAY_ON,
// new Intent(ACTION_STOP_POLLING_SQS),
// PendingIntent.FLAG_UPDATE_CURRENT));
}
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
notificationBuilder
.setSmallIcon(R.drawable.logo)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setUsesChronometer(true)
.setContentIntent(PendingIntent.getActivity(this, REQ_CODE_STAY_ON, intent, PendingIntent.FLAG_UPDATE_CURRENT))
.setContentTitle(getString(R.string.title_notification_running_background))
.setContentText(getString(R.string.description_running_background));
return notificationBuilder.build();
}
private void stopIfNeeded() {
if (!mShakeEnabled && !mPollingEnabled) {
try {
unregisterReceiver(mReceiver);
} catch (Exception e) {
// It can be IllegalStateException
}
stopNotification();
stopSelf();
if (lock != null && lock.isHeld()) {
lock.release();
}
}
}
public void startNotification() {
if (SqsPollManager.sharedInstance().isConnectInBackground() && !MyApp.sharedInstance().isAppInForeground()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
startForeground(ID_SHAKE_SERVICE, getShakeServiceForegroundNotification());
}
}
}
public void stopNotification() {
mNotificationManager.cancel(ID_SHAKE_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
stopForeground(true);
}
}
#Override
public void onDestroy() {
super.onDestroy();
mReceiver = null;
Log.i(LOG_TAG, "onDestroy");
mMessenger = null;
mSensorListener = null;
instance = null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.i(LOG_TAG, "onTaskRemoved! Stopping ConnectionHolderService");
try {
unregisterReceiver(mReceiver);
} catch (Exception e) {
}
stopNotification();
stopSelf();
if (lock != null && lock.isHeld()) {
lock.release();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
stopForeground(true);
}
stopSelf();
}
}
HERE IS MY APP CLASS:
public class MyApp {
#Override
public void onCreate() {
super.onCreate();
sendMessageToConnectionHolderService("SomeMessage");
}
public void sendMessageToConnectionHolderService(final int what) {
bindService(new Intent(this, ConnectionHolderService.class), new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(LOG_TAG, "ConnectionHolderService connected!");
Messenger messenger = new Messenger(service);
Message msg = new Message();
msg.what = what;
try {
messenger.send(msg);
Log.i(LOG_TAG, "Message " + what + " has been sent to the service!");
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error sending message " + msg.what + " to ConnectionHolderService", e);
}
final ServiceConnection conn = this;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
unbindService(conn);
}
}, 1000);
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.i(LOG_TAG, "ConnectionHolderService disconnected!");
}
}, Context.BIND_AUTO_CREATE);
}
private Runnable mStartNotificationRunnable = new Runnable() {
#Override
public void run() {
if (SqsPollManager.sharedInstance().isPollingEnabled()
&& SqsPollManager.sharedInstance().isConnectInBackground()
&& !isAppInForeground()) {
if (null != ConnectionHolderService.getInstanceIfRunningOrNull()) {
ConnectionHolderService.getInstanceIfRunningOrNull().startNotification();
}
}
}
};
private Runnable mStopNotificationRunnable = new Runnable() {
#Override
public void run() {
if (null != ConnectionHolderService.getInstanceIfRunningOrNull()) {
ConnectionHolderService.getInstanceIfRunningOrNull().stopNotification();
}
}
};
}
AndroidManifest :
<service
android:name=".ConnectionHolderService"
android:enabled="true"
android:exported="false" />
You should consider using WorkManager. There are a lot of resources on how to use it, including samples, code-labs and blogs.
And if you are interested in JobScheduler in particular because of the Android 8.0 guidelines, I wrote a blog post that provides insights.

FirebaseMessagingService doesn't work correct

I have service implemented of FirebaseMessagingService. Today I noticed unusial behavior when phone blocked. I contunie to receive message and android show me via notification but code in onMessageReceived doesn't work.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
final Context context = this;
if(remoteMessage == null){
return;
}
if(remoteMessage.getNotification() != null){
try {
final Message msg = createMessage(remoteMessage.getNotification());
Handler handler= new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
if(!isAppIsInBackgrund(context)){
Intent intent = new Intent("APP_MESSAGE_BROADCAST");
intent.putExtra("SENDER", msg.getCorrespondent().getId().toString());
intent.putExtra("MESSAGE_ID", msg.getId());
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
else {
showNotification(msg.getCorrespondent().getName(), msg.getBody());
}
}
});
} catch (Exception e) {
showNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
}
}
}
// isAppIsInBackgrund - method where's i check openning app.
public boolean isAppIsInBackgrund(Context context){
boolean isInBackground = true;
ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH){
List<ActivityManager.RunningAppProcessInfo> runningProcesses = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo:runningProcesses){
if(processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
for (String activeProcess:processInfo.pkgList){
if(activeProcess.equals(context.getPackageName())){
isInBackground = false;
}
}
}
}
}
else {
List<ActivityManager.RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1);
ComponentName componentName = taskInfo.get(0).topActivity;
if(componentName.getPackageName().equals(context.getPackageName())){
isInBackground = false;
}
}
return isInBackground; }

On Android 5.0 lollipop maybe due to depricated getRunningTask() method

Application is working with in Kitkat version. After lollipop version application is not working properly. I am thinking problem with getRunningTasks() . Could you please give me guidance ,How to overcome this problem.
public class StartupServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Log.d("Detector", "Auto Start" + AppLockerPreference.getInstance(context).isAutoStart());
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
if (AppLockerPreference.getInstance(context).isAutoStart()){
if (AppLockerPreference.getInstance(context).isServiceEnabled()){
context.startService(new Intent(context, DetectorService.class));
}else{
AppLockerPreference.getInstance(context).saveServiceEnabled(false);
}
}
return;
}else if (AppLockerPreference.getInstance(context).isServiceEnabled()){
Toast.makeText(context, "App------>6", Toast.LENGTH_SHORT).show();
context.startService(new Intent(context, DetectorService.class));
}
}
}
DetectorService
public class DetectorService extends Service {
//public static final String ACTION_DETECTOR_SERVICE = "com.gueei.detector.service";
#Override
public IBinder onBind(Intent intent) {
return null;
}
private static final Class<?>[] mStartForegroundSignature = new Class[] {
int.class, Notification.class};
private static final Class<?>[] mStopForegroundSignature = new Class[] {
boolean.class};
private NotificationManager mNM;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];
/**
* This is a wrapper around the new startForeground method, using the older
* APIs if it is not available.
*/
void startForegroundCompat(int id, Notification notification) {
// If we have the new startForeground API, then use it.
if (mStartForeground != null) {
mStartForegroundArgs[0] = Integer.valueOf(id);
mStartForegroundArgs[1] = notification;
try {
mStartForeground.invoke(this, mStartForegroundArgs);
} catch (InvocationTargetException e) {
// Should not happen.
//debug: log.w("Detector", "Unable to invoke startForeground", e);
} catch (IllegalAccessException e) {
// Should not happen.
//debug: log.w("Detector", "Unable to invoke startForeground", e);
}
return;
}
// Fall back on the old API.
stopForeground(true);
mNM.notify(id, notification);
}
/**
* This is a wrapper around the new stopForeground method, using the older
* APIs if it is not available.
*/
void stopForegroundCompat(int id) {
// If we have the new stopForeground API, then use it.
if (mStopForeground != null) {
mStopForegroundArgs[0] = Boolean.TRUE;
try {
mStopForeground.invoke(this, mStopForegroundArgs);
} catch (InvocationTargetException e) {
// Should not happen.
//debug: log.w("Detector", "Unable to invoke stopForeground", e);
} catch (IllegalAccessException e) {
// Should not happen.
//debug: log.w("Detector", "Unable to invoke stopForeground", e);
}
return;
}
// Fall back on the old API. Note to cancel BEFORE changing the
// foreground state, since we could be killed at that point.
mNM.cancel(id);
stopForeground(false);
}
#Override
public void onCreate() {
//debug: log.i("Detector","Service.Oncreate");
initConstant();
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
try {
mStartForeground = getClass().getMethod("startForeground",
mStartForegroundSignature);
mStopForeground = getClass().getMethod("stopForeground",
mStopForegroundSignature);
} catch (NoSuchMethodException e) {
// Running on an older platform.
mStartForeground = mStopForeground = null;
}
}
#Override
public void onDestroy() {
//debug: log.i("Detector","Service.Ondestroy");
mThread.interrupt();
// Make sure our notification is gone.
stopForegroundCompat(R.string.service_running);
}
// This is the old onStart method that will be called on the pre-2.0
// platform. On 2.0 or later we override onStartCommand() so this
// method will not be called.
#Override
public void onStart(Intent intent, int startId) {
//debug: log.i("Detector","Service.Onstart");
handleCommand(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//debug: log.i("Detector","Service.OnStartCommand");
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return Service.START_STICKY;
}
private void handleCommand(Intent intent){
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.service_running);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.statusbar_icon, text,
System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, AppLockerActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, text,
text, contentIntent);
startForegroundCompat(R.string.service_running, notification);
startMonitorThread((ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE));
}
private void startMonitorThread(final ActivityManager am){
if (mThread!=null)
mThread.interrupt();
mThread = new MonitorlogThread(new ActivityStartingHandler(this));
mThread.start();
}
private static Thread mThread;
private static boolean constantInited = false;
private static Pattern ActivityNamePattern;
private static String logCatCommand;
private static String ClearlogCatCommand;
private void initConstant() {
//debug: log.i("Detector","Service.OninitConstant");
if (constantInited) return;
String pattern = getResources().getString(R.string.activity_name_pattern);
//debug: log.d("Detector", "pattern: " + pattern);
ActivityNamePattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
logCatCommand = getResources().getString(R.string.logcat_command);
ClearlogCatCommand = getResources().getString(R.string.logcat_clear_command);
}
MonitorlogThread
private class MonitorlogThread extends Thread{
ActivityStartingListener mListener;
public MonitorlogThread(ActivityStartingListener listener){
//debug: log.i("Detector","Monitor//debug: logThread");
mListener = listener;
}
BufferedReader br;
private Context context;
#Override
public void run() {
//debug: log.i("Detector","RUN!");
while(!this.isInterrupted() ){
try {
Thread.sleep(100);
////debug: log.i("Detector","try!");
//This is the code I use in my service to identify the current foreground application, its really easy:
ActivityManager am = (ActivityManager) getBaseContext().getSystemService(ACTIVITY_SERVICE);
// The first in the list of RunningTasks is always the foreground task.
//Toast.makeText(context, "App------>7", Toast.LENGTH_SHORT).show();
Log.d("Android", "App------>7----"+am);
//RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
Log.d("Android", "App------>8----"+foregroundTaskInfo);
//Toast.makeText(context, "App------>7"+foregroundTaskInfo, Toast.LENGTH_SHORT).show();
//Thats it, then you can easily access details of the foreground app/activity:
String foregroundTaskPackageName = foregroundTaskInfo.topActivity.getPackageName();
PackageManager pm = getBaseContext().getPackageManager();
PackageInfo foregroundAppPackageInfo = null;
String foregroundTaskAppName = null;
String foregroundTaskActivityName = foregroundTaskInfo.topActivity.getShortClassName().toString();
try {
foregroundAppPackageInfo = pm.getPackageInfo(foregroundTaskPackageName, 0);
foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo.loadLabel(pm).toString();
//debug: log.i("Detector",foregroundTaskAppName);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (mListener!=null){
//mListener.onActivityStarting(foregroundAppPackageInfo.packageName,foregroundTaskAppName);
mListener.onActivityStarting(foregroundAppPackageInfo.packageName,foregroundTaskActivityName);
}
} catch (InterruptedException e) {
// good practice
Thread.currentThread().interrupt();
return;
}
}
}
}
Use this code for above 5.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
UsageStatsManager usageStatsManager = (UsageStatsManager) ctx.getSystemService("usagestats");
long milliSecs = 60 * 1000;
Date date = new Date();
List<UsageStats> queryUsageStats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, date.getTime() - milliSecs, date.getTime());
if (queryUsageStats.size() > 0) {
Log.i(TAG, "UsageStats size: " + queryUsageStats.size());
}
long recentTime = 0;
String recentPkg = "";
for (int i = 0; i < queryUsageStats.size(); i++) {
UsageStats stats = queryUsageStats.get(i);
if (i == 0 && !getPackageName().equals(stats.getPackageName())) {
Log.i(TAG, "PackageName: " + stats.getPackageName() + " " + stats.getLastTimeStamp());
}
if (stats.getLastTimeStamp() > recentTime) {
String recentTime = stats.getLastTimeStamp();
String recentPkg = stats.getPackageName();
}
};
} catch (Exception e) {
e.printStackTrace();
}
}
Can you try this.
ActivityManager am = (ActivityManager) getBaseContext().getSystemService(ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
ActivityManager.RunningAppProcessInfo runningAppProcessInfo = (ActivityManager.RunningAppProcessInfo) am.getRunningAppProcesses();
String foregroundTaskPackageName = runningAppProcessInfo.pkgList.getClass().getPackage().getName();
PackageManager pm = getBaseContext().getPackageManager();
PackageInfo foregroundAppPackageInfo = null;
String foregroundTaskAppName = null;
String foregroundTaskActivityName = runningAppProcessInfo.pkgList.getClass().getName();
try {
foregroundAppPackageInfo = pm.getPackageInfo(foregroundTaskPackageName, 0);
foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo.loadLabel(pm).toString();
//debug: log.i("Detector",foregroundTaskAppName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
} else {
ActivityManager.RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo.topActivity.getPackageName();
PackageManager pm = getBaseContext().getPackageManager();
PackageInfo foregroundAppPackageInfo = null;
String foregroundTaskAppName = null;
String foregroundTaskActivityName = foregroundTaskInfo.topActivity.getShortClassName().toString();
try {
foregroundAppPackageInfo = pm.getPackageInfo(foregroundTaskPackageName, 0);
foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo.loadLabel(pm).toString();
//debug: log.i("Detector",foregroundTaskAppName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
Use RunningAppProcessInfo instead of getRunningTasks for SDK versions greater than KitKat.
ActivityManager am = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
...
} else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
...
}

Activity Recognition Api wrongly detecting inVehicle

Sometimes when a user is sitting, or the phone is still on a table. the if statement which checks if inVehicle & 100% is triggered and the service in my app is started. I cannot figure out why ?
Activity Recognition in MainActivity
public String getDetectedActivity(int detectedActivityType) {
Resources resources = this.getResources();
switch (detectedActivityType) {
case DetectedActivity.IN_VEHICLE:
return resources.getString(R.string.in_vehicle);
case DetectedActivity.ON_BICYCLE:
return resources.getString(R.string.on_bicycle);
case DetectedActivity.ON_FOOT:
return resources.getString(R.string.on_foot);
case DetectedActivity.RUNNING:
return resources.getString(R.string.running);
case DetectedActivity.WALKING:
return resources.getString(R.string.walking);
case DetectedActivity.STILL:
return resources.getString(R.string.still);
case DetectedActivity.TILTING:
return resources.getString(R.string.tilting);
case DetectedActivity.UNKNOWN:
return resources.getString(R.string.unknown);
default:
return resources.getString(R.string.unidentifiable_activity, detectedActivityType);
}
}
public void requestActivityUpdates() {
if (!mGoogleApiClient.isConnected()) {
Toast.makeText(this, "GoogleApiClient not yet connected", Toast.LENGTH_SHORT).show();
} else {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("acr", true);
editor.commit();
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, 100, getActivityDetectionPendingIntent()).setResultCallback(this);
}
}
public void removeActivityUpdates() {
ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(mGoogleApiClient, getActivityDetectionPendingIntent()).setResultCallback(this);
}
private PendingIntent getActivityDetectionPendingIntent() {
Intent intent = new Intent(this, ActivitiesIntentService.class);
return PendingIntent.getService(this, 20, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public void onResult(Status status) {
if (status.isSuccess()) {
Log.e(TAG, "Successfully added activity detection.");
} else {
Log.e(TAG, "Error: " + status.getStatusMessage());
}
}
public class ActivityDetectionBroadcastReceiver extends BroadcastReceiver {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onReceive(Context context, Intent intent) {
ArrayList<DetectedActivity> detectedActivities = intent.getParcelableArrayListExtra(Constants.STRING_EXTRA);
String activityString = "";
for (DetectedActivity activity : detectedActivities) {
activityString += "Activity: " + getDetectedActivity(activity.getType()) + ", Confidence: " + activity.getConfidence() + "%\n";
}
//mDetectedActivityTextView.setText(activityString);
//Toast.makeText(context, activityString, Toast.LENGTH_LONG).show();
Log.d(TAG2, activityString);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
detectEnabled = preferences.getBoolean("mode", false);
buttonToggleDetect.setBackground(ui.uiToggle(getApplicationContext(), detectEnabled));
}
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected");
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed. Error: " + connectionResult.getErrorCode());
}
Intent Service
public class ActivitiesIntentService extends IntentService {
// TODO REMOVE EXPORTED & ENABLED IN MANIFEST RELATED TO THIS CLASS
private static final String TAG = "ActivitiesIntentService";
public ActivitiesIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
boolean serviceState;
int inVehicle = 0;
int onFoot = 2;
int walking = 7;
int running = 8;
int tilting = 5;
int still = 3;
Intent serviceIntent = new Intent(this, CallDetectService.class); //creating a new intent to be sent to CallDetectService class
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
Intent i = new Intent(Constants.STRING_ACTION);
ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();
// Log each activity.
Log.i(TAG, "activities detected");
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
serviceState = preferences.getBoolean("mode", false);
for (DetectedActivity da : detectedActivities) {
// // TODO: 16/07/16 local invehicle int precentage, if int is <50 return
// todo set up for logs from past day to be sent by user
if (da.getType() == inVehicle && da.getConfidence() >= 100 ) {
if (!serviceState) {
/*
ComponentName service = new ComponentName(getApplicationContext(), CallDetectService.class);
PackageManager pm = getApplicationContext().getPackageManager();
pm.setComponentEnabledSetting(service,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
*/
Log.d("Service", "service enabled by acr");
startService(serviceIntent);
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.music_marimba_chord);
mp.start();
//TODO ADD MP.FINISH HERE
}
}
//else if (da.getType() == still && da.getConfidence() >= 25)
else if (da.getType() == onFoot && da.getConfidence() >= 25
|| da.getType() == walking && da.getConfidence() >= 25
|| da.getType() == running && da.getConfidence() >= 25
|| da.getType() == still && da.getConfidence() == 100)
{
// stop detect service
if (serviceState) {
stopService(serviceIntent);
/*ComponentName service = new ComponentName(getApplicationContext(), CallDetectService.class);
PackageManager pm = getApplicationContext().getPackageManager();
pm.setComponentEnabledSetting(service,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
*/
Log.d("Service", "service disabled by acr");
}
}
}
i.putExtra(Constants.STRING_EXTRA, detectedActivities);
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
}
}
Am I missing something? I really cant figure it out.
I tried putting in a component enabled/disabled setting in the intent service which is commented. when I had that in the code, the service did not start when the user was not inVehicle but when turn on and off when they actually where.
Any Help would be greatly appreciated.

how to set different ids for different estimote beacons?

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 :)

Categories

Resources