I am trying to send Push notifications via Parse and integrating product flavors. When I implement product flavors, i am not able to receive Parse Push Notifications. Does anyone have any advise on correcting this issue
Gradle app file:
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.example.project"
minSdkVersion 16
targetSdkVersion 21
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
productFlavors{
freeApp{
applicationId "com.example.project.free"
}
premiumApp{
applicationId "com.example.project.paid"
}
}
}
dependencies {
compile files('libs/android-async-http-1.4.2-66-g4b6eb97.jar')
compile files('libs/android-support-v13.jar')
compile files('libs/bolts-android-1.2.0.jar')
compile files('libs/Parse-1.9.2.jar')
compile files('libs/ParseCrashReporting-1.9.2.jar')
}
Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.project"
android:versionCode="1"
android:versionName="1.1" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.project.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.project.permission.C2D_MESSAGE" />
<application
android:name="com.example.project.Application"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="com.example.project.MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="com.parse.push.notification_icon" android:resource="@drawable/ic_launcher"/>
<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.ParsePushBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.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" />
<!--
IMPORTANT: Change "com.parse.starter" to match your app's package name.
-->
<category android:name="com.example.project" />
</intent-filter>
</receiver>
</application>
NOTE: As has been observed, my solution is somewhat more complicated than the one by Morten Holmgaard below. Needless to say, had I known of the simpler solution I would have proposed that one. However, my answer does contain some relevant explanation and it also was the only - and only correct - answer for five weeks, so I will leave it up.
===========================================================================
What's the problem?
I think the reason you are not receiving any pushes is that in your AndroidManifest.xml you declare the following for Parse:
<permission android:name="com.example.project.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.project.permission.C2D_MESSAGE" />
<receiver android:name="com.parse.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" />
<!--
IMPORTANT: Change "com.parse.starter" to match your app's package name.
-->
<category android:name="com.example.project" />
</intent-filter>
</receiver>
The package names, however, are defined as
applicationId "com.example.project.free"
and
applicationId "com.example.project.paid"
So the package names don't match the declarations in your AndroidManifest.xml and therefore Parse is unable to receive pushes. Actually, if you look at your logcat output, you should be seeing a message from Parse that tells you exactly what is missing in your AndroidManifest.xml.
So, how to solve this?
This is a bit of a tricky situation but it can be done:
1.) Remove the two parts I quoted above from the AndroidManifest.xml in your main
source set (src/main/AndroidManifest.xml
).
2a.) Create an AndroidManifest.xml in your free
source set (src/free/AndroidManifest.xml
) and enter the following:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<permission
android:name="com.example.project.free.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.project.free.permission.C2D_MESSAGE" />
<application>
<receiver
android:name="com.parse.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" />
<category android:name="com.example.project.free" />
</intent-filter>
</receiver>
</application>
</manifest>
2b.) Do the same for the paid
source set. Be sure to replace the package name correctly in the AndroidManifest.xml.
Why does this work?
Because gradle does not replace the src/main/AndroidManifest.xml
with the src/free/AndroidManifest.xml
but instead merges them into one. So if you just leave the declarations out of the main
source set and put them in to free
and paid
you will get a correctly merged AndroidManifest.xml for each flavor.