hi I am using phonegap local notification plugin in my android project.
notification are working great.
i can delete a notification with ID
but in my app i have to delete all notification option, for which this plugin gives a method to cancelAll notification.
which is:-
plugins.localNotification.cancelAll();
but this is not working.
i am using this plugin from here
https://github.com/phonegap/phonegap-plugins/tree/master/Android/LocalNotification
any help will be appreciated.
I think this might be the answer to this one. As it says in the description of the cancelAllNotifications() method (LocalNotification.java line 124):
Android can only unregister a specific alarm. There is no such thing as cancelAll. Therefore we rely on the Shared Preferences which holds all our alarms to loop through these alarms and unregister them one by one.
However, take a look at the code where the cancelAllNotifications() method is called (line 59):
} else if (action.equalsIgnoreCase("cancelall")) {
unpersistAlarmAll();
return this.cancelAllNotifications();
}
Here's what unpersistAlarmAll() looks like (line 181):
private boolean unpersistAlarmAll() {
final Editor alarmSettingsEditor = this.cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE).edit();
alarmSettingsEditor.clear();
return alarmSettingsEditor.commit();
}
What's happening is that the alarmIds are being cleared from sharedPreferences before cancelAllNotifications() is called, effectively leaving no alarms to be canceled.
I'm not sure where the best place to move the call to unpersistAlarmAll() is, and I'd be happy to get some suggestions. In the meantime I have moved it to within cancelAllNotifications(), after the result returned from alarm.cancelAll(alarmSettings) is tested (line 133), like so:
if (result) {
unpersistAlarmAll();
return new PluginResult(PluginResult.Status.OK);
So far this seems to be working fine. Perhaps another way to do this would be to scrap the whole unpersistAlarmAll() method and instead call unpersistAlarm(String alarmId) (line 168) after each individual alarm is successfully canceled.
Depending on what you are trying to do, you could use the "Statusbar notificaiton". This plugin will enable you to put message on the android status bar.
https://github.com/phonegap/phonegap-plugins/tree/master/Android/StatusBarNotification
Related
I don't know this is an issue or bug. So I'm writing it. I wrote an alarm manager function to execute certain tasks periodically. it's firing periodically. But the problem is I can't use certain plugins inside that. I used the shared preference plugin to take some data from locally. But the alarm manager function returns null on that. I don't know why. It only happens inside that Alarm manager static function. I just used another plugin Get storage to do a similar thing again. But the result was similar.
In my case, I am just trying to build a wallpaper App. I just wanna change the wallpaper periodically. There are numerous categories like nature, bike, car, etc. for selection. If the user selects one category. Then I just fired an alarm manager and should have to do automatically change wallpaper according to the category. Due to the static function of the alarm manager, for knowing selected categories I just wrote those to the locals. So for grabbing it in the alarm manager static function, I'm used shared preference and Get storage plugins. But both of them can't work as expected in the alarm manager. I don't know why. Is this a bug or is this due to the static function of the alarm manager?
Is there any solution or is there any idea to overcome it?
my code when user taps on a button to set wallpaper for certain category:
onPressed: () async {
print("::::::::::::");
await AndroidAlarmManager.initialize();
var yes = await AndroidAlarmManager.cancel(id);
await AndroidAlarmManager.cancel(id);
categoryScheduled = searchController.text.toString();
print(yes);
final box = GetStorage();
var data = {
"category": categoryScheduled ,
};
await box.write("bg_image", data);
final prefs = await SharedPreferences.getInstance();
prefs.setString('counter', categoryScheduled);
await AndroidAlarmManager.periodic(
timeInterval,
20,
term,
);
},
Here suppose a user selects a category like "nature" for auto-change the wallpaper under the nature category. we just initialize the alarm manager. and also we cancel if a certain alarm is executing. After I'm trying to store that selected category locally using the Get storage plugin and after I tried with shared preference too. But I cant grab that in the alarm manager static function.
my alarm manager static function is given below:
static term() async {
int pageNumber = 0;
final prefs = await SharedPreferences.getInstance();
//here we tries to grab the locally stored keyword using shared preferbnce but it return null.but its fine workin in another function.
final counter = prefs.getString('counter') ?? 0;
//next tried to grab it using another plugin to get storage. its also return null.
final box = GetStorage();
var readData = await box.read("bg_image");
print(readData);
print("this is category");
var query = readData["category"];
var results;
//tries to calling API with selected category. but category returning null.
final response = await http.get(Uri.parse(
"https://api.unsplash.com/search/photos/?client_id=7674db521921f5e47a89c6a432205d49db929dadaae45356226372c756e&page=$pageNumber&query=$query"));
// if (response.statusCode == 200) {
// itemCount++;
// Scaffold.of(context).hideCurrentSnackBar();
// If the call to the server was successful, parse the JSON
var jsonData = json.decode(response.body);
print(jsonData.length);
results = jsonData["results"];
print(results.length);
print(results[0]["urls"]["full"]);
var url = results[0]["urls"]["full"];
var progressString = Wallpaper.ImageDownloadProgress(url);
progressString.listen((data) {}, onDone: () async {
//setting walllpaper
await Wallpaper.homeScreen();
// scaffoldKey.currentState.showSnackBar(snackBar);
}, onError: (error) {
print("Some Error");
});
}
Use Flutter Local Notifications package.
I have also faced the same issue with the package Work_manager where I used to access other Plugins. I solved it by creating an Isolate on Periodic task. And I was able to access the Plugin even when application was killed.
And However i faced issues when i used in-build flutter Isolate then I switched to this package and everything works fine now.
First of all thanks for the answers given by the guys.Those were very helpfull for me and got some new knowledge.As per the first answer we have to use flutter isolate.but it will not work when the app got killed. same stuffs happens in flutter local notifications plugin .To do this kind of work we can use two plugins (i got only two plugins,may there will be more)
1.Flutter Alaram manager plus
2.workmanager
I had some issues with Alaram manager as described above.Anyway i found some solution for it .Current scenario was lack of plugin support ( both in alaram manager plugin and work manager plugin) in the callback function.As per some docs in the workmanager ,it says we have to register those plugins to do some stuffs in callback function.But there is no idea how to do same stuffs inside Alaram manager's callback function.So work manager may more preferable for this kind of scenario.But there was some problem(i dont know its may be bug) between currebt version(2.2.3) of flutter and workmanager plugin.so i just downgradedflutter version 2.0.3 and its workin fine for me.it will support shared preference plugin and wallpaper manager plugin inside that callback function .hence its gonna be ease for me to do that task.But still some of the plugin will not support in that callback function.For that we have to register those plugin to do that( you can search how to register a plugin in workmanager).Else you should have to use method channel to do this kind of work.Any way,in my case i just wanted those two plugins for my tasks,by god's grace its workin fine in callback function and its workin fine for me.
I'm trying to add a BackdoorMethod to a Xamarin.Forms application to bypass the login (IDP - opened in chrome browser) step. I have the feeling that the method is not getting triggered, but not sure, and I don't know how could I make sure about it.
I've read the documentation here: https://learn.microsoft.com/en-us/appcenter/test-cloud/uitest/working-with-backdoors
Check this thread: https://forums.xamarin.com/discussion/85821/xamarin-uitest-backdoor-on-droid-with-splash-screen-how-do-i-access-my-mainactivity
Checked this example: https://github.com/brminnick/UITestSampleApp/tree/master/Src
In the MainActivity.cs file I've defined the BackdoorMethod:
[Preserve, Export(nameof(BypassLoginScreen))]
public string BypassLoginScreen()
{
// some additional code here. the code is working, when I called it
// directly from OnCreate it was executed without any error
return "called";
}
From the test case i'm trying to invoke it like:
public constructorMethod(Platform platform)
{
this.platform = platform;
app = AppInitializer.StartApp(platform);
var result = app.Invoke("BypassLoginScreen"); // result == "<VOID>"
}
I'm not getting any error message, the method simply not called, or not returns anything. (or i don't know what's happening there with it, because breakpoint also not working as the app started from the device)
This should be already working. I have similar code and it works for me.
you can add inside your function
Android.Util.Log.WriteLine(Android.Util.LogPriority.Info, "BypassLoginScreen", $"Some text as info");
And observe the result in Device Logs, Filter by BypassLoginScreen to see if there is any log created with the tag BypassLoginScreen
On our application there's a service that is normally started during Application.OnCreate (directly calling context.startService) and also later on via AlarmManager (refactor is in progress to migrate some of its work to JobScheduler).
Our application also have a BroadcastReceiver that gets launched with its direct intent.
Given the new limitations in Android Oreo (https://developer.android.com/about/versions/oreo/android-8.0-changes.html) we're having an issue as follows:
app/process is in background/dead
BroadcastReceiver gets fired by the OS
Application.onCreate() executes before the BroadcastReceiver
Application.onCreate() code tries to run the Service
this leads to crash with "IllegalStateException: Not allowed to start service Intent".
I'm aware of the new recommended ways of launching a Service as answered by CommonsWare here https://stackoverflow.com/a/44505719/906362, but for this specific case, I simply want to have if(process in foreground) { startService }. I'm currently using the following method and it seems to work:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean isProcessInForeground_V21(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.AppTask> tasks = am.getAppTasks();
return tasks.size() > 0;
}
But I can't find the exact checks Android Oreo is doing (I got as far as here https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ContextImpl.java on the startServiceCommon method, but from there requireForeground flag seems to go to some native implementation)
So my question:
For the specific purpose of Android Oreo new limitations, how to check if my process is foreground before calling startService?
To continue your investigation: (TL;DR: see between horizontal lines at the bottom)
Disclaimer, I don't know too much about Android, I just like digging in the source code.
Note: you can also navigate the code in Android Studio if you jump to file instead of class:
or searching for text in Project and Libraries.
IActivityManager is defined by AIDL, that's why there are no sources for it:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/app/IActivityManager.aidl#145
Based on how AIDL needs to be implemented I found that ActivityManagerService extends IActivityManager.Stub (God bless Google indexing).
Note I also found this, which might be an interesting read if you're really interested how things work internally.
https://programmer.group/android-9.0-source-app-startup-process.html
ActivityManagerService sources reveal that in Oreo startService is forwarded to ActiveServices which is located in the same package.
Assuming we're looking for an exception like this:
java.lang.IllegalStateException: Not allowed to start service Intent {...}: app is in background uid UidRecord{af72e61 u0a229 CAC bg:+3m52s273ms idle procs:1 seq(0,0,0)}
we have to continue down the rabbit hole: requireForeground gets assigned to fgRequired parameter and the message is here. The condition to allow this depends on the start mode returned by ActivityManagerService.getAppStartModeLocked(packageTargetSdk = 26 or greater, disabledOnly = false, forcedStandby = false).
There are 4 start modes:
APP_START_MODE_NORMAL (needs to be different than this, i.e. !=)
APP_START_MODE_DELAYED (this is ok, i.e. return null)
APP_START_MODE_DELAYED_RIGID
APP_START_MODE_DISABLED
Ephemeral apps will immediately return APP_START_MODE_DISABLED, but assuming this is a normal app, we end up in appServicesRestrictedInBackgroundLocked.
Note: this is where some of the whitelist mentioned in https://stackoverflow.com/a/46445436/253468 is decided.
Since all branches but last return APP_START_MODE_NORMAL, this redirects to appRestrictedInBackgroundLocked where we find our most likely suspect:
int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
// Apps that target O+ are always subject to background check
if (packageTargetSdk >= Build.VERSION_CODES.O) {
return ActivityManager.APP_START_MODE_DELAYED_RIGID;
}
So the reason for denial is simply targeting O. I think the final answer to your question of how the OS decides if your app is foreground or background is this condition in getAppStartModeLocked
UidRecord uidRec = mActiveUids.get(uid);
if (uidRec == null || alwaysRestrict || uidRec.idle) {
My guess is that a missing record means it's not running (but then how is it starting a service?!), and idle means it's backgrounded. Notice that in my exception message the UidRecord is saying that it's idle and has been backgrounded for 3m52s.
I peeked into your getAppTasks and it's based on TaskRecord.effectiveUid, so I'm guessing that's quite close to listing UidRecords for your app.
Not sure if this helps, but I'll post it anyway, so if anyone wants to investigate more, they have more info.
whenever we get a call, we do see missed call notification. Is there a way to remove the missed call notification in android programatically?
We see missed calls numbers & its count. Can we remove them via code?
The only "legal" but extremely ugly and usually useless way to achieve what you want is to show Call Log to user. And I mean literally show (becomes visual, gets focus). In case you want to do this, here's how:
public static boolean showCallLog(Context context)
{
try
{
Intent showCallLog = new Intent();
showCallLog.setAction(Intent.ACTION_VIEW);
showCallLog.setType(android.provider.CallLog.Calls.CONTENT_TYPE);
context.startActivity(showCallLog);
return true;
}
catch (Exception e)
{
Log.d("Couldn't show call log.", e.getMessage());
}
return false;
}
The reason behind this mess is the fact that apps authoritatively responsible for call logging and notifying users about missed calls (stock phone apps) use cached values. Why? Because of overall performance. You need to somehow notify those apps that Call Log has changed (seen means changed, as well) and that it should update it. It would be nice if all such apps on all devices would receive a broadcast in order to refresh, but as far as I know, it's not the case.
I hope someone will find a better way to force refresh on stock phone apps.
I have being upgrading an application to use the new Mobile Android GNSK but I have noticed that using the new MusicID-Stream is a little bit tricky. If the "identifyAlbumAsync" method get executed before the "audioProcessStart" method(since this need to be executed in a different thread), the application just crashes. In the Gracenote Demo application, the "audioProcessStart" method is continuously running so there is no need to synchronize its execution with the "identifyAlbumAsync" method call. Is it the way it is supposed to be used? It will be convenient if the application didn't crashed at least when the methods are not executed in order. Also in our application, we don't want to have the "audioProcessStart" method continuously like it is done in the demo application. We only want to run the "audioProcessStart" method when the user request identification and when the song playing gets identified , we want to stop the audio processing by calling "audioProcessStop". Is there an easy way to do this? Right now, we are getting the Thread where "identifyAlbumAsync" is running to sleep for 2 seconds in order to make sure that the Thread where the "audioProcessStart" method is supposed to run has time to get executed. Thank you in advance for your prompt response
In the upcoming 1.2 release, IGnMusicIdStreamEvents includes a callback that signals audio-processing has started, and an ID can be synced with this, e.g.:
#Override
public void musicIdStreamProcessingStatusEvent( GnMusicIdStreamProcessingStatus status, IGnCancellable canceller ) {
if (GnMusicIdStreamProcessingStatus.kStatusProcessingAudioStarted.compareTo(status) == 0) {
try {
gnMusicIdStream.identifyAlbumAsync();
} catch (GnException e) { }
}
}
Thanks for the feedback, you're right about this issue. Unfortunately right now sleeping is the best solution. But we are adding support for an explicit sync event in an upcoming release, please stay tuned.