Android- SMS_RECEIVED + broadcast in a foreground service crash - android

I have a service that is running in the foreground, inside this service i have a broadcast receiver, that listen to the SMS_RECEIVED action.
When the user is inside the application (both the application and the service are in the foreground) everything works well, and i am receiving the intent.
But when the user exists the application (only the service with the broadcast is in the foreground), the service stops when sms is received.
When the service is stopped no error reports are found anywhere (not in the logcat and no crash dialog pops up).
My service with the broadcast:
public class myService extends IntentService {
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(myService.this, intent.getAction(), Toast.LENGTH_SHORT).show();
}
};
#Override
public void onCreate() {
super.onCreate();
IntentFilter i= new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
i.setPriority(999);
registerReceiver(mReceiver, receiverFilter);
startForeground(...);
}
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
}
And i also have the following permission in my manifest:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
myService is declared like this in the manifest:
<service
android:name=".Services.myService"
android:enabled="true"
android:exported="false" />

I had the same problem and I solved it removing <uses-permission android:name="android.permission.RECEIVE_SMS" />. But removing this permission I can't detect incoming SMS, so I created a class like these Catching Outgoing SMS using ContentObserver and used MESSAGE_TYPE_RECEIVED = 1 instead MESSAGE_TYPE_SENT = 2. You need to add this permission <uses-permission android:name="android.permission.READ_SMS" />.

Related

Broadcast DOWNLOAD_COMPLETE is not recieved if app is not running

Issue: broadcasts android.intent.action.DOWNLOAD_COMPLETE is received only if application is running or in background. If application is killed then broadcast never received.
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
<uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
<receiver
android:name=".adapters.VideoListAdapter$VideoDownloadedReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
Receiver class
public static class VideoDownloadedReceiver extends BroadcastReceiver implements AsyncResponse {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("YES", "in receive");
}
}
Please note the I am facing this issue not in all devices.
Devices on which I am facing this issue: Lenevo A600, Asus Zenfone Max
Device on which it's working fine: Asus Zenfone 5 (cyanogenmod 13), Android Studio Emulator (Nexus 6p marshmallow), Samsung J7 Prime , Samsung j5, Nexus 5
I think the reason may be due to the customization ROM ,limited the broadcast,CM,ASOP,is the originally System.so,,,
if you want to receive broadcast even after app closed then you should use broadcast in service
following will help you to implement:-
https://stackoverflow.com/a/16824692/4246910
The receiver appears to be an internal class. Since the app is destroyed so is your internal receiver class which is part of a destroyed class.
I am basing this assumption because your manifest has
android:name=".adapters.VideoListAdapter$VideoDownloadedReceiver".
Separate the 'BroadcastReceiver' into its own class and it should work as expected.
As for working on some phones, I would check the other apps running and what kind of app suppression apps you may have running in the background which may be contributing to force closing your app.
you should have something like this. i looked at code and you have nested receeiver but you are not holding the service on.
Calling function to start the action
private void startDownloadService() {
Intent downloadIntent = new Intent(this, VideoDownloadReceiverService.class);
if (!VideoDownloadReceiverService.isRunning()) {
// My manifest has enabled="false" so i do this to turn it 'ON'
component = new ComponentName(CounterActivity.this, VideoDownloadReceiverService.class);
getPackageManager()
.setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
// Start the service
startService(downloadIntent);
}
}
in separate file here is the service
public class VideoDownloadReceiverService extends Service{
private static boolean isRunning = false;
public VideoDownloadReceiverService(){
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// you may not need this since oyu register it in the Manifest. the fact the service is running
// should keep your app alive and receiving and unable to be shutdown
// but this is what i did
IntentFilter filter = new IntentFilter();
filter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
receiver = new VideoDownloadReceiver();
registerReceiver(receiver, filter);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText("Viewer Text In Notification").build();
startForeground(MyConstants.NOTIFICATION_ID, notification);
isRunning = true;
return START_STICKY; // This is the line that keeps the service running no matter what
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy(){
unregisterReceiver(receiver);
super.onDestroy();
}
}
In separate file, here is the receiver
public class VideoDownloadReceiver extends BroadcastReceiver {
public VideoDownloadReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"com.example.johnbravado.zionwork");
wakeLock.acquire();
Toast.makeText(context, "in service", Toast.LENGTH_SHORT).show();
Log.i("YES", "service on receive");
wakeLock.release();
}
}

BroadcastReceiver in service doesn't react

I am writing an app which receives SMS data message, encrypt its content and save it to database. To realize it I've created a service with a local BroadcastReceiver as follow:
public class SMMReceiverService extends Service {
private class SMMreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extras = intent.getExtras();
//call a method from service
}
}
private SMMreceiver smmReceiver;
private IntentFilter intentFilter;
#Override
public void onCreate(){
super.onCreate();
android.os.Debug.waitForDebugger();
smmReceiver = new SMMreceiver();
intentFilter = new IntentFilter();
intentFilter.addAction("android.provider.Telephony.DATA_SMS_RECEIVED");
intentFilter.addDataScheme("sms");
intentFilter.addDataAuthority("localhost","8901");
registerReceiver(smmReceiver, intentFilter);
}
}
Service is starting normally but onReceive method of SMMreceiver is never called. In manifest I've declared only my service as follow:
<service
android:name=".Services.SMMReceiverService"
android:enabled="true"
android:exported="true" >
</service>
There are also all required permissions:
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
How to solve my problem in correct way? I will be grateful for your help!
Well, it seems like you kind of answered your own question.
"Service is starting normally but onReceive method of SMMreceiver is never called. In manifest I've declared only my service as follow:"
you have to also declare your receiver in your manifest, did you do that?

How custom permissions are used to restrict sending and receiving the broadcasts within a single app?

I am learning from "Learning Android" - Oreilly - Marko Gargenta.
I am at chapter 11 (Broadcast Receivers)
I followed the book and everything work OK. But I have a question about how custom permissions are used to restrict sending and receiving the broadcasts within a single app.
The book is clear about this topic. but I feel there is something missing.
How do the receiver and the sender tell each other about different permissions?
In AndroidManifest.xml file:
<permission
android:name="saleh.yamba.SEND_TIMELINE_NOTIFICATIONS"
android:description="#string/send_timeline_notifications_permission_description"
android:label="#string/send_timeline_notifications_permission_label"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="normal" />
<permission
android:name="saleh.yamba.RECEIVE_TIMELINE_NOTIFICATIONS"
android:description="#string/receive_timeline_notifications_permission_description"
android:label="#string/receive_timeline_notifications_permission_label"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="normal" />
<uses-permission android:name="saleh.yamba.SEND_TIMELINE_NOTIFICATIONS" />
<uses-permission android:name="saleh.yamba.RECEIVE_TIMELINE_NOTIFICATIONS" />
In the Service that send broadcasts:
Intent intent = new Intent("saleh.yamba.NEW_STATUS");
updaterService.sendBroadcast(intent, "saleh.yamba.RECEIVE_TIMELINE_NOTIFICATIONS");
Here, sender sends intent with saleh.yamba.RECEIVE_TIMELINE_NOTIFICATIONS permission, Ok, How does the receiver know about this permission?
In the Activity that receives the broadcast via BroadcastReceiver:
TimelineReceiver receiver;
IntentFilter filter;
protected void onCreate(Bundle savedInstanceState)
{
receiver = new TimelineReceiver();
filter = new IntentFilter("saleh.yamba.NEW_STATUS");
}
protected void onResume()
{
this.registerReceiver(receiver, filter, "saleh.yamba.SEND_TIMELINE_NOTIFICATIONS", null);
}
protected void onPause()
{
this.unregisterReceiver(receiver);
}
private class TimelineReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//do something.
}
}
Here receiver receives it with another permission. OK,
How does the receiver know about saleh.yamba.RECEIVE_TIMELINE_NOTIFICATIONS.
There is nothing in the code of the receiver part that tells that the BroadcastReceiver will be invoked only if the receiver has saleh.yamba.RECEIVE_TIMELINE_NOTIFICATIONSpermission.
There is nothing in the code of the receiver part that tells that the BroadcastReceiver will be invoked only if the sender has saleh.yamba.RECEIVE_TIMELINE_NOTIFICATIONSpermission.
Yes, there is. You passed in saleh.yamba.RECEIVE_TIMELINE_NOTIFICATIONS to registerReceiver().
Specifically, you are using the four-parameter version of registerReceiver(), where the third parameter is a "String naming a permissions that a broadcaster must hold in order to send an Intent to you. If null, no permission is required."

restart force stopped app on receiving sms

I am trying to restart my app on receiving sms if it is force stopped. This is my code.
Its not restarting the app.Should I try writing receiver as another class.
In manifest :
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<receiver android:name=".MySMSbr">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
My mainActivity onCreate() :
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
BroadcastReceiver SMSbr;
public void onCreate(Bundle savedInstanceState) {
Toast.makeText(getApplicationContext(),"in OnCreate", Toast.LENGTH_LONG).show();
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SMSbr = new BroadcastReceiver()
{
#Override
public void onReceive(Context context,Intent intent)
{
this.abortBroadcast();
Toast.makeText(context, "in onReceive", Toast.LENGTH_LONG).show();
toggleLogging(AppSettings.getServiceRunning(MainActivity.this),
AppSettings.getLoggingInterval(MainActivity.this));
this.clearAbortBroadcast();
}//end of onReceive method
};//end of BroadcastReceiver
IntentFilter SMSfilter = new IntentFilter(SMS_RECEIVED);
this.registerReceiver(SMSbr, SMSfilter);
}
in togglelogging the service is started
where is it going wrong.
You are declaring a BroadcastReceiver in your manifest - i.e, static receiver but in fact you do not have such a class and you are creating a dynamic receiver in your activity.
What you are actually doing is registering your receiver when your activity starts, but you want the other way around (start your activity/app once the receiver receives a broadcast).
You need to create a class which is called SMSbr extends BroadcastReceiver and there you can perform your logics.
That way you will have the receiver always registered and when an SMS broadcast will be received it will wake your app.

Broadcast Receiver within a Service

I am trying to start up a BroadcastReceiver within a Service. What I am trying to do is have a background running service going that collects incoming text messages, and logs incoming phone calls. I figured the best way to go about this is to have a service running that incorporates a broadcast receiver that can catalog either.
How do i go about doing this? I already have my service up and running.
as your service is already setup, simply add a broadcast receiver in your service:
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals("android.provider.Telephony.SMS_RECEIVED")){
//action for sms received
}
else if(action.equals(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED)){
//action for phone state changed
}
}
};
in your service's onCreate do this:
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
filter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);
filter.addAction("your_action_strings"); //further more
filter.addAction("your_action_strings"); //further more
registerReceiver(receiver, filter);
and in your service's onDestroy:
unregisterReceiver(receiver);
and you are good to go to receive broadcast for what ever filters you mention in onCreate. Make sure to add any permission if required. for e.g.
<uses-permission android:name="android.permission.RECEIVE_SMS" />
The better pattern is to create a standalone BroadcastReceiver. This insures that your app can respond to the broadcast, whether or not the Service is running. In fact, using this pattern may remove the need for a constant-running Service altogether.
Register the BroadcastReceiver in your Manifest, and create a separate class/file for it.
Eg:
<receiver android:name=".FooReceiver" >
<intent-filter >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
When the receiver runs, you simply pass an Intent (Bundle) to the Service, and respond to it in onStartCommand().
Eg:
public class FooReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// do your work quickly!
// then call context.startService();
}
}

Categories

Resources