I am developing an app which uses getRunningTasks() function to get the top activity name. But getRunningTasks() is deprecated in Android L. Is there any other way to get the top activity name (not package name) in Lollipop.
Class<?> currentClassName; // Declare Globally
Activity activity = (Activity) context;//casting context into activity
try
{
currentClassName = Class.forName(activity.getClass().getName()); //getting the current activity's class name from activity object
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
Please read SO Answer
I found a solution to get top activity name on Lollipop with the new Class UsageStatsManager added in Android L.
First you need the permission
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
And the user must enable this option.
Then use this method queryEvents()
There is a simple example.
while (true) {
final long INTERVAL = 1000;
final long end = System.currentTimeMillis();
final long begin = end - INTERVAL;
final UsageEvents usageEvents = manager.queryEvents(begin, end);
while (usageEvents.hasNextEvent()) {
UsageEvents.Event event = new UsageEvents.Event();
usageEvents.getNextEvent(event);
if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
Log.d("event", "timestamp : " + event.getTimeStamp());
Log.d("event", "package name : " + event.getPackageName());
Log.d("event", "class name : " + event.getClassName());
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
When an activity become to foreground, you can see its class name and package name in Logcat.
AccessibilityService can resolve this requirement, but the Accessibilityservice
api in android not stable, sometimes need checkbox off and on again, some code
<application>
<service
android:name=".service.DetectService"
android:exported="false"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/accessibility_service" />
</service>
<?xml version="1.0" encoding="UTF-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagReportViewIds"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"
android:notificationTimeout="100" />
import android.accessibilityservice.AccessibilityService;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
public class DetectService extends AccessibilityService {
#Override
protected void onServiceConnected() {
super.onServiceConnected();
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source == null) {
return;
}
Log.d("DetectService", "type: " + event.getEventType());
CharSequence packageName = source.getPackageName();
if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
return;
}
ComponentName componentName = new ComponentName(event.getPackageName().toString(), event.getClassName().toString());
try {
String activityName = getPackageManager().getActivityInfo(componentName, PackageManager.GET_META_DATA
| PackageManager.MATCH_ALL).toString();
activityName = activityName.substring(activityName.indexOf(" "), activityName.indexOf("}"));
Log.e("DetectService", packageName + ": " + activityName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
// sometime getActivityInfo will get NameNotFoundException,try use componentName
}
}
#Override
public void onInterrupt() {
Log.w("DetectService", "onInterrupt");
}
#Override
public boolean onUnbind(Intent intent) {
Log.w("DetectService", "onUnbind");
return super.onUnbind(intent);
}
}
Related
I create a app which uses accessibility. I passed intent for android accessibility settings but its not executed.
Here is code of android manifest.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.new_app">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<application
android:allowBackup="true"
android:label="#string/app_name"
android:icon="#mipmap/safety"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".Service_Running" />
<activity android:name=".MainActivity" />
<activity android:name=".injured_activity" />
<activity android:name=".splash_Activity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".Whatsapp_Accessibility"
android:label="Accessibility Service"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/whatsapp_service"/>
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
</service>
<service
android:name=".Background_Service"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
Here is code of accessiblity service xml file
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowContentChanged"
android:packageNames="com.whatsapp"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"/>
Here is the code of activity in which intent is passed
package com.example.new_app;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.app.ActivityManager;
import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import java.util.concurrent.TimeUnit;
public class splash_Activity extends AppCompatActivity {
SharedPreferences sharedPreferences;
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_);
sharedPreferences= getSharedPreferences("MySharedPreferences",MODE_PRIVATE);
String phone=sharedPreferences.getString("Phone_Number","");
String message=sharedPreferences.getString("Message","");
if (!isAccessibilitySettingsOn(getApplicationContext())) {
startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
}
if(phone!="" && message!="")
{
if(!isMyServiceRunning(Background_Service.class))
{
startForegroundService(new Intent(this,Background_Service.class));
}
Intent intent1=new Intent(this,Service_Running.class);
startActivity(intent1);
}
else
{
Intent intent1=new Intent(this,MainActivity.class);
startActivity(intent1);
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
private boolean isAccessibilitySettingsOn(Context mContext) {
int accessibilityEnabled = 0;
final String service = getPackageName() + "/" + Whatsapp_Accessibility.class.getCanonicalName();
try {
accessibilityEnabled = Settings.Secure.getInt(
mContext.getApplicationContext().getContentResolver(),
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
Log.v("this", "accessibilityEnabled = " + accessibilityEnabled);
} catch (Settings.SettingNotFoundException e) {
Log.e("this", "Error finding setting, default accessibility to not found: "
+ e.getMessage());
}
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
if (accessibilityEnabled == 1) {
Log.v("this", "***ACCESSIBILITY IS ENABLED*** -----------------");
String settingValue = Settings.Secure.getString(
mContext.getApplicationContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
mStringColonSplitter.setString(settingValue);
while (mStringColonSplitter.hasNext()) {
String accessibilityService = mStringColonSplitter.next();
Log.v("this", "-------------- > accessibilityService :: " + accessibilityService + " " + service);
if (accessibilityService.equalsIgnoreCase(service)) {
Log.v("this", "We've found the correct setting - accessibility is switched on!");
return true;
}
}
}
} else {
Log.v("this", "***ACCESSIBILITY IS DISABLED***");
}
return false;
}
}
Here is the code of Accessiblity Service
package com.example.new_app;
import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import java.util.List;
public class Whatsapp_Accessibility extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if(getRootInActiveWindow() == null){
return;
}
AccessibilityNodeInfoCompat rootNodeInfo = AccessibilityNodeInfoCompat.wrap(getRootInActiveWindow());
//get edit text if message from whats app
List<AccessibilityNodeInfoCompat> messageNodeList = rootNodeInfo.findAccessibilityNodeInfosByViewId("com.whatsapp:id/entry");
if(messageNodeList == null || messageNodeList.isEmpty())
return;
//checking if message field if filled with text and ending with our suffix
AccessibilityNodeInfoCompat messageField = messageNodeList.get(0);
if(messageField == null || messageField.getText().length() == 0 || !messageField.getText().toString().endsWith(" Send by Safety App"))
return;
// get whatsapp send message button node list
List<AccessibilityNodeInfoCompat> sendMessageNodeList = rootNodeInfo.findAccessibilityNodeInfosByViewId("com.whatsapp:id/send");
if(sendMessageNodeList == null || sendMessageNodeList.isEmpty())
return;
AccessibilityNodeInfoCompat sendMessage = sendMessageNodeList.get(0);
if(!sendMessage.isVisibleToUser())
return;
//fire send button
sendMessage.performAction(AccessibilityNodeInfo.ACTION_CLICK);
try{
Thread.sleep(2000);
performGlobalAction(GLOBAL_ACTION_BACK);
Thread.sleep(2000);
performGlobalAction(GLOBAL_ACTION_BACK);
}catch (InterruptedException ignored) {}
}
#Override
public void onInterrupt() {
}
}
I tested all this code on android 10
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 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);
}
}
}
I am trying to detect keyboard is active or not (Outside my application) using accessibility service. For that i tried to read the notifications "choose keyboard" (When multiple key board are enabled). Following code is used.
public class KeyboardWatcher extends AccessibilityService {
boolean isConnected = false;
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
final String packagename = String.valueOf(event.getPackageName());
Log.d("Package", packagename);
String msg = "";
List<CharSequence> s = event.getText();
if(s.iterator().hasNext())
{
msg += s.iterator().next().toString();
Log.d("MSG", msg);
}else{
Log.d("TYPE", event.getEventType()+"");
}
}else{
Log.d("EVENT TYPE__",event.getEventType()+"");
final String packagename = String.valueOf(event.getPackageName());
Log.d("PNE", packagename);
}
}
protected void onServiceConnected() {
if (isConnected) {
return;
}
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
setServiceInfo(info);
isConnected = true;
}
}
Now all notifications are logged by the application except "keyboard chooser" notification. How to read that notification, is that possible.
Thanks
package com.sat.app.notification;
import android.content.Context;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
public class NotificationService extends NotificationListenerService {
Context context;
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String title = sbn.getNotification().extras.getString("android.title");// It will be select keyboard
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Log.i("com.sat","Notification Removed");
}
}
IN Manifest : add
<service android:name="com.sat.app.notification.NotificationService"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
After installing application allow reading notification in settings.
Tested and working on Android 5.0
If I am correct there is no way to get that notification, the system itself detects all the available keyboards and displays them (if there is only one keyboard there will be no pop).
As far as I know there is no way to get that 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.