Reputation: 390
I am trying to build a simple app that will wait until a new SMS arrives, extract and process the data from it. The application should run in the background. The GUI has a single switch element to start/stop the broadcast receiver. Even if the app is destroyed and the screen is locked, the app should still be working unless the user manually turns it off.
I searched every resource on stackoverflow, and most of them did it this way, yet, it still does not work for me, and I can't seem to know why. I know because Log.d(...)
is not returning anything. Any help would be appreciated.
public class SMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("RECEIVER", "ENTERED");
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
Log.d("RECEIVER", "SMS RECEIVED");
SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
for(int i = 0; i < 4; i++){
SmsMessage sms = messages[i];
Log.d("Message " + i + 1 + " from: ", sms.getOriginatingAddress());
Toast.makeText(context,"SMS from " + sms.getOriginatingAddress(), Toast.LENGTH_SHORT).show();
}
}
}
}
public class MainActivity extends AppCompatActivity {
IntentFilter filter;
SMSReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
receiver = new SMSReceiver();
Switch startSwitch = (Switch) findViewById(R.id.startSwitch);
startSwitch.setChecked(false);
startSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if(isChecked){
getApplication().registerReceiver(new SMSReceiver(), filter);
} else {
getApplication().unregisterReceiver(receiver);
}
}
});
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ahmad.smsforwarder">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
</manifest>
Upvotes: 6
Views: 9894
Reputation: 367
Please use smsRetrieverAPI (message template requires app hash string in the end)or smsUserConsentAPI (message template doesn't require app hash string in the end). These google APIs don't require SMS read permission anymore.
Sms Retriever API https://developers.google.com/identity/sms-retriever/request
Sms User Consent API https://developers.google.com/identity/sms-retriever/user-consent/overview
<receiver android:name=".MySMSBroadcastReceiver" android:exported="true"
android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
</intent-filter>
</receiver>
Upvotes: 0
Reputation: 390
I suffered too long to find out that as of Android 6.0 (API 23), you will have to register permissions in the main activity java class as well. I fixed the problem by adding the following lines to the main activity's class onCreate() Method:
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_SMS},1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS},1);
Upvotes: 7
Reputation: 1194
You have to register your receiver in AndroidManifest.xml with specific intent in intent filter.
<receiver
android:name=".SMSReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Upvotes: 6