Is it possible encapsulate permission inside Andro

2019-07-26 20:22发布

问题:

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 ?

回答1:

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.



回答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.