Need help coding android manifest for broadcast receiver

閲覧: 91 回
最初の未読メッセージにスキップ

Carlos Choy

未読、
2015/03/16 13:51:512015/03/16
To: python-...@googlegroups.com
Hello

I am needing help on producing the correct entry in the Android manifest file for a broadcast receiver.

The project itself is to use Kivy to write a service that starts on bootup.  However being new to Kivy, and not finding any example on writing just a service per-se,  I decided to start with a well-known example found here: http://kivy.org/planet/2014/01/building-a-background-application-on-android-with-kivy/

The sample given starts an app (activity) that then starts a service.  I used that example and modified it.

As I am hoping to start the service on bootup, I put the following code in "/service/main.py" where main starts:
if __name__ == '__main__':
    br = BroadcastReceiver(on_broadcast,actions=['boot_completed']
    br.start()
   
and since I was working with the service part of the code, and since build.py has no way of modifying the service tag, I modified the AndroidManifest.tmpl.xml file in the <service> section as follows:

<service android:name="org.renpy.android.PythonService" android:process=":PythonService">
    <receiver android:name="XXX" android:enabled="true" android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</service>


where in XXX I tried each one of the following:
.BroadcastReceiver
org.renpy.android.BroadcastReceiver
org.renpy.android.broadcast.BroadcastReceiver

and in my build.py command line I added: --permission RECEIVE_BOOT_COMPLETED which correctly adds <user-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> in the resulting AndroidManifest.xml file.  The above additions to the AndroidManifest.tmpl.xml file are also faithfully replicated in the resulting manifest as well.

And after deploying it and restarting the android device and viewing the adb logcat, I found that app (or the service) are never started - that is, no intent of boot completed initiates a new process id for the app (or the service) to begin.

So I moved the python broadcast receiving code to the "/main.py" in the app itself and put in the "build" method as follows:

def build(self):
    if platform=='android':
        from android import AndroidService
        service = AndroidService("my pong service",'running')
        service.start('service started')
        self.service = service
    br = BroadcastReceiver(on_broadcast,actions=['boot_completed'])
    br.start()


and I altered the AndroidManifest.tmpl.xml so that the <receiver> is no longer in the <services> tag but rather in the <application>, such that it looks as follows:

    <receiver android:name="XXX" android:enabled="true" android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</application>

This time adb logcat does show an attempt to start the app on bootup because I see a process id given to the app to start it.  However, here is the logcat:

E/AndroidRuntime( 5092): FATAL EXCEPTION: main
E/AndroidRuntime( 5092): Process: org.beacon.testservice2, PID: 5092
E/AndroidRuntime( 5092): java.lang.RuntimeException: Unable to instantiate receiver org.beacon.testservice2.ServiceApp: java.lang.ClassNotFoundException: Didn't find class "org.beacon.testservice2.ServiceApp" on path: DexPathList[[zip file "/data/app/org.beacon.testservice2-1.apk"],nativeLibraryDirectories=[/data/app-lib/org.beacon.testservice2-1, /vendor/lib, /system/lib]]
E/AndroidRuntime( 5092):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2762)
E/AndroidRuntime( 5092):     at android.app.ActivityThread.access$1800(ActivityThread.java:174)
E/AndroidRuntime( 5092):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1397)
E/AndroidRuntime( 5092):     at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 5092):     at android.os.Looper.loop(Looper.java:146)
E/AndroidRuntime( 5092):     at android.app.ActivityThread.main(ActivityThread.java:5748)
E/AndroidRuntime( 5092):     at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 5092):     at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime( 5092):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
E/AndroidRuntime( 5092):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
E/AndroidRuntime( 5092):     at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 5092): Caused by: java.lang.ClassNotFoundException: Didn't find class "org.beacon.testservice2.ServiceApp" on path: DexPathList[[zip file "/data/app/org.beacon.testservice2-1.apk"],nativeLibraryDirectories=[/data/app-lib/org.beacon.testservice2-1, /vendor/lib, /system/lib]]
E/AndroidRuntime( 5092):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
E/AndroidRuntime( 5092):     at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
E/AndroidRuntime( 5092):     at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
E/AndroidRuntime( 5092):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2757)
E/AndroidRuntime( 5092):     ... 10 more

where java.lang.ClassNotFoundException says "....ServiceApp" when I code in the manifest <receiver android:name=".ServiceApp" .../>
(ServiceApp is the main app in http://kivy.org/planet/2014/01/building-a-background-application-on-android-with-kivy/),

and I also get the same java.lang.ClassNotFoundException with all of the following as coded above in the name of the receiver tab:
.BroadcastReceiver
org.renpy.android.BroadcastReceiver
org.renpy.android.broadcast.BroadcastReceiver


So my questions are:

1) what should my receiver tag name property be coded as?
2) can this whole thing be done without the app (activity) and only with just the service, and if so, how would I go about doing it?
3) the callback for the callback receiver is a function called on_broadcast, as follows:
def on_broadcast(context,intent):
    extras = intent.getExtras()
where can I find out more about what those extras are, what the intent methods and properties are, and also the same for the context?

Thanks for any help!  I feel I am close to solving this but just seem to be missing some info.

Carlos Choy

未読、
2015/03/28 2:26:052015/03/28
To: python-...@googlegroups.com
全員に返信
投稿者に返信
転送
新着メール 0 件