1

I have some project #1 which is library.

E.g. it works with GCM (C2DM) messages and has permissions (my_package.permission.C2D_MESSAGE and others) inside itself manifest file.

I connect project #1 (lib) to project #2 (some app).

Question: Is it possible to automatically activate permissions from project #1 for project #2 ?

olegflo
  • 1,105
  • 3
  • 17
  • 26

2 Answers2

2

Not presently. If "library" means "Android library project", this may be possible in the future.

However, in your specific case, that will probably never work. Some of the GCM framework classes are going to use the application's package, regardless of whether the code that uses GCM is in an Android library project or not.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Hi CommonsWare...I was wondering if I could ask for some clarity on this. I have an app (say, packagename "MyApp") which uses GCM. I will soon need to maintain two different versions of this app, so I was thinking of turning "MyApp" into a library project which is referenced by two others ("MyApp-A" and "MyApp-B"). MyApp-A and -B must be able to exist on the same device, and use GCM independently of each other. To accomplish this, I think I'll have to move the GCM stuff out of MyApp and into MyApp-A and MyApp-B, identical except for package name. Is this essentially what you're saying here? – Cephron Jan 09 '13 at 22:28
  • @Cephron: Your manifest entries will need to be in MyApp-A and MyApp-B. Your Java code could be in the library -- I cannot think of anything in GCM that would preclude this. – CommonsWare Jan 09 '13 at 23:08
  • @CommonsWare: I have the same situation as described by Cephron. I have the GCMBroadcastReceiver entries in MyApp-A's manifest, but the onRegistered() callback is not coming in. Specifically, I've tried both "MyApp" (the library project) and "MyApp-A" (the dependent project) for the android:name of the . I hope you are right, but are you sure it's not necessary to move the GCM code out of the library, and into each dependent application? Thanks. – gcl1 Mar 11 '13 at 15:06
  • @Cephron: were you able to make this work with the GCM code left in the library project? Thanks. – gcl1 Mar 11 '13 at 15:07
  • @gcl1: I haven't tried this. I am not aware of anything in GCM that would preclude the implementation being in the library project, so long as the app's package name is used for the things in the app's manifest. You might try the `android-gcm` Google Group if you cannot get this working. – CommonsWare Mar 11 '13 at 16:51
  • @CommonsWare: For now, I got it working by moving the GCMIntentService to my dependent projects. I can live with that for now. I'd still prefer to have it in only the library project, so I'll update later if I figure out what the hitch was. Thanks. – gcl1 Mar 11 '13 at 18:47
2

I have gotten this to work with AndroidStudio and mainfestmerging. I have all of the GCM permissions, the broadcast receiver and the intent receiver in a library project. The intent service in my library calls an intent service in my app. In my case, the app, registers this service name with the library and it is stored in a database, so the library intent service knows which intent to use for the application. I have no GCM code or permissions anywhere in my application. Here is my 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>

and here is my 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>

As CommonsWare points out, you have to be careful with your packages. The package for your ComponentName for your intent services (library or app) is always the application package, as the code for my BroadcastReceiver illustrates.

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Explicitly specify that GcmIntentService will handle the intent.
        ComponentName receiveIntentLauncherComponent =
                new ComponentName(context.getPackageName(),
                                  GcmReceiveIntentLauncher.class.getName());
        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, (intent.setComponent(receiveIntentLauncherComponent)));
        setResultCode(Activity.RESULT_OK);
    }
}

Also, be advised that you can't use the Google BroadcastReceiver; you need to define your own as above. In principle I could have launched the app intent from the broadcast receiver, but since I get the app intent name from a database, it is ill advised to do such operations in a broadcast receiver.

Hope that helps.

museofwater
  • 409
  • 5
  • 9