Android - Broadcast Receiver not being fired - java

I know this has been asked ALOT on here, but I have been scouring the interwebs for hours and I have even reused some of my previous code for receiving sms' and I got...nothing.
So, here goes, basic app to receive SMS but the app never receives the intent. I thought the intent may be ignored if the text is sent from the same phone but that does not seem to be the case, as other apps pick up the text fine.
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.encima.smsreceiver"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".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=".MessageReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
</manifest>
And, here is the receiver, nothing seems to be new here, so I have no idea what the problem is:
package com.encima.smsreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class MessageReceiver extends BroadcastReceiver {
private static final String TAG = "Message recieved";
#Override
public void onReceive(Context context, Intent intent) {
Bundle pudsBundle = intent.getExtras();
Object[] pdus = (Object[]) pudsBundle.get("pdus");
SmsMessage messages =SmsMessage.createFromPdu((byte[]) pdus[0]);
Log.i(TAG, messages.getMessageBody());
Toast.makeText(context, "SMS Received : "+messages.getMessageBody(),
Toast.LENGTH_LONG).show();
}
}
The debug phone I am using is running 2.2.2 and I have other apps running that detect sms, including some of my own.
Any insight into this would be appreciated!
Thanks

Because the SMS broadcast intent is sent by
Context.sendOrderedBroadcast(...),
if any other app registers the BroadcastReceiver and calls abortBroadcast, the other receiver will not get the broadcast.
To increase the probability of your app receiving the broadcast create an IntentFilter, use IntentFilter.setPriority.

I do not know if this is your problem but you should definitelly try this:
Instead of ".MessageReceiver" put android:name = "com.encima.smsreceiver.MessageReceiver"
This is fix that workout many times for me when something doesn't get called.

Related

App for setting up a certain series of alarms is only working in the Android Studio Emulator

My final goal is to easily activate and deactivate a certain series of 17 alarms in the clock app whenever necessary. Unfortunately, the app only offers the option to either deleting(!) all alarms at once or deactivating one by one. The same applies to every other app from the Play Store I have tried.
I think an acceptable workaround solution would be to delete all alarms with the mentioned functionality and re-implement the series of alarms programmatically as needed. So, I wrote a minimalist app in Android Studio that works perfectly fine in the emulator.
After building the debug APK, I transferred it on my smartphone and installed it without any errors. Now I am facing the problem that after starting my app only the first alarm is created. Does somebody have an explanation for this error. Thank you!
MainActivity.java
package com.example.setalarms;
import android.app.Activity;
import android.content.Intent;
import android.provider.AlarmClock;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.Arrays;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] messages = {"alarm1","alarm2to16","alarm17"};
int[] hours = {7,8,9};
int[] minutes = {0,0,0};
ArrayList<Integer> days = new ArrayList<>(
Arrays.asList(1,2,3,4,5,6,7)
);
Intent[] intents = new Intent[messages.length];
for (int i = 0; i < messages.length; i++) {
Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM)
.putExtra(AlarmClock.EXTRA_MESSAGE, messages[i])
.putExtra(AlarmClock.EXTRA_HOUR, hours[i])
.putExtra(AlarmClock.EXTRA_MINUTES, minutes[i])
.putExtra(AlarmClock.EXTRA_DAYS, days)
.putExtra(AlarmClock.EXTRA_SKIP_UI, i != messages.length - 1);
intents[i] = intent;
}
startActivities(intents);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.SetAlarms"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
Hardware / Software
SAMSUNG Galaxy A3 (2017) SM-A320FL
Android Studio Dolphin 2021.3.1 Patch 1
Android 8.0.0 (Oreo)
Clock 7.0.92.7 (Galaxy Store)

Permission Denial With Broadcast Receiver

I am trying to create an app which enters a log message when I make an outgoing call.
However, when I run the code, I get a permission denial, despite the fact that I have entered in the permissions.
Denial Log:
"09-04 02:35:50.535 1294-1666/? W/BroadcastQueue﹕ Permission Denial: receiving Intent { act=android.intent.action.NEW_OUTGOING_CALL flg=0x10000010 (has extras) } to samples.varma.packagecom.testreceive2/.CallReceiver requires android.permission.PROCESS_OUTGOING_CALLS due to sender android (uid 1000)"
Manifest Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="samples.varma.packagecom.testreceive2" >
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:enabled="true"
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=".CallReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
</application>
</manifest>
And here is the code for my receiver:
package samples.varma.packagecom.testreceive2;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
public class CallReceiver extends BroadcastReceiver {
public CallReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state == null) {
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i("TAG", "Outgoing Number: " + number);
} else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i("TAG", "Incoming Number: " + number);
}
}
}
I am very new to this so there is a good chance that there are several errors or I am completely off base. Regardless I would greatly appreciate any guidance. Would anyone know why I am getting this denial?
Thanks
Edit:
It is also giving me these permission denials even though I have added the phone state permission.
The privileged phone-state permission is a system permission so I cannot add.
09-04 04:36:03.249 1294-1440/? W/BroadcastQueue﹕ Permission Denial: receiving Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } to samples.varma.packagecom.testreceive2/.CallReceiver requires android.permission.READ_PRIVILEGED_PHONE_STATE due to sender android (uid 1000)
09-04 04:36:03.271 1294-1308/? W/BroadcastQueue﹕ Permission Denial: receiving Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } to samples.varma.packagecom.testreceive2/.CallReceiver requires android.permission.READ_PHONE_STATE due to sender android (uid 1000)
1294-1308/? W/BroadcastQueue﹕ Permission Denial: receiving Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } to samples.varma.packagecom.testreceive2/.CallReceiver requires android.permission.READ_PHONE_STATE due to sender android (uid 1000)
I have launched the same application on Android emulator and nothing helped, even
android:enabled="true"
android:exported="true"
The solution was to go to Settings->Apps -> MyApplication -> Permissions -> Toggle Phone Permission on.
Android Phone Permission for Application
I got it to work by following this link closely Intercepting outgoing call - what am I missing? (thanks ajit)
I ended up taking off the PHONE_STATE permission, adding android:enabled="true" and android:exported="true" to my receiver in the manifest, relocating the NEW_OUTGOING_CALL permission to below application(not sure if this is necessary), taking away the intended sdk versions and basically copying the receiver from the link.
Updated manifest code from receiver tag to manifest tag is:
<receiver
android:name=".testreceive3"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>-->
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />>-->
</manifest>
U need to apply the runtime permission int your code when your code running on Android 6.0 or above.
You should add the following thing in your Manifest receiver
<service android:name=".CallReceiver"
android:enabled="true"
android:exported="false" >
</service>
Use permission CALL_PHONE instead of OUTGOING
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Best solution is when you run the code activate usb debugging, make sure you select disable permissions monitor settings in developer settings ! App wont be asked for permissions by the OS anymore. Happy helping :)
This will work without changing anything in manifest!

Pushes not received after the app is closed

Before labeling this as a duplicate:
I've read at least 15 similar threads and each and every one is either using the old Parse code (the now deprecated setDefaultPushCallback) or the problem was a result of calling Parse.initialize(...) in an activity and not in the Application class. But this is not applicable to my case. The official example (which I'm using) is evidently doing it right, so the code is already in the Application class.
I've downloaded the Push Starter example from Parse's official guides and tried it out on an emulator. I receive pushes only while the app is running. The moment's it's closed (removed from the "recent apps" list, not force killed), I no longer get pushes. Which makes the entire feature rather useless... I tried with and without GCM, the behavior is the same.
Any clues what could possible be wrong? All classes are the stock example ones, nothing overridden or added by me (except for the id/key and the ParsePush.subscribeInBackground call which I copied from the guide). Weirdly enough, the example code did not contain ParsePush.subscribeInBackground and the QuickStart does not mention it. It even gives a Test button that supposedly sends a push which I never receive, with or without subscribeInBackground. The only way I've been able to get a push so far was with subscribeInBackground and sending a push manually though the web console, and only so if the app is running. The web console also keeps telling there's 2 registered devices... which is untrue.
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.parse.starter"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="21"/>
<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.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!--
IMPORTANT: Change "com.parse.starter.permission.C2D_MESSAGE" in the lines below
to match your app's package name + ".permission.C2D_MESSAGE".
-->
<permission android:protectionLevel="signature"
android:name="com.parse.starter.permission.C2D_MESSAGE" />
<uses-permission android:name="com.parse.starter.permission.C2D_MESSAGE" />
<application
android:name=".ParseApplication"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:allowBackup="true">
<activity
android:name=".ParseStarterProjectActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<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.parse.starter" />
</intent-filter>
</receiver>
</application>
</manifest>
ParseApplication:
package com.parse.starter;
...
public class ParseApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
// Initialize Crash Reporting.
ParseCrashReporting.enable(this);
// Enable Local Datastore.
Parse.enableLocalDatastore(this);
ParseUser.enableAutomaticUser();
// Add your initialization code here
Parse.initialize(this, "***", "***");
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access.
// defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
ParsePush.subscribeInBackground("", new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
} else {
Log.e("com.parse.push", "failed to subscribe for push", e);
}
}
});
}
}
Just to clarify why you are seeing this behaviour, Parse has two different ways for delivering push notifications:
"Parse way": the Parse SDK has a component running in your app, which keeps a connection to the Parse backend servers. This will only work when your app is actually running, because killing it breaks the connection with the Parse backend.
GCM "Google" push notifications: This works via Google Play Services, an app which is always running in the background and that can start your app when needed. This will always work, unless you force stop the application.
In your case you are there is a package name conflict: com.parse.starter is the package name that was actually included in the example. This causes GCM not to work, because it already knows the package under a different signature. Changing your package name to something unique like com.parse.kaqqao should solve the trick.
There are a few reasons for this:
There are two BroadcastReceiver viz the "com.parse.ParsePushBroadcastReceiver" and "com.parse.GcmBroadcastReceiver". I believe that the first receiver is getting prioritized over the GCMBroadcastReceiver and thus the behavior is not affected by removing or keeping this receiver. It could also be due to action "com.parse.push.intent.RECEIVE", which might be handling the push messages RECEIVE action. If both the receiver perform the same task of parsing the Push message (starting the same service in background), then include the intent-filter inside one receiver and let it handle all kinds of push messages. Since GCMBroadcastReceiver holds the C2DM permission.
Try changing the order of the two broadcast receiver tags in the manifest. (Keep GCMBroadcastReceiver before the ParsePushBroadcastReceiver)
It could be due to android:exported="false", maybe it prevents the Receiver from listening to the push messages sent by server. Try changing to true.

No activity found to handle custom intent

Using a customer defined activity and i've declared the intent action in the manifest.xml
Here's the manifest file with the error
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="course.labs.dangerousapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="13"
android:targetSdkVersion="18" />
<!--
TODO - Using a permission element,
define a custom permission with name
"course.labs.permissions.DANGEROUS_ACTIVITY_PERM"
and "dangerous" protection level.
-->
<permission
android:name="course.labs.permissions.DANGEROUS_ACTIVITY_PERM"
android:protectionLevel="dangerous"
>
</permission>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<!-- TODO - enforce the custom permission on this Activity -->
<activity
android:permission="course.labs.permissions.DANGEROUS_ACTIVITY_PERM"
android:name=".DangerousActivity"
android:label="#string/app_name" >
<!--
TODO - add additional intent filter info so that this Activity
will respond to an Implicit Intent with the action
"course.labs.permissions.DANGEROUS_ACTIVITY"
-->
<intent-filter >
<category android:name="android.intent.category.DEFAULT" />
<action android:name="course.labs.permissions.DANGEROUS_ACTIVITY" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Here's where the intent was invoked in the program
Code:
package course.labs.permissionslab;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class GoToDangerousActivity extends Activity {
private static final String TAG = "Lab-Permissions";
private static final String DANGEROUS_ACTIVITY_ACTION = "course.labs.permissions.DANGEROUS_ACTIVITY";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.go_to_dangerous_activity);
Button startDangerousActivityButton = (Button) findViewById(R.id.start_dangerous_activity_button);
startDangerousActivityButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startDangerousActivity();
}
});
}
private void startDangerousActivity() {
Log.i(TAG, "Entered startDangerousActivity()");
startActivity(new Intent(DANGEROUS_ACTIVITY_ACTION));
}
}
Please let me know if any other info will hell, I've been tried everything i know and not sure why i'm getting this error again.
Did you installed the first App that has the manifest before calling using the second App?
[EDIT]
To check if a activity is registered to some Intent, you can use adb.exe available on Platform-tools folder to list all intents configured on the device.
To do that, on prompt execute the command below:
adb shell dumpsys package > packages.txt
Then open packages.txt and find for action name course.labs.permissions.DANGEROUS_ACTIVITY. Should have a activity associate with that action.
Try so:
startActivity(new Intent(getApplicationContext(), DANGEROUS_ACTIVITY_ACTION.class));
This is the normail way of doing it
[EDIT]
OR (note the different declaration of DANGEROUS_ACTIVITY_ACTION)
private static final String DANGEROUS_ACTIVITY_ACTION = ".DangerousActivity";
// ...
startActivity(new Intent(DANGEROUS_ACTIVITY_ACTION));
I use this in a SplashScreen Activity to call the Main Activity (after done loading my graphics from SVG files).
You need to run "DangerousApp" before running "GoToDangerousActivity".
This is because your dangerous app is not even installed on the device. If you were trying to do this from android studio, by default studio would try to launch the app which won't be successful because of the permission it needs. To install your dangerours, modify studio's launch settings to not to run the app right away. I got the same issue.

Go back to launcher android programmatically

I use the following code to set my app as the default program. Press the home key to go to my app...
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
It also boots with DISABLE_KEYGUARD directly into my app, without needing to unlock the phone.
How can I change back to the default launcher programmatically? Meaning, how can I go back to android home screen?
I tried using System.exit(0) however it doesn't work - it just goes back to my app instead of the android home screen.
The following is my code.
It goes back to my APP automatically.
Please tell any problem in the code.
TesthomeActivity.java
public class TesthomeActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button)findViewById(R.id.button1);
btn.setOnTouchListener(exitappTouchListener);
}
OnTouchListener exitappTouchListener= new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent arg1) {
// TODO Auto-generated method stub
if(arg1.getAction() == MotionEvent.ACTION_DOWN){
}
if(arg1.getAction() == MotionEvent.ACTION_UP ){
Intent i = new Intent();
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
TesthomeActivity.this.startActivity(i);
finish();
System.exit(0);
}
return false;
}
};
}
StartupReceiver.java
public class StartupReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent)
{
Intent activityIntent = new Intent(context, TesthomeActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activityIntent);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.inno.testhome"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<application android:icon="#drawable/icon" android:label="#string/app_name" android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen">
<activity android:name=".TesthomeActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</activity>
<receiver android:name="StartupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
read this Is quitting an application frowned upon?
or use this
Intent i = new Intent();
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
yourActivity.this.startActivity(i);
finish();
I think this will help you
If your app is set as the default launcher, the Android system will automatically restart your app whenever it quits. It no longer has any concept of the original home screen - as far as the operating system is concerned, your app is the home screen now.
This is why you are unable to get back to the default launcher by quitting your app.
The only way to achieve the result you want is to change the default launcher.
You need to query the PackageManager for the apps that respond to the Home intent.
You can then launch the correct one as you would start any other activity. Be sure to remove your app from the list before processing...
For useful info on that, I suggest #Commonsware's Launchalot sample app, which shows how to enumerate a list of apps that respond to a certain intent.
Check his code on github here.

Categories