I am basically working with Android Application , i have requirement to restrict to open others apps while my app is running, Means My app is running it will put some locks on other application while i am accessing the others app, Kind of Application Lock. I am trying but could not find good solution. If any buddy have some idea or link or sample code please share to me.
Basically you want Kiosk Mode .
Try this:
Home button press:
<category android:name="android.intent.category.HOME" /> //add in manifest
What id does: whenever you press the home button, all the applications installed in your phone which have category.HOME category in intent-filter in their AndroidManifest.xml will be listed .
then handle Long press Home Button:
#Override
protected void onPause() {
super.onPause();
ActivityManager activityManager = (ActivityManager) getApplicationContext()
.getSystemService(Context.ACTIVITY_SERVICE);
activityManager.moveTaskToFront(getTaskId(), 0);
}
for this add this line in manifest :
<uses-permission android:name="android.permission.REORDER_TASKS" />
3.handle BackButton :
#Override
public void onBackPressed() {
// Stop user to exit
// super.onBackPressed();
}
You can also try this for Kiosk Mode:
Read this document
import android.app.ActivityManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.provider.SyncStateContract;
import android.util.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
public class HeartBeat extends Service {
private static final String TAG = HeartBeat.class.getSimpleName();
public Timer TIMER;
// private static Set<AccessGranted> mAccessGrantedList = new HashSet<AccessGranted>();
private Set<String> mLockedApps = new HashSet<String>();
private long lastModified = 0;
private BroadcastReceiver mScreenStateReceiver;
// private BroadcastReceiver mAccessGrantedReceiver;
private File mLockedAppsFile;
ArrayList<String> packagezList;
SharedPreferences sharedPrefs;
Map<String, ?> allEntries;
SharedPreferences sharedPrefsapp;
String prefix;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startService(new Intent(this, HeartBeat.class));
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
if (TIMER == null) {
TIMER = new Timer(true);
TIMER.scheduleAtFixedRate(new LockAppsTimerTask(), 1000, 250);
mScreenStateReceiver = new BroadcastReceiver() {
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = false;
}
if (screenOff) {
//Log.i(TAG, "Cancel Timer");
TIMER.cancel();
} else {
// Log.i(TAG, "Restart Timer");
TIMER = new Timer(true);
TIMER.scheduleAtFixedRate(new LockAppsTimerTask(), 1000, 250);
}
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenStateReceiver, filter);
}
// this.stopSelf();
//startforeground goes here
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
startService(new Intent(this, HeartBeat.class));
}
private class LockAppsTimerTask extends TimerTask {
#Override
public void run() {
sharedPrefs = getApplicationContext().getSharedPreferences(getApplicationContext().getPackageName(), Context.MODE_PRIVATE);
sharedPrefsapp = getApplicationContext().getSharedPreferences("appdb", Context.MODE_PRIVATE);
allEntries= null;
allEntries = sharedPrefsapp.getAll();
Set keySet = allEntries.keySet();
Iterator<String> keySetIter = keySet .iterator();
while (keySetIter.hasNext()) {
String keyEntry= keySetIter.next();
Log.e("Shared Vaues",keyEntry);
}
//prefix = "m";
packagezList= null;
packagezList = new ArrayList<String>();
for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
packagezList.add(entry.getKey());
Log.e("right key: ", entry.getKey().toString() + "right value: " + entry.getValue().toString());
}
/* for (Map.Entry<String, ?> entry : allEntries.entrySet())
{
//Check if the package name starts with the prefix.
if (entry.getKey().startsWith(prefix)) {
//Add JUST the package name (trim off the prefix).
packagezList.add(entry.getKey().substring(prefix.length()));
packagezList.add(entry.getKey());
}
}*/
for(Object object: packagezList){
Log.e("YO!", (String) object);
}
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
try {
//List<RecentTaskInfo> recentTasks = activityManager.getRecentTasks(1, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> RunningTask = mActivityManager
.getRunningTasks(1);
ActivityManager.RunningTaskInfo ar = RunningTask.get(0);
String activityOnTop = ar.topActivity.getPackageName();
Log.e("activity on Top", "" + activityOnTop);
Log.e(" My package name", "" + getApplicationContext().getPackageName());
//for (Object data : newArrayList) {
for(Object object: packagezList){
// Provide the packagename(s) of apps here, you want to show password activity
if (!activityOnTop.contains(getApplicationContext().getPackageName()))
// if(!activityOnTop.contains(getApplicationContext().getPackageName()))
{ // you have to make this check even better
Intent i = new Intent(getApplicationContext(), LockScreenActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
i.putExtra( "", "");
startActivity(i);
}
}
} catch (Exception e) {
Log.e("Foreground App", e.getMessage(), e);
}
}
}
Related
-I am developing an application that records user location in a .csv file and uploads them to firebase storage and I've written a service to accomplish this. The service needs to run indefinitely until the user stops it (by unchecking a switch from the activity that launched the service). The service runs in foreground and after running for 15-20 minutes, the phone manager app gives "resource intensive app found" notification and kills the service. onDestroy() never gets called!. I return START_STICKY which is supposed to recreate the service and call onStartCommand() again but the service never gets created again!
I've seen some people write workarounds for this problem but they target specific android versions. My app targets android Pie and I haven't seen any "generic" solution to this problem yet. All solutions are either device/brand specific or API level specific. For now I'm testing the app on Huawei Y7 prime 2018 (Android O) and on my device, i got around this by manually disallowing the phone manager app to manage my application, this way the service does run indefinitely until the user kills it from the app. The nature of the application is such that i need minimum user engagement and i don't expect the users to go through the hassle of manually disabling my app from battery optimizer/phone manager app. My LocationService.java class is attached, if somebody could please provide either a better implementation of this service or some generic method to keep it alive, that'd be great. Even some hack to make sure that onDestroy() gets called before the system kills the application would work!
package com.example.bumps;
import android.Manifest;
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.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class LocationService extends Service implements LocationListener {
private static final String CHANNEL_ID = "LocationServiceChannel";
private static final int ONGOING_NOTIFICATION_ID = 1;
public static final String PREFS_TAG = "PendingUploadPrefs";
private LocationManager locationManager;
DecimalFormat numberFormat = new DecimalFormat("#.000");
DecimalFormat coordinatesFormat = new DecimalFormat("#.00000");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
SimpleDateFormat sdfForDir = new SimpleDateFormat("dd-MM-yyyy_hh:mm:ss");
File locationDirectory;
String currentDataDirectory;
FirebaseStorage filesStorage;
String userUUID;
List<ResumeFileUpload> pendingFileUploads;
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor sharedPrefEditor;
private SOTWFormatter sotwFormatter;
#Override
public void onCreate() {
super.onCreate();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
filesStorage = FirebaseStorage.getInstance();
pendingFileUploads = new ArrayList<>();
sharedPreferences = this.getSharedPreferences(PREFS_TAG, Context.MODE_PRIVATE);
sharedPrefEditor = sharedPreferences.edit();
sotwFormatter = new SOTWFormatter(this);
String timeStamp = sdfForDir.format(new Date());
currentDataDirectory = "RBD_" + timeStamp;
locationDirectory = new File(getExternalFilesDir(null), currentDataDirectory);
if (!locationDirectory.exists())
locationDirectory.mkdir();
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//userUUID = intent.getStringExtra("userUUID");
userUUID = sharedPreferences.getString("userUUID", "UNKNOWN");
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 0, this);
}
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
createNotificationChannel();
Notification notification =
new Notification.Builder(this, CHANNEL_ID)
.setContentTitle(getText(R.string.notification_title))
.setContentText(getText(R.string.notification_message))
.setSmallIcon(R.drawable.bump)
.setContentIntent(pendingIntent)
.setTicker(getText(R.string.ticker_text))
.build();
startForeground(ONGOING_NOTIFICATION_ID, notification);
return START_STICKY;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Location Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
try {
manager.createNotificationChannel(serviceChannel);
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
locationManager.removeUpdates(this);
}
File newFileLoc = writeLocationDataToFile(locationStringBuilder);
pendingFileUploads.add(new ResumeFileUpload(currentDataDirectory,
newFileLoc.getPath()));
uploadToStorage(newFileLoc);
/*if there are no pending files from some previous session, just save the ones
* that just got created*/
if (getPendingFileUploads() == null){
setList("PendingUploads", pendingFileUploads);
}else{
/*if there are pending uploads from some previous session, fetch them,
* update the list of pending uploads with and save for later upload*/
List<ResumeFileUpload> pUploads = getPendingFileUploads();
for (ResumeFileUpload resumeFileUpload: pendingFileUploads){
pUploads.add(resumeFileUpload);
}
setList("PendingUploads", pUploads);
}
}
private List<ResumeFileUpload> getPendingFileUploads(){
List<ResumeFileUpload> pendingUploads = null;
String serializedObject = sharedPreferences.getString("PendingUploads", null);
if (serializedObject != null){
Gson gson = new Gson();
Type type = new TypeToken<List<ResumeFileUpload>>(){}.getType();
pendingUploads = gson.fromJson(serializedObject, type);
}
return pendingUploads;
}
private boolean deleteFile(File file){
try {
Uri uri = Uri.fromFile(file);
File fdelete = new File(uri.getPath());
if (fdelete.exists()) {
if (fdelete.delete()) {
System.out.println("file Deleted :" + uri.getPath());
return true;
} else {
System.out.println("file not Deleted :" + uri.getPath());
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private File writeLocationDataToFile(StringBuilder data) {
String fileName = "Location.csv";
String colNamesLoc = "Timestamp,Latitude,Longitude,Accuracy,DirectionOfMotion,Speed\n";
File newFile = new File(locationDirectory, fileName);
try {
FileWriter fileWriter = new FileWriter(newFile);
fileWriter.append(colNamesLoc);
fileWriter.append(data.toString());
fileWriter.flush();
fileWriter.close();
Toast.makeText(this, "Saved To " + getExternalFilesDir(null)
+ "/" + fileName, Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
return newFile;
}
private void uploadToStorage(final File newFile){
Uri uri = Uri.fromFile(new File(newFile.getPath()));
StorageReference storageReference = filesStorage.getReference()
.child(userUUID + "/" + currentDataDirectory + "/" +
uri.getLastPathSegment());
UploadTask uploadTask = storageReference.putFile(uri);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast.makeText(LocationService.this,
newFile.getName() + " Upload Failed!", Toast.LENGTH_SHORT).show();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
deleteFile(newFile);
Toast.makeText(LocationService.this,
newFile.getName() + " Upload Successful!", Toast.LENGTH_SHORT).show();
}
});
}
/*Location Listener*/
#Override
public void onLocationChanged(Location location) {
if (location != null) {
String lat = coordinatesFormat.format(location.getLatitude());
String lng = coordinatesFormat.format(location.getLongitude());
String bearing = "0.0";
if (location.getBearing() != 0.0)
bearing = String.valueOf(sotwFormatter.format(location.getBearing()));
int speed = (int) location.getSpeed();
String currentSpeed = String.valueOf(speed * 3.6f) + " KM/h";
String accuracy = "0.0";
if (location.getAccuracy() != 0.0)
accuracy = coordinatesFormat.format(location.getAccuracy());
String timeStamp = simpleDateFormat.format(new Date());
String locationData = timeStamp + ", " + lat +
", " + lng + ", " + accuracy + ", " + bearing + ", "
+ currentSpeed;
locationStringBuilder.append(locationData);
locationStringBuilder.append("\n");
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
/*SharedPreferences code*/
public <T> void setList(String key, List<T> list) {
Gson gson = new Gson();
String json = gson.toJson(list);
set(key, json);
}
public void set(String key, String value) {
sharedPrefEditor.putString(key, value);
sharedPrefEditor.commit();
}
}
I'm building an Android Wear service which runs in the background and logs device data every three minutes. For this logging, I am using a Handler, which records the values and then has an interval of three minutes. This will be used to monitor user behaviour for one month, and as such it should not randomly stop.
I have also used android.intent.action.BOOT_COMPLETED in my manifest and this successfully runs the application whenever the watch is booted.
My issue is that the service can run correctly for 12 hours...and then just suddenly stop. The amount of time appears to be non-deterministic, as sometimes it will stop after 40 minutes. I suspect it's being killed by Android, but in this case I would like it to restart. I have included return START_STICKY in my service and this should minimise the chance of it being killed.
In some solutions, I have seen onDestroy() overridden and a refresh broadcast being sent to the service. While this appears to work, the onDestroy() function is being called every time the Handler completes one piece of work. This leads to the service restarting every three minutes, rather than when the application is actually killed by Android.
I have also looked at the intent actions to see whether my service could be called at regular intervals. However, aside from android.intent.action.BOOT_COMPLETED, all the useful ones cannot be registered in the Manifest file. Since the service will not be running, registerReceiver() would serve little purpose.
Does anybody know of a technique to either a) guarantee a service will not be killed by Android; or b) guarantee that a service will always be restarted after it has been killed. Any help would be greatly appreciated, as I've even started considering writing a Cron job on the device and setting it to execute my app every three minutes! I've also looked at the AlarmManager class, but I fear it is as likely to be killed if running for long periods.
Please find my code below: (AndroidManifest.xml)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.study">
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.DeviceDefault">
<receiver android:name="com.example.study.MyServiceManager" android:enabled="true">
<intent-filter>
<action android:name="com.example.study.RestartAction" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name="com.example.study.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="com.example.study.RecordService"
android:exported="false" />
</application>
</manifest>
RecordService.java
package com.example.study;
import android.Manifest;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import com.google.android.gms.location.LocationServices;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.text.TextUtils;
import com.google.android.gms.location.*;
import com.google.android.gms.tasks.OnSuccessListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class RecordService extends IntentService {
private static Context context;
private final static int INTERVAL = 1000 * 5; // 1 minutes
Handler handler = new Handler();
Location myLocation;
private FusedLocationProviderClient mFusedLocationClient;
SensorManager sensorManager;
SensorManager gyroSensorManager;
SensorManager compassSensorManager;
SensorEventListener sensorEventListener;
float[] accValues;
float[] gyroValues;
float[] compassValues;
Runnable handlerTask = new Runnable() {
#Override
public void run() {
try {
recordData();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.postDelayed(handlerTask, INTERVAL);
}
};
public RecordService() {
super("RecordService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
handlerTask.run();
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
public void recordData() throws ExecutionException, InterruptedException {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.getAppContext());
boolean fineLocationGranted = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
boolean coarseLocationGranted = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
boolean isLocationEnabled = isLocationEnabled(this);
if(fineLocationGranted && coarseLocationGranted && isLocationEnabled) {
long startTime = System.currentTimeMillis();
long timeWaiting = 0L;
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(MainActivity.getActivity(), new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
myLocation = location;
} else {
System.out.print("");
}
}
});
do {
timeWaiting = System.currentTimeMillis() - startTime;
} while (myLocation == null && timeWaiting < 200);
}
List<PackageInfo> packages = getPackageManager().getInstalledPackages(PackageManager.GET_PERMISSIONS);
KeyguardManager kg = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
boolean isLocked = kg.isDeviceSecure();
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
gyroSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
compassSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if(sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
accValues = sensorEvent.values;
} else if(sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE){
gyroValues = sensorEvent.values;
} else if(sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
compassValues = sensorEvent.values;
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {}
};
try {
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
gyroSensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL);
compassSensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
} catch(SecurityException e) {
e.printStackTrace();
}
long startTime2 = System.currentTimeMillis();
long timeWaiting2 = 0L;
do {
timeWaiting2 = System.currentTimeMillis() - startTime2;
} while((accValues == null || gyroValues == null || compassValues == null) && timeWaiting2 < 200);
StringBuilder builder = new StringBuilder();
builder.append("G" + (isLocationEnabled ? 1 : 0));
builder.append(" L" + (isLocked ? 1 : 0));
if(accValues != null && gyroValues != null && compassValues != null) {
builder.append(" ACX" + accValues[0]);
builder.append(" ACY" + accValues[1]);
builder.append(" ACZ" + accValues[2]);
builder.append(" GYX" + gyroValues[0]);
builder.append(" GYY" + gyroValues[1]);
builder.append(" GYZ" + gyroValues[2]);
builder.append(" CMX" + gyroValues[0]);
builder.append(" CMY" + gyroValues[1]);
builder.append(" CMZ" + gyroValues[2]);
}
if(myLocation != null) {
builder.append(" LT" + myLocation.getLatitude());
builder.append(" LN" + myLocation.getLongitude());
}
builder.append("\n");
for(PackageInfo info: packages) {
int lastDot = info.packageName.lastIndexOf('.');
builder.append(info.packageName + "\n");
if(info.requestedPermissions != null) {
for (String rqprm : info.requestedPermissions) {
int dot = rqprm.lastIndexOf('.');
builder.append(rqprm.substring(dot != -1 ? dot + 1 : 0) + " ");
}
builder.append("\n");
for (int permflag : info.requestedPermissionsFlags) {
builder.append("" + permflag + " ");
}
builder.append("\n");
}
}
SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd--HH-mm-ss");
String currentDateString = sdf.format(new Date());
File log = new File("/sdcard/Recordings/" + currentDateString);
try {
if (!log.exists()) {
log.createNewFile();
}
BufferedWriter writer = new BufferedWriter(new FileWriter(log, true));
writer.append(builder.toString());
writer.newLine();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean isLocationEnabled(Context context) {
int locationMode = 0;
String locationProviders;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
try {
locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
return false;
}
return locationMode != Settings.Secure.LOCATION_MODE_OFF;
} else {
locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return !TextUtils.isEmpty(locationProviders);
}
}
MainActivity.java
package com.example.study;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView mTextView;
private static Context context;
private static MainActivity activity;
Intent serviceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.context = getApplicationContext();
activity = this;
serviceIntent = new Intent(this, RecordService.class);
startForegroundService(serviceIntent)
startService(serviceIntent);
}
public static Context getAppContext() {
return MainActivity.context;
}
public static MainActivity getActivity() {
return activity;
}
}
MyServiceManager.java
package com.example.study;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
public class MyServiceManager extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
}
i'm making a service
which works perfactly well so far,
but everytime the phone restarts, the service is lost,
how do i make the service restart every time the phone shuts off, and turns back on again , (if it was running out of battery, or if user has done a restart)
is there a simple way of making it ?
this is my service >
package com.greenroad.candidate.mywallpaperchanger;
import android.app.Service;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by pitsponet on 31/08/2015.
*/
public class myService extends Service {
int oneSecond = 1000;
int oneMinute = oneSecond*60;
int oneHour = oneMinute*60;
int pictureNumberToChoos = 0;
boolean isTimerRunning = false;
int timerDeley = oneHour;
private Timer timer;
private TimerTask timerTask = new TimerTask() {
#Override
public void run() {
//this timer will run again in 10 seconds
Log.d("MyLog", "timer entered ");
//shows a toast saying timer has entered
Handler mainHandler = new Handler(getApplicationContext().getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "timer listener Entered", Toast.LENGTH_LONG).show();
}
});
//takes picture modifier and updates it to +1 then stores it at var > pictureModifireInt
// Access the default SharedPreferences
SharedPreferences pref = getApplicationContext().getSharedPreferences("myGlobalPrefTable", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
//open a boolean to tell if the service is activated for the first time it will say false
Integer pictureModifireInt = pref.getInt("pictureModifire", 0);
pictureModifireInt++;
/////holds a list with all the images
int displayPicture = R.drawable.captain;
ArrayList<Integer> pictureNames = new ArrayList<>();
pictureNames.add(R.drawable.captain);
pictureNames.add(R.drawable.flash);
pictureNames.add(R.drawable.superman);
pictureNames.add(R.drawable.thor);
pictureNames.add(R.drawable.wonder);
pictureNames.add(R.drawable.a);
pictureNames.add(R.drawable.b);
pictureNames.add(R.drawable.c);
pictureNames.add(R.drawable.d);
pictureNames.add(R.drawable.e);
pictureNames.add(R.drawable.f);
pictureNames.add(R.drawable.g);
pictureNames.add(R.drawable.h);
pictureNames.add(R.drawable.i);
pictureNames.add(R.drawable.j);
pictureNames.add(R.drawable.k);
pictureNames.add(R.drawable.l);
pictureNames.add(R.drawable.m);
pictureNames.add(R.drawable.n);
pictureNames.add(R.drawable.o);
//logs the stored prefrence and select the correct image at place > picture modifire
Log.d("myLog", "storedPreference: " + pictureModifireInt);
displayPicture = pictureNames.get(pictureModifireInt-1);
if(pictureModifireInt > 19){
// Edit the saved preferences
Log.d("myLog", "putting in pictureModifire : : " + 0);
editor.putInt("pictureModifire", 0); // getting String
editor.commit();
} else {
Log.d("myLog", "putting in pictureModifire : : " + pictureModifireInt);
editor.putInt("pictureModifire", pictureModifireInt); // getting String
editor.commit();
}
///////////////////////////start of wallpaper implemintation
WindowManager wm= (WindowManager) getSystemService(MainActivity.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Bitmap bmap2 = BitmapFactory.decodeResource(getResources(), displayPicture);
Bitmap bitmap = Bitmap.createScaledBitmap(bmap2, width, height, true);
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
try {
wallpaperManager.setBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
//////////////////////////end of wallpaper implementation
mainHandler = new Handler(getApplicationContext().getMainLooper());
final Integer finalPictureModifireInt = pictureModifireInt-1;
mainHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "wallpaper changed to : "+ finalPictureModifireInt+" and started a new timer", Toast.LENGTH_LONG).show();
}
});
}
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getApplicationContext(), "a new service created",
Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyLog", "a new service started");
final Handler mainHandler = new Handler(getApplicationContext().getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "serviceStarterd", Toast.LENGTH_LONG).show();
// Access the default SharedPreferences
SharedPreferences pref = getApplicationContext().getSharedPreferences("myGlobalPrefTable", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
//open a boolean to tell if the service is activated for the first time it will say false
boolean serviceStateOn = pref.getBoolean("isServiceActivated", false);
if(serviceStateOn == false){
// Edit the saved preferences
Toast.makeText(getApplicationContext(), "a New Timer Started with Delay: "+timerDeley, Toast.LENGTH_LONG).show();
editor.putBoolean("isServiceActivated", true); // getting String
editor.commit();
timer = new Timer();
timer.scheduleAtFixedRate(timerTask, timerDeley, timerDeley);
} else {
Log.d ("myLog", "Service is on so do nothing");
}
}
});
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getApplicationContext(), "service stoped",
Toast.LENGTH_LONG).show();
}
}
and this is my Manifest >
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.greenroad.candidate.mywallpaperchanger" >
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
<application
android:allowBackup="true"
android:icon="#mipmap/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=".myService"
android:exported="false"
/>
</application>
</manifest>
THANKX EVERYONE IN ADVANCe ! "_
i wouldn't know how to live without this site lol..
You need to make a receiver which will listen to intent.Boot complete.
And then in on receive(), you can start your service.
You need to add Receiver Class.
Add below permission in AndroidManifest.xml file.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Add below statements in Application Tag in AndroidManifest.xml
<receiver android:name=".YourBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter></receiver>
YourBroadcastReceiver.java
package com.test;
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, MyService.class);
context.startService(startServiceIntent);
}
}
So i'm using asmack library to listen for incoming xmpp packets. I've got the service implemented. It's started, bound, a method is run and then it's unbound. The service creates a PacketListener to get incoming messages, and displays a notification when a new message comes in. This all works while the app is the active activity, but doesn't work when it's fully closed (swiped away in the window list) and it's just the service running, the PacketListener doesn't fire. It fires as soon as the app is reopened though, firing off all notifications. I'm looking to get those notifications fired as they come in, instead of the service being suspended, if you will. The code for the service is here:
package com.jayseeofficial.xmpp.service;
import java.io.File;
import java.util.ArrayList;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import android.widget.Toast;
import com.jayseeofficial.xmpp.MainActivity;
import com.jayseeofficial.xmpp.Program;
import com.jayseeofficial.xmpp.R;
import com.jayseeofficial.xmpp.objects.Contact;
import com.jayseeofficial.xmpp.preferences.Preferences;
public class XMPPService extends Service {
private Connection conn = null;
private boolean loggedIn = false;
private final XMPPBinder binder = new XMPPBinder();
private Handler handler;
#Override
public IBinder onBind(Intent arg0) {
handler = new Handler(getMainLooper());
return binder;
}
public class XMPPBinder extends Binder {
public XMPPService getService() {
return XMPPService.this;
}
}
public void logIn() {
new LogInTask().execute();
}
public boolean isLoggedIn() {
return loggedIn;
}
private ConnectionConfiguration getConnectionConfiguration() {
ConnectionConfiguration config = new ConnectionConfiguration(
Preferences.Account.getServer(), Preferences.Account.getServerPort());
config.setSASLAuthenticationEnabled(true);
config.setCompressionEnabled(true);
config.setSecurityMode(SecurityMode.enabled);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
config.setTruststoreType("AndroidCAStore");
config.setKeystoreType("AndroidCAStore");
config.setTruststorePassword(null);
config.setTruststorePath(null);
} else {
config.setTruststoreType("BKS");
String path = System.getProperty("javax.net.ssl.trustStore");
if (path == null) {
path = System.getProperty("java.home") + File.separator + "etc" + File.separator
+ "security" + File.separator + "cacerts.bks";
}
config.setTruststorePath(path);
}
return config;
}
private void showNotification() {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setContentTitle("XMPP+").setContentText("running")
.setSmallIcon(R.drawable.speech_bubble);
Intent i = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(i);
// Assign the intent
mBuilder.setContentIntent(stackBuilder.getPendingIntent(9127,
PendingIntent.FLAG_UPDATE_CURRENT));
NotificationManager mgr = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification n = mBuilder.build();
n.flags |= Notification.FLAG_ONGOING_EVENT;
mgr.notify(1,n);
}
private void hideNotification() {
// TODO Implement hideNotification in XMPPService
}
private class LogInTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
showNotification();
// Set up and log in
conn = new XMPPConnection(getConnectionConfiguration());
conn.connect();
conn.login(Preferences.Account.getUsername(), Preferences.Account.getPassword());
// Set up to receive messages
PacketFilter filter = new PacketTypeFilter(Message.class);
conn.addPacketListener(new XMPPMessagePacketListener(), filter);
conn.sendPacket(new Presence(Type.available));
final ArrayList<Contact> allContacts = new ArrayList<Contact>();
// Populate contact list
for (RosterEntry re : conn.getRoster().getEntries()) {
Log.d("Roster entry: ", re.getUser() + ": " + re.getName());
Contact c = new Contact();
if (re.getName() == null) {
c.setName(re.getUser());
} else {
c.setName(re.getName());
}
c.setAddress(re.getUser());
allContacts.add(c);
}
handler.post(new Runnable() {
#Override
public void run() {
Program.contacts.addAll(allContacts);
}
});
loggedIn = true;
} catch (XMPPException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void ignored) {
if (loggedIn) {
Toast.makeText(XMPPService.this, "Logged in successfully", Toast.LENGTH_LONG)
.show();
} else {
Toast.makeText(XMPPService.this, "Failed to log in", Toast.LENGTH_LONG).show();
}
}
}
private class XMPPMessagePacketListener implements PacketListener {
#Override
public void processPacket(Packet packet) {
Message m = (Message) packet;
if (m.getBody() != null) {
com.jayseeofficial.xmpp.objects.Message message = new com.jayseeofficial.xmpp.objects.Message();
message.setRecipient(Preferences.Account.getUsername() + "#"
+ Preferences.Account.getServer());
String fullSender = m.getFrom();
String address = fullSender.substring(0, fullSender.indexOf('/'));
message.setSender(address);
message.setContents(m.getBody());
Program.showMessageNotification(message, 9127);
}
}
}
}
and the code for the starting/binding the service is here:
public static void init() {
if (!initialized) {
// Call other portions of init code first
SmackAndroid.init(context);
Preferences.init();
// Set up our variables
contacts = GlazedLists.threadSafeList(new BasicEventList<Contact>());
// Start up the xmpp connection
Intent ixmpp = new Intent(context, XMPPService.class);
context.startService(ixmpp);
context.bindService(ixmpp, xmppConnection, Context.BIND_AUTO_CREATE);
initialized = true;
}
}
So as I said, i want to receive notifications from the service running in the background when the foreground activity is closed. Is there any way of doing this? Maybe have it in it's own process? Something else?
EDIT: the ongoing notification sticks around and works when clicked, in case you're wondering
use startforeground method
http://developer.android.com/reference/android/app/Service.html#startForeground%28int,%20android.app.Notification%29
in onCreate of service
public void onCreate() {
startForeground (int id, Notification notification)
}
I am trying to implement NotificationListnerService which is added in android 4.3 but I am not able to get the notification details.
My code are as below
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.drawable.ic_launcher);
mBuilder.setContentTitle("notification test");
mBuilder.setContentText("Notification text");
mBuilder.setAutoCancel(true);
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(1, mBuilder.build());
}
#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;
}
}
public class NotificationListenerTesting extends NotificationListenerService{
public static String TAG = "NotificationListenerTesting";
//private StatusBarNotification[] mStatusBarNotification;
#Override
public void onCreate(){
super.onCreate();
Log.d(TAG, "Inside on create");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
TAG = "onNotificationPosted";
Log.d(TAG, "id = " + sbn.getId() + "Package Name" + sbn.getPackageName() +
"Post time = " + sbn.getPostTime() + "Tag = " + sbn.getTag());
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
TAG = "onNotificationRemoved";
Log.d(TAG, "id = " + sbn.getId() + "Package Name" + sbn.getPackageName() +
"Post time = " + sbn.getPostTime() + "Tag = " + sbn.getTag());
}
}
Android manifest file is
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.notificationtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.notificationtest.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.example.notificationtest.ResultActivity"></activity>
<service android:name="com.example.notificationtest.NotificationListenerTesting"
android:label="notification"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService"/>
</intent-filter>
</service>
</application>
</manifest>
but after notification click or on notification post NotificationListenerService is not getting called , Whats wrong in this or did I miss somthing ? How to implement it ?
You need to grant access to your app to read notifications:
"Settings > Security > Notification access" and check your app.
Inside the NotificationListenerService you need a looper to communicate with GUI thread so you can create a broadcast to handle the GUI interaction.
Hope this example will help you.
At least one problem with your code is that your implementation of onBind()
There is no necessity to override this method. But if you must, then at least return the IBinder returned by the superclass.
#Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
It might be a bit late. But a few months ago I also struggled with making NotificationListenerService work.
Since then I`ve learned how to implement it and felt like building a implementation tutorial to help others who went through the same as me
If anyone is interested, check the project here:
https://github.com/Chagall/notification-listener-service-example
Hope it helps someone who is struggling with it.
I know its too late to answer the question , but as I was not able to find Settings > Sound and notifications -> Notification access, so I directly allow access of notifications to my app by firing this intent:
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
I ran into the same problem and have found some clues for that.
NotificationListenerService may not be running unless you call bindService() to start it.
Sometimes it started automatically when you enabled "Notification access" and sometimes it's not.
I am doing the same thing as in GitHub, but still I am not going into the notification class.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
/**
* #author dinesh
*
*/
public class UserNotificationService extends NotificationListenerService {
private String TAG = "UserNotificationService";
UserNotificationServiceReceiver notfRcvr;
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Log.i(TAG,"********** onNotificationRemoved");
Log.i(TAG,"ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText +"\t" + sbn.getPackageName());
Intent i = new Intent("de.tu.darmstadt.moodsense.services.Notification");
i.putExtra("notification event", "On notification removed");
sendBroadcast(i);
}
#Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
Log.i(TAG,"********** onNotificationPosted");
Log.i(TAG,"ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText + "\t" + sbn.getPackageName());
Intent i = new Intent("de.tu.darmstadt.moodsense.services.Notification");
i.putExtra("notification event", "On notification posted");
sendBroadcast(i);
}
#Override
public void onCreate() {
super.onCreate();
notfRcvr = new UserNotificationServiceReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("de.tu.darmstadt.moodsense.services.Notification");
registerReceiver(notfRcvr, filter);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(notfRcvr);
}
class UserNotificationServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if(intent.getStringExtra("command").equals("clearall")) {
UserNotificationService.this.cancelAllNotifications();
}
}
}
}
import java.lang.Thread.State;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import twitter4j.Status;
import twitter4j.TwitterException;
import de.tu.darmstadt.moodsense.R;
import de.tu.darmstadt.moodsense.app.UserMood;
import de.tu.darmstadt.moodsense.constants.Constants;
import de.tu.darmstadt.moodsense.util.MqttMoodClient;
import de.tu.darmstadt.moodsense.util.TwitterMoodUtils;
import de.tu.darmstadt.moodsense.util.TwitterUtils;
import android.app.AlarmManager;
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.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.IBinder;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
/**
* #author dinesh
* Added for V1.1
* Code style based on : https://newcircle.com/s/post/1049/
* tutorial_services_part_1_android_bootcamp_series_2012
*
*/
public class UserMoodService extends Service{
static final String TAG = "UserMoodService";
public static boolean userMoodSet = false;
//declarations for twitter
private SharedPreferences prefs;
SharedPreferences userPref;
String userTwitterMood = "";
String worldTwitterMood = "";
String screenName, userName;
int m_counter;
long shortMinutes;
boolean m_enterMood;
int m_myMood;
int m_moodIntensity;
MqttMoodClient mqc;
TwitterMoodUtils tmu;
Calendar cal = Calendar.getInstance();
private static final int MY_NOTIFICATION_ID=1;
NotificationManager notificationManager;
Notification myNotification;
UserMoodNotificationReceiver usrMoodNotfnnRcvr;
public UserMoodService() {
// TODO Auto-generated constructor stub
mqc = new MqttMoodClient();
tmu = new TwitterMoodUtils();
}
public void reset() {
m_myMood = Constants.NUM_MOOD_TYPES;
m_moodIntensity = Constants.MILD;
m_enterMood = false;
m_counter = 0;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
// TODO Auto-generated method stub
Intent restartService = new Intent(getApplicationContext(),this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartServicePI = PendingIntent.getService(getApplicationContext(),
1, restartService, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() +100, restartServicePI);
}
/** (non-Javadoc)
* #see android.app.Service#onCreate()
*/
#Override
public void onCreate() {
Log.d(TAG, "OnCreation");
//super.onCreate();
usrMoodNotfnnRcvr = new UserMoodNotificationReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("Notofication Obj");
registerReceiver(usrMoodNotfnnRcvr, filter);
}
/** (non-Javadoc)
* #see android.app.Service#onStartCommand(android.content.Intent, int, int)
*/
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "OnStartCommand");
try {
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
Log.d(TAG,"Twitter loop enter");
//Check the user's mood on twitter
computeMoodOnTwitter();
if(userMoodSet) {
Log.d(TAG, "user's twitter mood" + userTwitterMood);
} /*else {
Log.d(TAG, "user mood not set, world mood computation started");
//If user's mood is not set then check for world's mood
}*/
}
} catch(Exception e) {
e.printStackTrace();
}
return START_STICKY;
}
private void computeMoodOnTwitter() {
// TODO Auto-generated method stub
reset();
this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
Thread twitterThread;
twitterThread = new Thread() {
public void run() {
//userMoodSet = false;
Log.d(TAG, "User mood is :: "+ userMoodSet);
/*try {
String usrNme = TwitterUtils.getUserName(prefs).toString();
List<Status> statuses = TwitterUtils.getHomeTimeline(prefs);
for(int i=0; i < Constants.NUM_MOOD_TYPES; i++) {
for (int j =0 ; j < Constants.NUM_MOOD_TYPES; j++)
{
for (twitter4j.Status status : statuses) {
//Check if the status is from the user and it matches our mood strings
if(status.getText().contains(Constants.searchStrings[i][j])
&& (status.getUser().getScreenName().equals(usrNme))) {
Date date = status.getCreatedAt();
long Minutes = tmu.getMinuteDifference(cal.getTime(), date);
if((Constants.sdf.format(date).equals(Constants.sdf.format(cal.getTime())))) {
//Increment counter for each tweet
Log.d(TAG, "User has a status");
userMoodSet = true;
m_counter++;
//track time for the first tweet
if(m_counter == 1) {
shortMinutes = Minutes;
m_moodIntensity = computeMoodIntensity(i,j);
m_myMood = i;
Log.d(TAG, "intensity + mood" + m_moodIntensity +","+ m_myMood);
Log.d(TAG,"SocialMood:: mymood- " + Constants.moodIntensityNames[m_moodIntensity]+
" "+ Constants.moodNames[m_myMood]);
Log.d(TAG, "SocialMood:: status-"+status.getText());
} else //counter more than 1 //track time for the later tweets
{ //take latest tweet only if logged minutes is shorter than earlier minutes
if(Minutes < shortMinutes) {
shortMinutes = Minutes;
Log.d(TAG, "Called compute mood_intensity :: "+ m_counter);
m_moodIntensity = computeMoodIntensity(i,j);
m_myMood = i;
}
}
}
}
}
}
}
} catch(TwitterException te) {
userMoodSet = false;
Log.d(TAG, "Unable to process twitter get requests "+te.getErrorCode()+ " "+ te.getErrorMessage());
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d(TAG,"Error msg");
e.printStackTrace();
}*/
try {
stopThread(this);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
twitterThread.start();
}
public int computeMoodIntensity(int m_detect, int m_type) {
// TODO Auto-generated method stub
for(int j=0; j < Constants.m_extreme.length; j++) {
if(m_type == Constants.m_extreme[m_detect][j])
return Constants.EXTREME;
}
for(int j=0; j < Constants.m_considerable.length; j++) {
if(m_type == Constants.m_considerable[m_detect][j])
return Constants.CONSIDERABLE;
}
return Constants.MILD;
}
private String userStatusToMood(int myMood) {
// TODO Auto-generated method stub
String userMood = Constants.userNoTwitter;
if(m_myMood >= Constants.NUM_MOOD_TYPES) {
m_enterMood = true;
Log.d(TAG, userMood);
//Unreachable code - maybe we need to delete this ?? QNS
/*Intent i = new Intent(UserMoodService.this,UserMood.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);*/
}
else {
userMood = "User mood is "+ Constants.moodNames[m_myMood];
userTwitterMood = Constants.moodIntensityNames[m_moodIntensity]
+" "+Constants.moodNames[m_myMood];
Log.d(TAG, "Updated user mood is "+userTwitterMood);
//call MQTT
MqttMoodClient mqc = new MqttMoodClient();
mqc.setupMqttClient();
mqc.sendMessage(userTwitterMood);
}
return userMood;
}
private void stopThread(Thread theThread) throws Exception {
// method to stop the worker thread once the process needed to do has been completed
Log.d(TAG,"userMoodSet :: "+ userMoodSet);
if (theThread != null)
{
theThread = null;
Log.d(TAG, "Execution complete inside stop thread");
if(userMoodSet)
userStatusToMood(m_myMood);
}
if(!userMoodSet) {
Log.d(TAG, "In world thread");
//Call world Service
//WorldMoodService worldService = new WorldMoodService();
//worldService.computeWorldMood(this);
//show notification!!
/**
* V1.1
* #author dinesh
* Code adapted from : http://android-er.blogspot.de/2013/06/
* start-activity-once-notification-clicked.html
*/
Intent myIntent = new Intent(UserMoodService.this, UserMood.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
UserMoodService.this,
0,
myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);
myNotification = new NotificationCompat.Builder(UserMoodService.this)
.setContentTitle("MoodSense notification")
.setContentText("Please enter mood to play music as per your mood")
.setTicker("Please enter mood to play music as per your mood")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.app_icon)
.build();
notificationManager =
(NotificationManager)UserMoodService.this.
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
} else if (userMoodSet) {
Intent i = new Intent("de.tu.darmstadt.moodsense.services.Notification");
i.putExtra("command", "clear all");
sendBroadcast(i);
}
}
public class UserMoodNotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String temp = intent.getStringExtra("notification event");
}
}
/** (non-Javadoc)
* #see android.app.Service#onDestroy()
*/
#Override
public void onDestroy() {
Log.d(TAG, "OnDeletion");
super.onDestroy();
}
}
Update 2020 Kotlin And AndroidX
package com.hiteshsahu.notificationlistener.notification
import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager
class CustomNotificationListenerService : NotificationListenerService() {
private var commandFromUIReceiver: CommandFromUIReceiver? = null
override fun onCreate() {
super.onCreate()
// Register broadcast from UI
commandFromUIReceiver = CommandFromUIReceiver()
val filter = IntentFilter()
filter.addAction(READ_COMMAND_ACTION)
registerReceiver(commandFromUIReceiver, filter)
}
/**
* New Notn Added Callback
*/
override fun onNotificationPosted(newNotification: StatusBarNotification) {
Log.i(
TAG,
"-------- onNotificationPosted(): " + "ID :" + newNotification.id + "\t" + newNotification.notification.tickerText + "\t" + newNotification.packageName
)
sendResultOnUI("onNotificationPosted :" + newNotification.packageName + "\n")
}
/**
* Notn Removed callback
*/
override fun onNotificationRemoved(removedNotification: StatusBarNotification) {
Log.i(
TAG,
"-------- onNotificationRemoved() :" + "ID :" + removedNotification.id + "\t" + removedNotification.notification.tickerText + "\t" + removedNotification.packageName
)
sendResultOnUI("onNotificationRemoved: " + removedNotification.packageName + "\n")
}
internal inner class CommandFromUIReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.getStringExtra(COMMAND_KEY) == CLEAR_NOTIFICATIONS)
// remove Notns
cancelAllNotifications()
else if (intent.getStringExtra(COMMAND_KEY) == GET_ACTIVE_NOTIFICATIONS)
// Read Notns
fetchCurrentNotifications()
}
}
/**
* Fetch list of Active Notns
*/
private fun fetchCurrentNotifications() {
sendResultOnUI("===== Notification List START ====")
val activeNotnCount = this#CustomNotificationListenerService.activeNotifications.size
if (activeNotnCount > 0) {
for (count in 0..activeNotnCount) {
val sbn = this#CustomNotificationListenerService.activeNotifications[count]
sendResultOnUI("#" + count.toString() + " Package: " + sbn.packageName + "\n")
}
} else {
sendResultOnUI("No active Notn found")
}
sendResultOnUI("===== Notification List END====")
}
// sendMessage success result on UI
private fun sendResultOnUI(result: String?) {
val resultIntent = Intent(UPDATE_UI_ACTION)
resultIntent.putExtra(RESULT_KEY, Activity.RESULT_OK)
resultIntent.putExtra(RESULT_VALUE, result)
LocalBroadcastManager.getInstance(this).sendBroadcast(resultIntent)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(commandFromUIReceiver)
}
companion object {
const val TAG = "NotificationListener"
//Update UI action
const val UPDATE_UI_ACTION = "ACTION_UPDATE_UI"
const val READ_COMMAND_ACTION = "ACTION_READ_COMMAND"
// Bundle Key Value Pair
const val RESULT_KEY = "readResultKey"
const val RESULT_VALUE = "readResultValue"
//Actions sent from UI
const val COMMAND_KEY = "READ_COMMAND"
const val CLEAR_NOTIFICATIONS = "clearall"
const val GET_ACTIVE_NOTIFICATIONS = "list"
}
}
Complete Project
https://github.com/hiteshsahu/Android-Notification-Demo
The notification that you build does not have "tickerText." I have found that if the notification does not have tickerText, onNotificationPosted does not get called.
In your code add mBuilder.setTicker( "your text here" ).
onNotificationPosted should now be called assuming that the rest of the NotificationListenerService set up is copacetic.