Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android Added JobScheduler for Android Lollipop and newer #42

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

DoktorAerzt
Copy link

@DoktorAerzt DoktorAerzt commented Jul 12, 2018

In this PR i added support for JobScheduler. The point is, we don´t need an Service witch hold the AlarmManager "online" and we don´t need to safe the notification for reboot.
Another point against the use of Service is that at android 8.0 they are very limitted.

Fixes issue #7 when using Lollipop or newer .

Changes proposed in this pull request:

  • Make use of JobScheduler
  • Will hold the notification over a reboot for Android. Only when using Lollipop or newer and you need to add the Permission "RECEIVE_BOOT_COMPLETED". When you don´t have the permission then the Notification will be deleted on reboot.

Nice wishes from germany

@DoktorAerzt DoktorAerzt reopened this Jul 12, 2018
@DoktorAerzt
Copy link
Author

I Forgot a commit, thats why i closed and reopen the PR

@agharium
Copy link

Hi.. I really need this. How do I install your forked project?.. I tried to compile and replace my files with yours, but it gave me a reference error..

@DoktorAerzt
Copy link
Author

DoktorAerzt commented Jul 14, 2018

You can just download the nuget file from the temporary build. https://ci.appveyor.com/project/edsnider/localnotificationsplugin/build/3.0.1-pr42-build24/artifacts

Then you safe it on your PC and add the folder as nuget repository. Then you can update it with nuget, you just need to check "pre Version " or something like that. And you need to choice your newly created repo

I hope me little write down will help you

@agharium
Copy link

agharium commented Jul 14, 2018

Thank you so much!

It throws this error when compiling to Release in Android with linking properties set to SDK Assemblies:

Falha inesperada da tarefa "LinkAssemblies".
Mono.Linker.MarkException: Error processing method: 'System.Void Plugin.LocalNotifications.LocalNotificationsImplementation::Show(System.String,System.String,System.Int32)' in assembly: 'Plugin.LocalNotifications.dll' ---> Mono.Cecil.ResolutionException: Failed to resolve Android.App.NotificationChannel
   em Mono.Linker.Steps.MarkStep.HandleUnresolvedType(TypeReference reference)
   em Mono.Linker.Steps.MarkStep.MarkType(TypeReference reference)
   em MonoDroid.Tuner.MonoDroidMarkStep.MarkType(TypeReference reference)
   em Mono.Linker.Steps.MarkStep.MarkMethodBody(MethodBody body)
   em Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method)
   em Mono.Linker.Steps.MarkStep.ProcessQueue()
   --- Fim do rastreamento de pilha de exceções internas ---
   em Mono.Linker.Steps.MarkStep.ProcessQueue()
   em Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue()
   em Mono.Linker.Steps.MarkStep.Process()
   em Mono.Linker.Steps.MarkStep.Process(LinkContext context)
   em Mono.Linker.Pipeline.Process(LinkContext context)
   em MonoDroid.Tuner.Linker.Process(LinkerOptions options, ILogger logger, LinkContext& context)
   em Xamarin.Android.Tasks.LinkAssemblies.Execute(DirectoryAssemblyResolver res)
   em Xamarin.Android.Tasks.LinkAssemblies.Execute()
   em Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   em Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()	ProMama.Android			

With the linking set to "None", the error is not thrown and it compiles and runs just fine.

I'll be testing this version itself in the next couple of hours (closing the app and rebooting the phone, etc.) and I'll come back with some feedback.

Also, you think you may have a fix or workaround for the link thing? Without the Assembly link, my apk size goes from 39MB to 66MB.

I don't think it has anything to do with your changes to the code, probably it's due to version 3.0' changes (I was using version 2.1 until now), since the error has something to do with Android.App.NotificationChannel.

@DoktorAerzt
Copy link
Author

For with SDK Version are you building and using?

@agharium
Copy link

7.1 (so I could use version 2.1, otherwise it wouldn't work)

Maybe it's because of that.. good point

@DoktorAerzt
Copy link
Author

Could you try to build it with Android 8.1 ?

@agharium
Copy link

Yeah, just built it on 8.1 and it went just fine. Tested it with instant notifications and it's working alright. Now I'm testing with the app closed and rebooting.

@agharium
Copy link

It's working good. But why the icon I set is not being used?

screenshot-1531681250693

If the notification is fired while the app is open, it works out ok:

screenshot-1531681636546

Do you have any idea of how I can fix this?

@DoktorAerzt
Copy link
Author

First things first, i was not able to get the Notification running when the app is closed and you had started the app from Visual Studio. But when you start the app in the Emulator from icon then all should work.

For the icon i need to make a new commit, i will work this evening on it.

@agharium
Copy link

First things first, i was not able to get the Notification running when the app is closed and you had started the app from Visual Studio. But when you start the app in the Emulator from icon then all should work.

Yeah. I got it working by archiving the android project and then I got the .apk and installed it on my phone. It worked fine. But it still didn't work when I rebooted the phone.

For the icon i need to make a new commit, i will work this evening on it.

Thank you very much!

@DoktorAerzt
Copy link
Author

Im testing the reboot. Do you have first marked "RECEIVE_BOOT_COMPLETED" in manifest and ask for that permission?

Could you check in your app what

Application.Context.CheckSelfPermission("RECEIVE_BOOT_COMPLETED") 

will give you?

@agharium
Copy link

07-17 09:53:52.715 D/MyApp (30372): Denied

It's denied.. How can I ask for that permission on runtime? I've searched a lot and this was what I came up with:

async Task GetReceivedBootCompletePermission()
{
    string[] BootPermission = { Manifest.Permission.ReceiveBootCompleted };

    if (CheckSelfPermission(BootPermission[0]) != (int)Permission.Granted && (int)Build.VERSION.SdkInt >= 23)
    {
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.SetTitle("Permissão de inicialização");
        alert.SetMessage("O aplicativo precisa da permissão de inicialização para enviar notificações corretamente.");
        Dialog dialog = alert.Create();
        dialog.Show();

        RequestPermissions(BootPermission, 0);
    }
}

I wrote that code on MainActivity.cs, turned my OnCreate method into an async method and invoked it with await GetReceivedBootCompletePermission();, but nothing happens. Any idea of how I can do this?

@DoktorAerzt
Copy link
Author

This is one think i also need to get to work. And at the moment i have no fix for it.

@agharium
Copy link

No problem, man. You already helped a lot with fixing the issue where the notifications wouldn't fire if the app was closed, and that's a lot for me. Thank you!

@DoktorAerzt
Copy link
Author

DoktorAerzt commented Jul 19, 2018

Thank you but the fix for the permission error should be a easy one.

@agharium
Copy link

agharium commented Jul 22, 2018

I see. If you achieve it, let me know, please :)

@agharium
Copy link

Hey, I'm getting some unexpected behavior.

When I try to install on any Android below 8.0, this error shows up:

3>Unexpected install output: Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/vmdl1165202956.tmp/base.apk (at Binary XML file line #28): <service> does not have valid android:name]
3>
3>   em Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName)
3>   em Mono.AndroidTools.AndroidDevice.<>c__DisplayClass94_0.<InstallPackage>b__0(Task`1 t)
3>   em System.Threading.Tasks.ContinuationTaskFromResultTask`1.InnerInvoke()
3>   em System.Threading.Tasks.Task.Execute()
3>
3>A implantação falhou em Motorola Moto G (5) Plus

Now, the error says "[...] (at Binary XML file line #28): <service> does not have valid android:name [...]". In line #28 on my project's generated AndroidManifest.xml (found on "ANDROID_PROJECT_FOLDER\obj\Debug\android"), this shows up:

<service android:name="Plugin.LocalNotifications.ScheduledJobHandler" android:permission="android.permission.BIND_JOB_SERVICE" />

The pattern in all other service's android:name's found in my generated AndroidManifest is some kind of md5 string like this:

<service android:name="md5dcb6eccdc824e0677ffae8ccdde42930.KeepAliveService" />

How can I fix this? This is somewhat of an urgent matter for me. I have a ten days' deadline to finish this project.

@agharium
Copy link

Hey, checking the changes you made, I noticed you set the service like this:

[Service(Name = "Plugin.LocalNotifications.ScheduledJobHandler", Permission = "android.permission.BIND_JOB_SERVICE")]

from here

But I looked up for the "KeepAliveService" code (it's the other service I have in my generated AndroidManifest and it has the md5 string before it's name) and it's written simply like this:

[Service]

from here

Maybe, if you set it like this, it will work fine:

[Service(Permission = "android.permission.BIND_JOB_SERVICE")]

It's just an idea. Maybe it can help, maybe not.

Thanks.

@DoktorAerzt
Copy link
Author

The point is, at my phone (running android 7) i have no problem with the installation.

Could you send me your complete android manifest? Maybe it will help.

And where do you get the error from?
You builded the app and copyed to you android 7 device and tryed to install it there?

@DoktorAerzt
Copy link
Author

DoktorAerzt commented Jul 24, 2018

And the Name shouldn´t be the problem.

Look https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/services/creating-a-service/

And please also mention what build optimisation tools you use. Maybe the service get cut out too safe some space.

@agharium
Copy link

You builded the app and copyed to you android 7 device and tryed to install it there?

If I try to install with .apk, it gives an error saying that "there was a problem when analyzing the package".

And where do you get the error from?

If I try to install with Visual Studio (on Release or Debug mode, error happens both ways), it throws out the error I already sent you:

3>Unexpected install output: Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/vmdl1165202956.tmp/base.apk (at Binary XML file line #28): <service> does not have valid android:name]
3>
3>   em Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName)
3>   em Mono.AndroidTools.AndroidDevice.<>c__DisplayClass94_0.<InstallPackage>b__0(Task`1 t)
3>   em System.Threading.Tasks.ContinuationTaskFromResultTask`1.InnerInvoke()
3>   em System.Threading.Tasks.Task.Execute()
3>
3>A implantação falhou em Motorola Moto G (5) Plus

This is my AndroidManifest before compiling:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="br.gov.rs.osorio.promama" android:installLocation="auto" android:versionCode="1" android:versionName="1.0">
	<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="27" />
  <uses-permission android:name="android.permission.CAMERA" />
  <!--<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />-->
	<application android:label="Pró-Mamá" android:icon="@drawable/icon">
		<provider android:name="android.support.v4.content.FileProvider" android:authorities="br.gov.rs.osorio.promama.fileprovider" android:exported="false" android:grantUriPermissions="true">
			<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
		</provider>
	</application>
</manifest>

And this is after compilation:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="br.gov.rs.osorio.promama" android:installLocation="auto" android:versionCode="1" android:versionName="1.0">
  <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="27" />
  <uses-permission android:name="android.permission.CAMERA" />
  <!--<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />-->
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-feature android:name="android.hardware.camera" android:required="false" />
  <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
  <application android:label="Pró-Mamá" android:icon="@drawable/icon" android:name="md53e3df0725c458c2699e003c3433b7eb1.MainApplication" android:allowBackup="true" android:debuggable="true">
    <provider android:name="android.support.v4.content.FileProvider" android:authorities="br.gov.rs.osorio.promama.fileprovider" android:exported="false" android:grantUriPermissions="true">
      <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
    </provider>
    <activity android:configChanges="orientation|screenSize" android:icon="@drawable/icon" android:label="Pró-Mamá" android:theme="@style/MainTheme" android:name="md53e3df0725c458c2699e003c3433b7eb1.MainActivity" />
    <activity android:label="Pró-Mamá" android:noHistory="true" android:theme="@style/MainTheme.Splash" android:name="md53e3df0725c458c2699e003c3433b7eb1.SplashActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <receiver android:enabled="true" android:exported="false" android:label="Connectivity Plugin Broadcast Receiver" android:name="md59628c2715c1bb8febcc7ae8402df0582.ConnectivityChangeBroadcastReceiver" />
    <receiver android:enabled="true" android:label="Local Notifications Plugin Broadcast Receiver" android:name="md51251ca0436b286678a1cd2c1ca81248e.ScheduledAlarmHandler" />
    <service android:name="Plugin.LocalNotifications.ScheduledJobHandler" android:permission="android.permission.BIND_JOB_SERVICE" />
    <activity android:configChanges="orientation|screenSize" android:name="md54cd65ac53ae710bff80022afc423e0f3.MediaPickerActivity" />
    <service android:name="md5dcb6eccdc824e0677ffae8ccdde42930.KeepAliveService" />
    <receiver android:enabled="true" android:exported="false" android:name="md51558244f76c53b6aeda52c8a337f2c37.PowerSaveModeBroadcastReceiver" />
    <provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="2147483647" android:authorities="br.gov.rs.osorio.promama.mono.MonoRuntimeProvider.__mono_init__" />
    <!--suppress ExportedReceiver-->
    <receiver android:name="mono.android.Seppuku">
      <intent-filter>
        <action android:name="mono.android.intent.action.SEPPUKU" />
        <category android:name="mono.android.intent.category.SEPPUKU.br.gov.rs.osorio.promama" />
      </intent-filter>
    </receiver>
  </application>
  <uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
  <uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />
  <uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS" />
  <uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT" />
  <uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE" />
  <uses-permission android:name="com.sonymobile.home.permission.PROVIDER_INSERT_BADGE" />
  <uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT" />
  <uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE" />
  <uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE" />
  <uses-permission android:name="com.huawei.android.launcher.permission.READ_SETTINGS" />
  <uses-permission android:name="com.huawei.android.launcher.permission.WRITE_SETTINGS" />
  <uses-permission android:name="android.permission.READ_APP_BADGE" />
  <uses-permission android:name="com.oppo.launcher.permission.READ_SETTINGS" />
  <uses-permission android:name="com.oppo.launcher.permission.WRITE_SETTINGS" />
  <uses-permission android:name="me.everything.badger.permission.BADGE_COUNT_READ" />
  <uses-permission android:name="me.everything.badger.permission.BADGE_COUNT_WRITE" />
</manifest>

I tried to install it on Android 6.0 and 7.0 with no success. But, on Android 8.0 and 8.1 it works just fine.

@agharium
Copy link

agharium commented Jul 24, 2018

And please also mention what build optimisation tools you use. Maybe the service get cut out too safe some space.

I only saw that message now..

I use only the "Linking" that comes with Xamarin. Currently is set on "Only SDK Assemblies", but I set to "None" and it didn't work as well.

And the Name shouldn´t be the problem.

Yeah, that was a long shot haha

@agharium
Copy link

agharium commented Jul 24, 2018

Hey.

So I've been running tests on different Android versions (4.4 up to 8.1 - it's the range that I need my app to work on). My conclusions are:

Android 8.1 (API 27) - works
Android 8.0 (API 26) - works
Android 7.1 (API 25) - works
Android 7.0 (API 24) - does not work
Android 6.0 (API 23) - does not work
Android 5.1 (API 22) - does not work
Android 5.0 (API 21) - does not work
Android 4.4 (API 19) - does not work (which is actually ok... JobScheduler was only added in API 21)

I can only assume that something about the manifest changed on 7.1 (API 25).

Can you verify if your phone is running 7.1 or 7.0?

Also, I tried on Android 6.0 without the plugin installed in my project and it deployed just fine, so...

@agharium
Copy link

agharium commented Jul 24, 2018

@DoktorAerzt
Copy link
Author

So my app is running on different versions. see:

grafik

I will look into your link. But im away for 2 weeks. I will look what i can do. Maybe you need to made the changes for your self.

@DoktorAerzt
Copy link
Author

Is it working now? See here for the build

@DoktorAerzt
Copy link
Author

Hi
@edsnider are there any new news when this PR will get merged? Or do i need to add something?

@EmilAlipiev
Copy link

was that merged in any version like Pre release etc?

@edsnider
Copy link
Owner

edsnider commented Dec 3, 2018

@EmilAlipiev for now, you can use CI build package: https://ci.appveyor.com/project/edsnider/localnotificationsplugin/build/3.0.1-pr42-build30/artifacts

@qkfang2
Copy link

qkfang2 commented Jan 28, 2019

I noticed some errors from app centre using the CI build package from Android 5.0 - 5.1.1.
Might need to add another check in CheckBootPermission func for version.

The method Context#checkSelfPermission(String) was added to the API 23. Also below API 23 it's pointless as the permission is always granted. Make a check for the API version before handling the permissions
https://stackoverflow.com/questions/33407250/checkselfpermission-method-is-not-working-in-targetsdkversion-22

LocalNotificationsImplementation.CheckBootPermission ()
Java.Lang.LinkageError: no non-static method "Landroid/content/ContextWrapper;.checkSelfPermission(Ljava/lang/String;)I"
Java.Interop
JniEnvironment+InstanceMethods.GetMethodID (Java.Interop.JniObjectReference type, System.String name, System.String signature)
Java.Interop
JniType.GetInstanceMethod (System.String name, System.String signature)
Java.Interop
JniPeerMembers+JniInstanceMethods.GetMethodInfo (System.String encodedMember)
Java.Interop
JniPeerMembers+JniInstanceMethods.InvokeVirtualInt32Method (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters)
Android.Content
ContextWrapper.CheckSelfPermission (System.String permission)
Plugin.LocalNotifications
LocalNotificationsImplementation.CheckBootPermission ()
Plugin.LocalNotifications
LocalNotificationsImplementation.Show (System.String title, System.String body, System.Int32 id, System.DateTime notifyTime)
giftcardbal.PageView
GiftCardListPage.Notification (System.String cardList)
java.lang.NoSuchMethodError: no non-static method "Landroid/content/ContextWrapper;.checkSelfPermission(Ljava/lang/String;)I"
mono.java.lang.RunnableImplementor.n_run(Native Method)
mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:30)
android.os.Handler.handleCallback(Handler.java:739)
android.os.Handler.dispatchMessage(Handler.java:95)
android.os.Looper.loop(Looper.java:135)
android.app.ActivityThread.main(ActivityThread.java:5343)
java.lang.reflect.Method.invoke(Native Method)
java.lang.reflect.Method.invoke(Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)

@DoktorAerzt
Copy link
Author

@wodaidai i will look into it in a few days.

@DoktorAerzt
Copy link
Author

@wodaidai sorry for the long time you needed to wait but now the fix is included.

@edsnider are there any news when this pr get merged?

@pfedotovsky
Copy link

@edsnider any updates?

@edsnider
Copy link
Owner

edsnider commented Apr 8, 2019

@DoktorAerzt could you pull in the last two commits on master?

DoktorAerzt and others added 8 commits April 17, 2019 14:11
And make use of it when the Device is newer or is Lollipop
And Fixed 2 Bugs
Removed useless Variable
Get the Correct JobScheduler
Changed Job Name to lowercase to try to fix the manifest error
The Permission aren't called RECEIVE_BOOT_COMPLETED they are called android.permission.RECEIVE_BOOT_COMPLETED
Added a check for the Version in CheckBootPermission and use PermissionChecker if the Version is not Marshmallow or higher
@DoktorAerzt
Copy link
Author

@edsnider i made the changes, is there anything else i need to change?

@edsnider
Copy link
Owner

@DoktorAerzt awesome, thank you! The .sln still has changes that shouldn't need to be committed.

@DoktorAerzt
Copy link
Author

@edsnider i hope it´s better now.

@DoktorAerzt
Copy link
Author

@edsnider is there something more i missed?

@edsnider
Copy link
Owner

edsnider commented May 6, 2019

@DoktorAerzt Nope, I think that's it... thank you! Could you enable maintainer edits on this pull request? I'd like to make a few minor code cleanup adjustments before I merge it into master.

@DoktorAerzt
Copy link
Author

@edsnider all right. Maintainer Edits should be enabled.

@JaoHundred
Copy link

Any news on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants