I have literally followed the examples for implementing GCM inside an android app and the app is receiving the messages using the following code:
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp;
comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
The problem is that the GcmIntentService (public class GcmIntentService extends IntentService) is never being run? Am I missing something or should it usually fire the onHandleIntent method?
In case in any way related the Manifest file is below, thanks in advance:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.diversivi.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19"/>
<application
android:label="#string/app_name"
android:icon="#drawable/ic_launcher">
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
<activity
android:name=".DemoActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.diversivi.test" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.INTERNET" />
<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="com.diversivi.test.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.diversivi.test.permission.C2D_MESSAGE" />
</manifest>
I don't see your GcmIntentService service declared in the manifest. That could be the problem.
In addition, the following line
comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName());
assumes that the GcmIntentService class is in the main package of your app (i.e. its full name is com.diversivi.test.GcmIntentService). If that's not the case, the broadcast receiver can't find the service class.
Related
I have a program with a service and if I reboot my device also the service should Restart. But this only works on the Emulator if I try this on my real device the service doesn't start at all.
Does someone know what I'm doing wrong or why it only works on Emulator?
BroadcastReviever:
#Override
public void onReceive(Context context, Intent intent) {
//we double check here for only boot complete event
if(intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED))
{
//here we start the service
Intent serviceIntent = new Intent(context, UploadService.class);
context.startService(serviceIntent);
}
}
Manifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="Upload FTP"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<receiver
android:name=".BootCompletedIntentReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter >
</activity>
<service
android:name=".UploadService"
android:isolatedProcess="false"
android:exported="true"
android:enabled="true"/>
</application>
The emulator is at API 23 and real device is API 27.
I'm Building for a min API Level 23 and max API Level 27
EDIT
Now I have also tried the program with a emulator and android API 27 and there when I start my program and then I restart the emulator, the emulator doesn't start any more. As soon as the emulaor has started he begins to reboot again and that in a endless loop. (Real device starts normal just doesn't restarts service)
try to use LOCKED_BOOT_COMPLETED receiver as follow:
<receiver
android:name=".BootReceiver"
android:directBootAware="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
<!-- For pre-N devices -->
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
don't forget permission
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
take a look here for more explanation
Now I fixed in on my own it was easier then i thought
public class BootCompletedIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context, YourClass.class);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) {
context.startForegroundService(i);
}
else {
context.startService(i);
}
}
I had some weird experience if I don't put full URI,
for example .BootCompletedIntentReceiver would become com.company.BootCompletedIntentRecevier.
I know it sounds dumb but I had many weird regressions when not explicitly stating things on the Manifest with modern SDKs.
I am attempting to migrate an app from Parse to OneSignal. Things have been running fairly smooth except for one issue. If the app has not already been started, clicking (opening) the notification does not launch the app and bring it to the foreground.
I am using a custom onNotificationOpenedHandler:
Main Activity, onCreate
// Init OneSignal
OneSignal.startInit(this).setNotificationOpenedHandler(new NotificationOpenHandler()).init();
NotificationOpenedHandler, also in the launcher Main Activity:
class NotificationOpenHandler implements OneSignal.NotificationOpenedHandler {
// This fires when a notification is opened by tapping on it.
#Override
public void notificationOpened(OSNotificationOpenResult result) {
JSONObject data = result.notification.payload.additionalData;
String stationName = data.optString("stationName");
String timestamp = data.optString("timestamp");
String filename = data.optString("filename");
String url = getString(R.string.callResourceUrl) + filename;
Log.d("APP", "Notification clicked");
Intent intent = new Intent(getApplicationContext(), CallActivity.class);
intent.putExtra("stationName", stationName);
intent.putExtra("time", timestamp);
intent.putExtra("url", url);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
Here is my Android Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.opheliadesign.tevfd">
<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" />
<application
android:supportsRtl="true"
android:allowBackup="true"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:logo="#drawable/ic_launcher"
android:launchMode="singleInstance"
android:theme="#style/Theme.Tevfd">
<activity android:name="com.example.app.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".CallActivity"
android:label="#string/title_activity_call"
android:parentActivityName=".MainActivity"
android:screenOrientation="portrait" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.app.MainActivity" />
</activity>
<meta-data android:name="com.onesignal.NotificationOpened.DEFAULT" android:value="DISABLE" />
</application>
</manifest>
Any ideas?
UPDATE
Previously, using Parse, I utilized a BroadcastReceiver with a PendingIntent. It seems a bit unclear how to accomplish this with OneSignal as so much seems to be configured automatically.
If I remove the custom Intent, the application comes to the foreground.
Any help would be greatly appreciated.
I have a class which the code as follows:
public class CallManager extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
tManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Log.i("onReceive","here");
}
}
Permissions on the manifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.PROCESS_INCOMING_CALLS" />
<uses-permission android:name="android.permission.BOOT_COMPLETED" />
Receiver intent filter:
<receiver android:name="com.ram.tapdetector.CallManager">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
For some reason, nothing is getting logged from the onReceive function?
How can I fix this? Any help would be appreciated, thanks.
You need the following in your AndroidManifest.xml file:
1) In your element:
`<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />`
2) In your element (be sure to use a fully-qualified [or relative] class name for your BroadcastReceiver):
<receiver android:name="com.example.CallManager">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
`
In MyBroadcastReceiver.java:
` package com.example;
public class CallManager extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
tManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Log.i("onReceive","here");
}
}`
if you are using HTC mobile-
Along with
`<action android:name="android.intent.action.BOOT_COMPLETED" /> `
also use,
`<action android:name="android.intent.action.QUICKBOOT_POWERON" />`
HTC devices dont seem to catch BOOT_COMPLETED
You have to add the permission
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
instead of
<uses-permission android:name="android.permission.BOOT_COMPLETED" />
for BOOT_COMPLETED. Checkout the documentation here.
As far as I see everything else should be ok.
p.s.: if you want to receive a broadcast event for incoming calls, use permission
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
and declare your intent filter with
<receiver
android:name="com.ram.tapdetector.CallManager"
android:enabled="true">
<intent-filter
android:priority="1000">
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Check this nice tutorial for more.
Have you tried with flags:
android:enabled="true"
android:exported="true"
?
This question is outdated, but I have a suggest anyway.
Be carefull, you have twice times the permission :
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
This could generate some errors when you try to run your application.
I'm using GCM in my android application and when I try to register the device with GCM (with the command gcm.register(SENDER_ID)) I get the SEVICE_NOT_AVAILABLE error, I tried what someone suggested here (the accepted solution) and I did get the registration id.
Why is it like that?
Android manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.appspot.smartgan"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="com.appspot.smartgan.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.appspot.smartgan.permission.C2D_MESSAGE" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Light" >
<activity
android:name="com.appspot.smartgan.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".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.appspot.smartgan" />
</intent-filter>
</receiver>
<service
android:name=".GcmIntentService"
android:enabled="true" />
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name="com.appspot.smartgan.LoginActivity"
android:label="#string/title_activity_login"
android:windowSoftInputMode="adjustResize|stateVisible" >
</activity>
<activity
android:name="com.appspot.smartgan.ChildActivity"
android:label="#string/title_activity_child" >
</activity>
</application>
</manifest>
register method:
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String message = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
message = "Device registered, registration ID=" + regid;
Log.d("SMARTGAN_PLAY", "register completed");
// send registration id to the server
sendRegistrationIdToServer();
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException e) {
message = "Error:" + e.getMessage();
}
return message;
}
}.execute(null, null, null);
}
I think issue is regarding allowed IP addresses mentioned in your Google API project.
Please check details of the project and remove IP address if present under restrict use to IP address. I faced similar problem.
If you are receiving a Register ID it means you have registered the device successfully to the GCM.
Edit:
Here is a good tutorial for GCM: http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
<receiver
android:name="rockit.app.beardallstreetprimary.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="rockit.app.beardallstreetprimary" />
</intent-filter>
</receiver>
<service android:name="com.google.android.gcm.GCMIntentService" android:enabled="true" />
My GCM is set up based on the Tutorial i linked above so if you read through that aswell it should work for you it looks like your not far off. I will say the Manifest is very picky and you need to ensure that you link your Packages fully.
Also you dont need the Register Intent
I have a small application that uses two activities. Both the activities inherit from MapActivity and display a map (com.google.android.maps).
Since the Android Google Map documentation says
Only one MapActivity is supported per
process. Multiple MapActivities
running simultaneously are likely to
interfere in unexpected and undesired
ways.
I modified my manifest to run the two activities in two different processes (I have removed some lines to make it short):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
android:theme="#android:style/Theme.Light">
<uses-library android:name="com.google.android.maps" />
<activity
android:name=".Activity1"
android:process=".Activity1">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>Unit
</activity>
<activity
android:name=".Activity2"
android:process=".Activity2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>
Now the application runs fine but I have problems when I what to run Unit Tests on both the Activities.
For example:
package com.example.myapp;
public class Activity1Test extends ActivityInstrumentationTestCase2<Activity1> {
Activity1 mActivity;
public Activity1Test() {
super("com.example.myapp.Activity1", Activity1.class);
}
#Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
setActivityIntent(new Intent());
mActivity = getActivity(); //An exception is thrown at this line
}
}
When I call the getActivity() method an exception is thrown:
java.lang.RuntimeException: Intent in process com.example.myapp resolved to different process .Activity1: Intent { flg=0x10000000 cmp=com.example.myapp/.Activity1 }
at android.app.Instrumentation.startActivitySync(Instrumentation.java:377)
at android.test.InstrumentationTestCase.launchActivityWithIntent(InstrumentationTestCase.java:119)
at android.test.ActivityInstrumentationTestCase2.getActivity(ActivityInstrumentationTestCase2.java:100)
at com.example.myapp.Activity1Test.setUp(Activity1Test.java:28)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:520)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
Is there a way to make the Unit Test to "resolve" the correct process?
Instrumentation runs all of your application components in the same process.