Trying to implement google C2DM service.
registrationIntent.putExtra("app", PendingIntent.getBroadcast(context,0,new Intent(), 0));
registrationIntent.putExtra("sender","example#gmail.com");
context.startService(registrationIntent);
Almost every tutorial features this line of code. Is this a service that I must code? or does Android know how to handle this type of Intent. I am calling this method from a helper class with the default constructor. I pass the current Context to the this above method to create the registration Intent. Anyone have some insight on how this works or where my program will go?
No, you don't have to write a service. You need to send an intent to a Google's service. You've omitted the first line, where the intent is created, and that contains the service name. It's something like this typically:
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
The line com.google.android.c2dm.intent.REGISTER identifies the Google's service.
Now, you still have to write the broadcast receiver that'll receive the registration result (either an ID or error). And a receiver to receive the actual C2DM messages.
You left out the most interesting piece of code
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
Is this a service that I must code? or does Android know how to handle this type of Intent.
Note that the intent is in the com.google.android.c2dm domain. The Android C2DM implementation on the device knows how to handle this intent and you will be starting its own service to process it.
Related
I have written an Application, which checks when you receive a new SMS and if its from a certain number, the app plays the ringtone. Now, the App should check if there is a new SMS even if it isn´t lauchned, and so my question is: How can I launch my App by receiving a new SMS?
I tryed to upload my existing code but it didn´t worked, I am sorry.
To start an activity from almost everywhere you can simply call:
Intent myIntent = new Intent(CurrentActivity.this, NewActivity.class);
CurrentActivity.this.startActivity(myIntent);
That should also work from your BroadcastReceiver which is triggered while receiving the sms.
Hi i am running a background service using alaram manager its working fine but for some mi devices background service is not working.I used sevices but it is not working how to run my background service in mi ?
MI UI has its own security options, so what you need to is not just above mentioned sticky Service,
you need to
Enable Autostart
go to power setting make changes as per these youtube videos
https://www.youtube.com/watch?v=-Ffgir-QgsU, or refer for this for more suggestions
https://www.quora.com/How-do-I-keep-an-app-running-in-the-background-in-MIUI
then you have created a custom broadcast receiver which will start the service when your service is destroyed
as per this example https://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android
If the 3rd option doesn't work onDestroy recall of the service call the custom broadcast receiver on
w
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.e(TAG, " In recieve Custome Broadcast receiver");
Intent broadcastIntent = new Intent("ac.in.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
}
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.android.settings","com.android.settings.Settings$HighPowerApplicationsActivity"));
startActivity(intent);
try this code
it will open one setting page
then find your app and then tap "Don't Optimize"
it will turn off battery optimization and your background services run without problem
When you start a service by extending an Service class than you will get the call inside OnStartCommand() this method has three types of return type on the basis of this return type operating system itself manage when to start a service.
So suppose if your service gets killed in between due to low memory or any other issue when you return a correct type from onStartCommand() than os will take care of when to start service again.
Three return types are:
START_STICKY : When this is the return type than os takes the guarantee to restart the service again if its get killed it will definitely start you service again even if there is no pending intent it will start the service by passing intent as null.
START_NOT_STICKY: says that, after returning from onStartCreated(), if the process is killed with no remaining start commands to deliver, then the service will be stopped instead of restarted. This makes a lot more sense for services that are intended to only run while executing commands sent to them. For example, a service may be started every 15 minutes from an alarm to poll some network state. If it gets killed while doing that work, it would be best to just let it be stopped and get started the next time the alarm fires.
START_REDELIVER_INTENT is like START_NOT_STICKY, except if the service's process is killed before it calls stopSelf() for a given intent, that intent will be re-delivered to it until it completes (unless after some number of more tries it still can't complete, at which point the system gives up). This is useful for services that are receiving commands of work to do, and want to make sure they do eventually complete the work for each command sent.
I have got following problem.
My application architecture more or less consits of 3 main parts:
Devices view (shows available BLE devices)
BLE service (handles BLE connections and data)
Services view (shows services for particular device)
My issue is with passing BluetoothGATTService to the intent second time (first time it works).
More or less actions are like this:
choose device, for which you want to show services
send intent with device and action to perform to the BLEService
BLEService performs service discovery and sends intent with services back
BroadcastReceiver receives intent properly and wats to start new activity using data in received intent.
And on the last step there is a problem as I cannot put ArrayList to the intent/bundle as it causes exception:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.projects.dawid.gattclient, PID: 4133
java.lang.RuntimeException: Parcel: unable to marshal value android.bluetooth.BluetoothGattService#ef62956
at android.os.Parcel.writeValue(Parcel.java:1337)
at android.os.Parcel.writeList(Parcel.java:711)
at android.os.Parcel.writeValue(Parcel.java:1284)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:638)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1313)
at android.os.Bundle.writeToParcel(Bundle.java:1096)
at android.os.Parcel.writeBundle(Parcel.java:663)
at android.content.Intent.writeToParcel(Intent.java:7838)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2530)
for me it's very very strange, as if the operation is unsupported, then we would get this exception on sending ArrayList of services from BLEService to the BroadcastReceiver, not now.
Source code:
BLEService to Broadcast receiver code
private void notifyServicesDiscovered(BluetoothGatt gatt) {
Intent intent = new Intent();
intent.setAction(BLEService.RESPONSE);
intent.putExtra(BLEService.RESPONSE, BLEService.Responses.SERVICES_DISCOVERED);
intent.putExtra(BLEService.Responses.DEVICE, gatt.getDevice());
intent.putParcelableArrayListExtra(BLEService.Responses.SERVICES_LIST, getArrayListServices(gatt));
LocalBroadcastManager.getInstance(mServiceContext).sendBroadcast(intent);
}
#NonNull
private ArrayList<BluetoothGattService> getArrayListServices(BluetoothGatt gatt) {
ArrayList<BluetoothGattService> services = new ArrayList<>();
services.addAll(gatt.getServices());
return services;
}
This works fine. Now
Broadcast receiver to new activity code
After recognizing the proper intent to handle this method is invoked
private void createViewWithServices(Intent intent) {
Log.i(TAG, "creating new activity!");
BluetoothDevice device = intent.getParcelableExtra(BLEService.Responses.DEVICE);
ArrayList<BluetoothGattService> services = intent.getParcelableArrayListExtra(BLEService.Responses.SERVICES_LIST);
Intent serviceShowIntent = new Intent(mActivityContext, ServiceShowActivity.class);
serviceShowIntent.putExtra(BLEService.Responses.DEVICE, device);
serviceShowIntent.putParcelableArrayListExtra(BLEService.Responses.SERVICES_LIST, services); //this line causes error
mActivityContext.startActivity(serviceShowIntent); // here exception is thrown
}
Can anyone explain me the mistery lying behind this? I just cannot understand why first code is just fine, while second fails with exception.
Already tried doing things in lots of different ways, but all of them failed. I was even exchanging bundles between intents as their contents are same, but this also failed, copying list items makes no difference.
EDIT
refering to the AndroidRuntime error: Parcel: unable to marshal value error. Difference is, that I am using objects of classes provided by android itself, that is BluetoothGATTService, which do implement parcelable interface refering to the https://developer.android.com/reference/android/bluetooth/BluetoothGattService.html
There are two issues in play here: one causes everything to work fine when local broadcasts are used, another one makes serialization of BluetoothGattService fail.
In order to pass data between two processes, it must be serialized (written to Parcel). Bundle contents are serialized/deserialized lazily — as long as Bundle object does not cross process boundaries or get stored on disk, all contained objects will be stored in memory (within a HashMap) and won't get serialized.
Local broadcasts never cross process boundaries, thus do not serialize/deserialize Intent extras. Inter-process communications (global broadcasts, asking ActivityManager to start an Activity) do.
In order to be passed between processes, Intent extras must be either Parcelable or Serializable, otherwise Android may treat them as opaque objects under some circumstances, and will attempt to determine approach to their serialization (as Serializable/Parcelable/String etc.) at runtime (see writeValue) — and fail.
As for BluetoothGattService — it clearly didn't implement Parcelable after initial public release and was retroactively changed to implement Parcelable in API 24. This means, that there are devices in the wild, where that class does not implement Parcelable (even if it does in the source code of the latest Android version). Adding a parent to inheritance chain is not technically a breaking change as far as binary compatibility is concerned — Java Classloaders won't complain. But any code, that relies on parcelability of such class, will either fail during bytecode validation or cause ClassCastException/ArrayStoreException on older versions.
Java generics are not reified — when compiled to binary code, ArrayList<String> and ArrayList<Parcelable> look to ClassLoader the same: as ArrayList<?>. You are not casting BluetoothGattService to Parcelable and neither is ArrayList (internally it stores it's contents in Object[]). In order to serialize ArrayList, HashMap and similar classes, Android have to use reflection, and that fails in your case, because the runtime type of BluetoothGattService does not implement Parcelable on the device. Just add a code, that explicitly makes a cast (such as placing BluetoothGattService in Parcelable[]) and you will see.
Also, even on devices, where it does happen to implement Parcelable prior to API 24, trying to serialize a BluetoothGattService is still bad idea (that wasn't officially public API, wasn't covered by CTS, and thus is completely untested).
I recommend you to refrain from passing BluetoothGattService via parcelization and find other way to approach your task (such as passing it's contents or storing an instance in singlton).
You can send BluetoothGattService through LocalBroadcastReceiver
I have integrated the Zxing API and use this code:
Intent data = new Intent("com.google.zxing.client.android.SCAN");
And getting the result with this code:
String contents = data.getStringExtra("SCAN_RESULT");
String format = data.getStringExtra("SCAN_RESULT_FORMAT");
But when I run this code, the app will ask to force close.
When sending an Intent to startActivity(), you must always check if the user has any apps that can handle the intent:
Caution: It's possible that a user won't have any apps that handle the implicit intent you send to startActivity(). If that happens, the call will fail and your app will crash. To verify that an activity will receive the intent, call resolveActivity() on your Intent object. If the result is non-null, then there is at least one app that can handle the intent and it's safe to call startActivity(). If the result is null, you should not use the intent and, if possible, you should disable the feature that issues the intent.
Go through this. App is crashing because Zxing app is not installed in the mobile. I gave a detailed answer in the same link.
I'd like to enable a "silent send" from my application-- that is, I'd like to catch the SEND intent in a Service, not an Activity. How does the default Android web browser send that intent? Is it possible to handle it in a Service, or in an Activity that never sets a View?
Is it possible to handle it in a
Service, or in an Activity that never
sets a View?
ACTION_SEND Intents are sent as activity intents (e.g., startActivity()), and so you cannot have a Service receive them. You can have them handled by an Activity that never calls setContentView(), though.