22

I want to develop a library project which consists of a GCMIntentService and it performs GCM registration process and receives messages sent over GCM.

I have used AIDL to expose my library project service to host application,but I need to declare the service in application project also..... How can I avoid this?
Also I needed to declare all the permissions required for GCM in application manifest too.
Is there any way in which all permissions and services from library project can be referenced from host application without having to declare them again in the manifest?

I have searched over this and found:
1. Is it possible encapsulate permission inside Android framework (library)
Which clearly says that what I'm trying to achieve is not possible.
2. Something useful Library Project does the manifest file merge? The answer by @Hayes Haugen says that "AndroidManifest.xml merging is supported in version 20 of the ADT tools"
I'm using ADT version 20.0.3

Is there anyway I can achieve having library project providing GCM integration?

Community
  • 1
  • 1
Zeba
  • 3,041
  • 1
  • 28
  • 39
  • 1
    Enable with the manifestmerger.enabled property – Leonidos Jan 31 '13 at 08:43
  • @Leonidos I have 'manifestmerger.enabled=true ' in my project.properties file... Yet i get an exception when i use permissions specified in library project manifest. – Zeba Jan 31 '13 at 11:26

5 Answers5

2

What error are you getting?

This is working great for me:

Library Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="org.plasync.client.android"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Needed for devices with 4.02 or earlier android -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <permission android:name="org.plasync.client.android.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="org.plasync.client.android.permission.C2D_MESSAGE" />
   <!-- <uses-permission android:name="com.playsnc.client.android.data.permission.READ_WRITE"/>-->

    <application android:label="" android:icon="@drawable/ic_launcher">
        <!-- This is the signin activity for plAsync -->
        <activity android:name="org.plasync.client.android.AsyncMultiplayerSetupActivity"
                  android:label="@string/SETUP_ACTIVITY_NAME"
                  android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">

            <!-- This is the intent for getting the local user.  Apps that use plAsync must use this
                 intent to retrieve the local user, or allow the user to signin.  Apps should
                 use startActivityForResult as the sigin activity may require user interaction -->
            <intent-filter>
                <action android:name="@string/SETUP_ASYNC_MULTIPLAYER_SESSION_ACTION"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <receiver android:name="org.plasync.client.android.gcm.GcmBroadcastReceiver"
                  android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            </intent-filter>
        </receiver>

        <service android:name="org.plasync.client.android.gcm.GcmReceiveIntentLauncher"/>
    </application>
</manifest>

Application Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.plasync.client.android.testapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name="org.plasync.client.android.testapp.AsyncMultiplayerTestAppActivity"
            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=".search.FriendSearchActivity"
                  android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <meta-data android:name="android.app.searchable"
                android:resource="@xml/searchable"/>
        </activity>

        <service android:name=".AsyncMultiplayerTestAppMessageReceiver"/>
    </application>

</manifest>

Also, I wonder if you solution with services and AIDL is overkill. I started down that route, but got turned off by the complexity of the interprocess communication for my situation. I have been able to simply define a broadcast receiver and intent service in my library, that launches an intent service in my app. You just have to be careful with package names. and component names. The package name will always be the package name for your app, but the component name will be the class name for your service.

museofwater
  • 409
  • 5
  • 9
1

I hope this helps, I had a similar problem as you and could not find a solution which did not cause some or other problem. My solution was when someone uses my application builder it drops my library into the application as well as my copy of the GCMintent class and CGM lib file.

The system then automatically adds the permissions to the manifest of his app and out pops a new apk for him to use. This is just how we do it, I hope this might tend you in the direction of a solution.

David
  • 3,927
  • 6
  • 30
  • 48
1

Take a look at UrbanAirship's solution to that particular problem.

UrbanAirship Android documentation

Specially the part Configuring your Client Application

yyouf
  • 51
  • 3
0

afaik the manifest of the library is completely ignored when compiling

NikkyD
  • 2,209
  • 1
  • 16
  • 31
  • 3
    It isn't ignored if you enable `manifestmerger` in the project properties (or use Gradle, where merging is the default). – Ken Mar 05 '14 at 15:47
  • at the time of the answer this wasnt working properly (for me) – NikkyD Dec 14 '16 at 12:32
0

For the merge part, I had the same problem of having to declare my service from a lib project in the manifest of the main project again.

For those whom manifestmerger is not working with Eclipse (as a reminder, the idea is to put the following line in project.properties):

manifestmerger.enabled=true

... you may then need to clean the main project so it can works... (menu Project, Clean...)

It sounds stupid, but since I had trouble finding why modifying project.properties was not working, other may have had the same problem.

You can check if the merge was correctly done by checking the file bin/AndroidManifest.xml.

Vincent Hiribarren
  • 5,254
  • 2
  • 41
  • 65