Broadcast Receiver issue - java

Ok, so I have an app that needs to receive incoming SMS, and send out an SMS to the sender. This I can set up fine. The problem is, I only want the Broadcast Receiver to receive when the service is started. I declared the receiver class within the service. I destroy the reference (and unregister the receiver) in onDestroy. While the app compiles, and runs, the broadcast receiver never runs. If I delcare it in the manifest, it works fine, but never stops. The receiver just keeps waking up and processing.

You can try to implement this code:
<receiver android:name=".mystuff" android:enabled="false">
on
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(
new ComponentName(context, mystuff.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
off
... PackageManager.COMPONENT_ENABLED_STATE_DISABLED ...

One thing to mention is that you need to declare the Receiver file in your manifest for sure. This actually registers your service with the phone. According to API docs
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active.
So what i have done is i defined my onReceive(Context, Intent) within the Service and register it. Hope this helps.

Related

How can I verify that the onReceive method of a Broadcast Receiver from a different App is actually called?

I'm a beginner with Android and I am confronted with the following problem.
I'm trying to call a Broadcast Receiver registered by App A from (a different) App B.
In App A's Broadcast Receiver I have implemented the following onReceive() method, for testing purposes:
#Override
public void onReceive(Context context, Intent intent) {
//TODO: React to the Intent received.
System.out.println("onReceive has been called");
}
The Boradcast Receiver is called with the following code within App B:
Intent explicitIntent = new Intent();
explicitIntent.setComponent(new ComponentName("<A's package name>", "<fully qualified BR class name>"));
sendBroadcast(explicitIntent);
When running App B, I expected to see the onReceive has been called string appearing on the Android Studio console, but it doesn't.
Is it because the method is in fact not called (for some reason) or because it is naive to expect that App B console can visusalize System.out.println messages from App A?
In the second case, is there another simple way to test in Android Studio that the onReceive() method from App A is actually called?
I do not have your API ver to test with, but your setup will work if you register your receiver a bit differently:
<receiver android:name=".MyBroadcastReceiver" android:exported="true"/>

Check time every minute by broadcast receiver

I want to check the time every minute to make alarm app but when I but this in receiver
<action android:name="android.intent.ACTION_TIME_CHANGED"/>
<action android:name="android.intent.ACTION_TIME_TICK"/>
<action android:name="android.intent.action.TIME_TICK"/>
and put this in broadcast receiver
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context,"changed",Toast.LENGTH_LONG)
.show();
}
My app don't work or do any thing
I searched more and more but nothing was useful I hope someone help me
From the way you wrote <action android:name="android.intent.ACTION_TIME_CHANGED"/>, it appears that you're trying to register your BroadcastReceiver in the Manifest.xml.
However, I'll quote this straight from the documentation:
ACTION_TIME_TICK
Broadcast Action: The current time has changed. Sent every minute. You cannot receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver().
--https://developer.android.com/reference/android/content/Intent.html#ACTION_TIME_TICK
You can only receive this broadcast by registering the BroadcastReceiver through the registerReceiver() method in either something like your Activity or Service.
However, I do want to mention that you should avoid using this broadcast if your intention is to create an Alarm app.
Constantly fetching the time every minute can become quite battery draining, especially if the alarm takes a while to ring.
Instead, you should consider scheduling your alarm through services like JobScheduler or AlarmManager.

BroadcastReceiver onReceive method not called?

I have a service running in which I am getting location updates. The service returns the location successfully. But after that I am trying to broadcast the location to any activity that might be listening. I have registered the receiver in my activity but for some reason the onReceive method is not being called.
Here is the code inside my onLocationChanged method inside my service.
#Override
public void onLocationChanged(Location location) {
Intent intent = new Intent();
intent.setAction("LocationBroadcast");
double lat = location.getLatitude();
double lng = location.getLongitude();
intent.putExtra("lat", lat);
intent.putExtra("lng", lng);
//I am initializing the broadcaster object in onCreate method of my service but I am putting it here for simplicity
broadcaster = LocalBroadcastManager.getInstance(this);
//This Toast successfully shows my coordinates so I know the problem is not with this method
Toast.makeText(GoogleFusedLocationApiService.this, ""+lat+", "+lng+"", Toast.LENGTH_SHORT).show();
broadcaster.sendBroadcast(intent);
}
Inside my activity in my onCreate method, I am registering for the LocationBroadcast like so.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
...
IntentFilter intentFilter = new IntentFilter("LocationBroadcast");
super.registerReceiver(mMessageReceiver, intentFilter);
startService(new Intent(MyApp.getAppContext(), GoogleFusedLocationApiService.class));
}
I've tried this.registerReceiver(mMessageReceiver, intentFilter); and LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, intentFilter); but neither worked.
Here is my mMessageReceiver defined,
public BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
double lat = intent.getDoubleExtra("lat", 0);
double lng = intent.getDoubleExtra("lng", 0);
// This Toast never shows and neither can I debug this method at all
// so for now the only conclusion is the broadcast is not being received
Toast.makeText(MyApp.getAppContext(), "Cordinates are "+lat+", "+lng+"", Toast.LENGTH_SHORT).show();
}
};
Moreover, some of the details that I might think matter after some research. I haven't declared receiver in the manifest because I read that you only do that when you want your application to launch when the broadcast is received but I only want my application to react when it is already running. Not launch whenever the services sends a broadcast.
And I haven't extended the activity to BroadcastReceiver either since the activity is already extended to FragmentActivity
The app does not crash and onLocationChanged is located inside the service that is being started after the BroadcastReceiver is registered so onLocationChanged is not invoked before the BroadcastReceiver has been registered
I managed to solve the issue. I will post my findings and the answer for anyone else faced with this issue in the future. I have probably dumbed down a lot of concepts here but for the purpose of understanding this specific problem I'll try to be accurate to the best of my understanding.
The Answer:
The problem was that I was not sending the Broadcast and receiving the broadcast with the same Context. What I mean by that is, this is how I had declared my service in the Manifest file
<service
android:name=".GoogleFusedLocationApiService"
android:process=":google_fused_location_api_service"/>
The android:process attribute meant that this service would run on a different process from the process that the app is running on. So when I was calling, super.registerReceiver(mMessageReceiver, intentFilter); it was being called from the context of the Activity and when I was calling broadcaster = LocalBroadcastManager.getInstance(this); broadcaster.sendBroadcast(intent); here sendBroadcast is being called from the context of the service which has a different process running for it. So you see I was registering the receiver from a different context and sending broadcast from a different context.
LocalBroadcastManager only works when the broadcast is being sent and received from the same process i.e., context. So in this case, since my service and my app/activity are running or separate processes i.e., contexts I cannot use LocalBroadcastManager. I need to use the Global broadcasts and make sure that I am registering the broadcast and sending the broadcast from the same context.
Now since the I have a static context of the app that I can use anywhere by simply calling, MyApp.getAppContext() which you can learn how to do from this answer now if I register the broadcast receiver and send broadcasts using this context, that means both are done from the same context which is MyApp.getAppContext() and now I begin to receive broadcasts successfully.
So to sum it up, if you have separate process for your service, use MyApp.getAppContext().registerReceiver() and MyApp.getAppContext().sendBroadcast()
If you have the same process for your service or don't have the android:process attribute in your service tag in Manifest file, then you can use LocalBroadcastManager.getInstance(this).registerReceiver() and LocalBroadcastManager.getInstance(this).sendBroadcast().
You can still use MyApp.getAppContext here but using LocalBroadcastManager is the best practice and the proper way of doing things in the second case.

How to run a background service even the app is killed in MI devices

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.

How to queue up data for server dispatch on android

I am working on an android app with an email feature. I want my users to be able to compose and send emails while in airplane mode. For that I need some sort of queue that can check if there is network and send, etc. I image this must have been done 100s of times. But I am not really sure why my searches aren't turning up much. Does anyone know of a library or git project that I can use to accomplish this? If not, does anyone know how to accomplish this?
I believe it is called the Queue and send pattern.
Update
I am starting a bounty on this question. What I hope for is a working example that does not use SMS. For my particular case I am working on an Appengine Connected Android Project. The client needs to send data (String, Bitmap, etc under a particular POJO say Dog) to the server. I want to be able to queue up these data somehow. I can use Gson to save data to file, etc. The bottom line is that I need to be able to check for network. When there is network I dequeue my queue into the server. If there is no network, I keep saving into the queue.
My queue can be Queue<Dog>, where Dog is my class with fields such as Bitmap (or path to image), String, long, etc.
I am looking for a working example. It can be very simple, but the example must work. A git zip would be great. I am giving up close to half of my points for this question.
class Dog{
String dogname;
String pathToImage;
int dogAge;
//etc.
}
//Design pattern for sending Dog to server
0) Unmarshall queue from file using Gson
1) Add dog to queue
2) If there is network, loop through queue and send data to server
3) if there is no network save queue to file
//Ideally, as soon as there is network, the method should be able to detect so and run to send data to server
First you need to set up a receiver to watch the wifi connection to see when they have data, you could also check for normal 3g/4g connections and make a broadcast receiver for that as well. todo this let use implement a broadcast receiver for connection status changes. put something like this in the manifest in the application tag
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
now we need to make the receiver we just defined in the manifest
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//here, check that the network connection is available. If yes, start your email service. If not, stop your email service.
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null) {
if (info.isConnected()) {
//start service
Intent intent = new Intent(this, ItemServiceManager.class);
startService(intent);
}
else {
//stop service
Intent intent = new Intent(this, ItemServiceManager.class);
stopService(intent);
}
}
}
}
What this does is puts a big fat antenna called NetworkChangeReceiver out in android land, that is fine tuned to listen in on when android has something to say about a change in the data connection status.
now you need to build your ItemServiceManager.class which should read from a database (it should also extend Service. It should choose the oldest item in the database, (email it, text it, upload to server, whatever), and if the connection was successful then remove the item from the database, and load the next oldest one. If there is no more then close the service and the broadcast receiver.
If you have a connection and the user needs to send more data, then add it to the database, and then make sure the service is started. Maybe notify it that it should double check the database (after a few seconds) before deciding it can close because nothing is there.
This is how you might disable your broadcast receiver.
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, NetworkChangeReceiver.class);
packageManager.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
When a new item is to be uploaded, if there is no web connection, the email should be saved to the database and the broadcast receiver should be started to know when internet is back so it can know when to upload. You might start it up like this.
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, NetworkChangeReceiver.class);
packageManager.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);
The whole point is you only care about connection broadcasts when you have something stored to be uploaded but can not upload it because of no data connection. When you have nothing to upload, don't waste processing and battery by keeping your receiver/service around. And when you do have emails waiting, then start up you broadcastreceiver, to know when you have data connection so that you can start uploading.
I do not think anyone is going to write a whole working solution for you, hopefully this is more than enough to get you on your way.
Edit:
Another thing you can do, is let the server allow acceptance of an array of your items, that way you can just upload it all at once when you get a valid connection. Generally you would do this if each item was decently small. But if you are uploading pictures or videos or anything large, best to do it one at a time probably.

Categories