I am trying to read incoming message using receiver.I followed tutorial and added below code but broadcast receiver is not getting fired.Log placed inside onReceive never gets fired.
Manifest
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application
android:name=".xyz"
android:allowBackup="true"
android:icon="#mipmap/icon_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<receiver android:name="xyz.receiver.SmsReceiver">
<intent-filter android:priority="1">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
BroadcastReceiver
public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
#Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getExtras();
Log.e("TEST",data.toString());
Object[] pdus = (Object[]) data.get("pdus");
for(int i=0;i<pdus.length;i++){
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = smsMessage.getDisplayOriginatingAddress();
String messageBody = smsMessage.getMessageBody();
mListener.messageReceived(messageBody);
}
}
public static void bindListener(SmsListener listener) {
mListener = listener;
}
}
Activity
SmsReceiver.bindListener(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Toast.makeText(OTPActivity.this, "Message: " + messageText, Toast.LENGTH_LONG).show();
}
});
I have used this code, hope this works for you too :)
private BroadcastReceiver mSMSReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
try {
Log.e("sms receiver", "0000sdfghjkjhgfdsdfghjk");
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
String sms;
for (Object pdu : pdus) {
SmsMessage tmp;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
tmp = SmsMessage.createFromPdu((byte[]) pdu, bundle.getString("format"));
} else {
tmp = SmsMessage.createFromPdu((byte[]) pdu);
}
String senderMobile = tmp.getMessageBody();
sms = tmp.getMessageBody();
if (senderMobile.startsWith("کد فعالسازی شما در توپ 360:")) {
Log.e("sms receiver", "1111sdfghjkjhgfdsdfghjk");
final String mSMS = sms.replaceAll("[^0-9]", "");
//TODO Check SMS Center number with senderMobile if(senderMobile.equals(989100000)){...}
if (mSMS.length() == 5 || mSMS.length() == 6) {
Log.e("sms receiver", "2222sdfghjkjhgfdsdfghjk");
runOnUiThread(new Runnable() {
#Override
public void run() {
//CODE IS mSMS
code.setText(mSMS);
Log.e("sms receiver", "3333sdfghjkjhgfdsdfghjk");
}
});
abortBroadcast();
break;
}
}
}
}
}
} catch (Exception e) {
Log.e("sms exception", e.getMessage());
}
}
};
#Override
public void onResume() {
super.onResume();
if (isGranted) {
IntentFilter mIntentFilter = new IntentFilter();
Log.e("sms receiver", "4444sdfghjkjhgfdsdfghjk");
mIntentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
mIntentFilter.setPriority(Integer.MAX_VALUE);
registerReceiver(mSMSReceiver, mIntentFilter);
} else {
Log.e("sms receiver", "5555sdfghjkjhgfdsdfghjk");
}
}
#Override
public void onPause() {
super.onPause();
if (isRegistered) {
unregisterReceiver(mSMSReceiver);
Log.e("sms receiver", "6666sdfghjkjhgfdsdfghjk");
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 100: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
isGranted = true;
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
mIntentFilter.setPriority(Integer.MAX_VALUE);
registerReceiver(mSMSReceiver, mIntentFilter);
Log.e("sms receiver", "7777sdfghjkjhgfdsdfghjk");
isRegistered = true;
onResume();
} else {
isGranted = false;
Snackbar snackbar = Snackbar.make(coordinatorLayout, "دریافت کننده خودکار پیامک غیرفعال است.", Snackbar.LENGTH_LONG);
snackbar.show();
}
return;
}
}
}
Related
I am using SMS Retriever API to get OTP but the problem I am facing is that it is not receiving SMS every time. Sometime SMS content is retrieved and some time nothing happens.
I have used the Toast (Broadcaster started) to show if it is started every time but Toast is also not displayed every time. I am unable to diagnose the problem.
Broadcast Receiver code:
public class OTPBroadcastReceiver extends BroadcastReceiver {
private String otp;
private static OTPSMSReceiveListner otpsmsReceiveListner = null;
private final Pattern p = Pattern.compile("(|^)\\d{4}");
public static void injectListner(OTPSMSReceiveListner listner){
otpsmsReceiveListner = listner;
}
#Override
public void onReceive(Context context, Intent intent) {
try {
Toast.makeText(context,"Broadcaster started",Toast.LENGTH_LONG).show();
if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
Bundle extras = intent.getExtras();
Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);
switch (status.getStatusCode()) {
case CommonStatusCodes.SUCCESS:
//Toast.makeText(context,"success",Toast.LENGTH_LONG).show();
// Get SMS message contents
String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
if (message != null) {
Matcher m = p.matcher(message);
if (m.find()) {
otp = m.group(0);
}
String token;
try {
token = CommonMethods.getSecurePref("OTP", context);
} catch (Exception ex) {
token = null;
}
if (token == null) {
//Pass on the text to our listener.
otpsmsReceiveListner.onOTPReceived(otp);
}
}
break;
case CommonStatusCodes.TIMEOUT:
Log.d("onReceive", "timed out (5 minutes)");
//Toast.makeText(context,"Timeout",Toast.LENGTH_LONG).show();
otpsmsReceiveListner.onOTPTimeout();
break;
}
}
}
catch (Exception ex){
Toast.makeText(context,ex.getLocalizedMessage(),Toast.LENGTH_LONG).show();
}
}
public interface OTPSMSReceiveListner{
void onOTPReceived(String otp);
void onOTPTimeout();
}
}
OTP class:
SmsRetrieverClient client = SmsRetriever.getClient(mContext);
Task<Void> task = client.startSmsRetriever();
task.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
try
{
Log.e("onSuccess","Successfully started retriever");
}
catch (Exception ex)
{
Log.e("onSuccess",ex.getMessage());
}
}
});
task.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e("onFailure", "Failed to start retriever");
}
});
OTPBroadcastReceiver.injectListner(new OTPBroadcastReceiver.OTPSMSReceiveListner() {
#Override
public void onOTPReceived(String otp) {
if(otp.length() == 4) {
otpField.setText(otp);
btnVerify.performClick();
}
}
#Override
public void onOTPTimeout() {
Log.e("onOTPTimeout","onOTPTimeout");
}
});
Manifest:
<receiver
android:name=".helpers.OTPBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" />
</intent-filter>
</receiver>
SMS:
<#> your App OTP is:8149 585dyDy8cbh
See this answer https://stackoverflow.com/a/55374780/10449332. Please register the BroadcastReceiver inside SmsRetriever addOnSuccessListener callback.
I am developing an Android application, where I have asked to implement the call record ,I have gone through SO and found One Solution which is working fine when my app is opened. If I close my app or clear it from recent apps, Call record is not working. Tried searching in the Google and SO but no luck. I am posting my code here, Can some one help me in getting the solution.
CallreCorder Service class:
public class TService extends Service {
MediaRecorder recorder;
File audiofile;
String name, phonenumber;
String audio_format;
public String Audio_Type;
int audioSource;
Context context;
private Handler handler;
Timer timer;
Boolean offHook = false, ringing = false;
Toast toast;
Boolean isOffHook = false;
private boolean recordstarted = false;
private static final String ACTION_IN = "android.intent.action.PHONE_STATE";
private static final String ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL";
private CallBr br_call;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
Log.d("service", "destroy");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// final String terminate =(String)
// intent.getExtras().get("terminate");//
// intent.getStringExtra("terminate");
// Log.d("TAG", "service started");
//
// TelephonyManager telephony = (TelephonyManager)
// getSystemService(Context.TELEPHONY_SERVICE); // TelephonyManager
// // object
// CustomPhoneStateListener customPhoneListener = new
// CustomPhoneStateListener();
// telephony.listen(customPhoneListener,
// PhoneStateListener.LISTEN_CALL_STATE);
// context = getApplicationContext();
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_OUT);
filter.addAction(ACTION_IN);
this.br_call = new CallBr();
this.registerReceiver(this.br_call, filter);
// if(terminate != null) {
// stopSelf();
// }
return START_NOT_STICKY;
}
public class CallBr extends BroadcastReceiver {
Bundle bundle;
String state;
String inCall, outCall;
public boolean wasRinging = false;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_IN)) {
if ((bundle = intent.getExtras()) != null) {
state = bundle.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
wasRinging = true;
Toast.makeText(context, "IN : " + inCall, Toast.LENGTH_LONG).show();
} else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
if (wasRinging == true) {
Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();
String out = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss").format(new Date());
File sampleDir = new File(Environment.getExternalStorageDirectory(), "/TestRecordingDasa");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
Log.d("TService", "onReceive: "+sampleDir);
String file_name = "Outgoing";
try {
audiofile = File.createTempFile(file_name, ".wav", sampleDir);
} catch (IOException e) {
e.printStackTrace();
}
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
recorder = new MediaRecorder();
// recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
// recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
recorder.setOutputFile(audiofile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
recordstarted = true;
}
} else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
wasRinging = false;
Toast.makeText(context, "REJECT || DISCO", Toast.LENGTH_LONG).show();
if (recordstarted) {
recorder.stop();
recordstarted = false;
}
}
}
} else if (intent.getAction().equals(ACTION_OUT)) {
if ((bundle = intent.getExtras()) != null) {
outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show();
File sampleDir = new File(Environment.getExternalStorageDirectory(), "/TestRecordingDasa");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
Log.d("TService", "onReceive: "+sampleDir);
String file_name = "Record";
try {
audiofile = File.createTempFile(file_name, ".wav", sampleDir);
} catch (IOException e) {
e.printStackTrace();
}
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
recorder = new MediaRecorder();
// recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
// recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
recorder.setOutputFile(audiofile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
recordstarted = true;
}
}
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("callRecord"));
}
}
}
Receiver class:
public class DeviceAdminDemo extends DeviceAdminReceiver {
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
public void onEnabled(Context context, Intent intent) {
};
public void onDisabled(Context context, Intent intent) {
};
}
MainActivity Class
public class MainActivity extends Activity {
private static final int REQUEST_CODE = 0;
private DevicePolicyManager mDPM;
private ComponentName mAdminName;
private static final int PERMISSION_REQUEST_CODE= 123;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (checkPermission()){
Toast.makeText(this, "Permission granted", Toast.LENGTH_SHORT).show();
}else{
requestPermission();
}
try {
// Initiate DevicePolicyManager.
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mAdminName = new ComponentName(this, DeviceAdminDemo.class);
if (!mDPM.isAdminActive(mAdminName)) {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "Click on Activate button to secure your application.");
startActivityForResult(intent, REQUEST_CODE);
} else {
// mDPM.lockNow();
// Intent intent = new Intent(MainActivity.this,
// TrackDeviceService.class);
// startService(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
LocalBroadcastManager.getInstance(MainActivity.this).registerReceiver(receiver, new IntentFilter("callRecord"));
Intent intent = new Intent(MainActivity.this, TService.class);
startService(intent);
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase("callRecord")) {
Toast.makeText(MainActivity.this, "Call record", Toast.LENGTH_SHORT).show();
}
}
};
private boolean checkPermission(){
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
return true;
}else{
return false;
}
}
private void requestPermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.ACCESS_COARSE_LOCATION)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.CALL_PHONE)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.SEND_SMS)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.READ_CONTACTS)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.READ_PHONE_STATE)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.PROCESS_OUTGOING_CALLS)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.RECORD_AUDIO)
|| ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CAPTURE_AUDIO_OUTPUT)){
Toast.makeText(MainActivity.this,"Allow Us pemissions. Please allow in App Settings for additional functionality.",Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.CALL_PHONE, Manifest.permission.SEND_SMS, Manifest.permission.READ_CONTACTS,
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE,
Manifest.permission.PROCESS_OUTGOING_CALLS, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAPTURE_AUDIO_OUTPUT}, PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission Granted, ", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Permission not Granted", Toast.LENGTH_SHORT).show();
}
break;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (REQUEST_CODE == requestCode) {
Intent intent = new Intent(MainActivity.this, TService.class);
startService(intent);
}
}
#Override
public void onResume() {
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter("callRecord"));
super.onResume();
}
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
}
Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.practice.callrecorder">
<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
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>
<receiver
android:name=".DeviceAdminDemo"
android:description="#string/app_name"
android:label="#string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/my_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
<action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />
<action android:name="android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED" />
</intent-filter>
</receiver>
<service
android:name=".TService"
android:enabled="true"
android:exported="true">
</service>
</application>
my_admin.xml
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" >
<uses-policies>
<force-lock />
</uses-policies>
any help would be grateful!!!
Thanks in advance!!
use START_STICKY as return param of onStartCommand() so when you kill you app it will restart the service
for reference you can check android developer guide
https://developer.android.com/reference/android/app/Service.html
I want to retrieve the incoming/outgoing call's phone number, but sometimes the delivered phone number is null. I'm unable to reproduce it, but my clients are reporting that sometimes it's not working. I can confirm this because I have logs about this (~1000 times a day the phone number is empty).
I have 2 different BroadcastReceiver's which extends WakeLockBroadcast. The IntentServices are declared in Android's manifest file.
This is the outgoing call's receiver:
public class OutgoingCallReceiver extends WakeLockBroadcast {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, OutgoingCallReceiver.PhoneService.class);
if (intent != null && intent.getExtras() != null) {
service.setAction(intent.getAction());
Bundle bundle = new Bundle(intent.getExtras());
service.putExtras(bundle);
}
startWakefulService(context, service);
}
public static class PhoneService extends IntentService {
public PhoneService() {
super("PhoneService outgoing call");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
try {
if (intent != null) {
String action = intent.getAction();
if (action != null) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
if (action.equals("android.intent.action.NEW_OUTGOING_CALL")) {
String number = bundle.getString(Intent.EXTRA_PHONE_NUMBER, null);
onOutgoingCall(number);
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
catch (Error e) {
e.printStackTrace();
}
finally {
try {
if (intent != null)
completeWakefulIntent(intent);
}
catch (NullPointerException e) {
e.printStackTrace();
}
}
}
private void onOutgoingCall(String number) {
if (TextUtils.isEmpty(number))
return;
Log.d(APPNAME, "Outgoing call: " + number);
}
}
}
This is the incoming call's receiver:
public class IncomingCallReceiver extends WakeLockBroadcast {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, IncomingCallReceiver.PhoneService.class);
if (intent != null && intent.getExtras() != null) {
service.setAction(intent.getAction());
Bundle bundle = new Bundle(intent.getExtras());
service.putExtras(bundle);
}
startWakefulService(context, service);
}
public static class PhoneService extends IntentService {
public PhoneService() {
super("PhoneService incoming call");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
try {
if (intent != null) {
String action = intent.getAction();
if (action != null) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
// Incoming call
if (action.equals("android.intent.action.PHONE_STATE")) {
String stateStr = bundle.getString(TelephonyManager.EXTRA_STATE, "");
String number = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER, "");
int state = 0;
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
if (state == TelephonyManager.CALL_STATE_IDLE) {
onCallEnd();
}
else if (state == TelephonyManager.CALL_STATE_RINGING) {
onIncomingCall(number);
}
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
catch (Error e) {
e.printStackTrace();
}
finally {
try {
if (intent != null)
completeWakefulIntent(intent);
}
catch (NullPointerException e) {
e.printStackTrace();
}
}
}
private void onCallEnd() {
}
private void onIncomingCall(String phoneNumber) {
if (TextUtils.isEmpty(phoneNumber))
return;
Log.d("APPNAME", "Incoming call: " + phoneNumber);
}
}
}
The Android's manifest file:
<receiver android:name=".broadcast.IncomingCallReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<receiver android:name=".broadcast.OutgoingCallReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Services:
<service android:name=".broadcast.IncomingCallReceiver$PhoneService" />
<service android:name=".broadcast.OutgoingCallReceiver$PhoneService" />
I might think that the intent or the intent's bundle is empty. As you can see, I'm making a check before if intent or bundle is different than null and after that setting the data to the newly created intent.
public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
#Override
public void onReceive(Context context, Intent intent) {
final Bundle data = intent.getExtras();
final Object[] pdus = (Object[]) data.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = smsMessage.getDisplayOriginatingAddress();
//You must check here if the sender is your provider and not another one with same text.
Log.i("Sender id ",sender);
String messageBody = smsMessage.getMessageBody();
Log.i("get Message body ",messageBody);
messageBody=smsMessage.getDisplayMessageBody();
Log.i("Message Body ",messageBody);
//Pass on the text to our listener.
mListener.messageReceived(messageBody);
}
}
public static void bindListener(SmsListener listener) {
mListener = listener;
}
}
public interface SmsListener {
public void messageReceived(String messageText);
}
in the fragement/dialog calling :
SmsReceiver.bindListener(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Log.d("Text",messageText);
Toast.makeText(getContext(),"Message: "+messageText,Toast.LENGTH_LONG).show();
}
});
#Override
public void onResume() {
Log.i("In resume ","resume");
SmsReceiver.bindListener(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Log.d("Text",messageText);
Toast.makeText(getContext(),"Message: "+messageText,Toast.LENGTH_LONG).show();
}
});
super.onResume();
}
#Override
public void onPause() {
Log.i("In pause ","pause");
super.onPause();
SmsReceiver.bindListener(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Log.d("Text",messageText);
Toast.makeText(getContext(),"Message: "+messageText,Toast.LENGTH_LONG).show();
}
});
}
<receiver android:name="services.SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
I am not getting any error and nothing is prints in log also. Don't know what wrong going on. Even no print from the broadcast receiver. I think code in onResume is also not executing.
For Xiaomi Permission Dialog Use this Read all SMS
private void displaySmsLog() {
Uri allMessages = Uri.parse("content://sms/");
//Cursor cursor = managedQuery(allMessages, null, null, null, null); Both are same
Cursor cursor = getActivity().getContentResolver().query(allMessages, null,
null, null, null);
if (cursor!=null) {
while (cursor.moveToNext()) {
for (int i = 0; i < cursor.getColumnCount(); i++) {
Log.d(cursor.getColumnName(i) + "", cursor.getString(i) + "");
}
Log.d("One row finished",
"**************************************************");
}
}
else {
}
}
Hope this helps.:)
Since its a xiaomi device, it denies sms read/receive permission either you have to manually switch on the permission or you can try the below code just to let xiaomi know your app needs to read/receive sms and it will show a permission dialog to read sms :-
Cursor cursor = getActivity().getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);
if (cursor == null) {
return;
}
try {
if (cursor.moveToFirst()) {
// must check the result to prevent exception
//This will show a permission dialog to let app read /receive sms
}
} while (cursor.moveToNext());
} else {
Log.e(this.getClass().getSimpleName(), "No SMS");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
cursor.close();
}
i m trying to read OTP from message, but i cant auto read it.please tell me what i did wrong, here is my code.i m using marshmallow. thank you.
here is my SmsReceiver class:
public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
#Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getExtras();
Object[] pdus = (Object[]) data.get("pdus");
for(int i=0;i<pdus.length;i++){
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = smsMessage.getDisplayOriginatingAddress();
//You must check here if the sender is your provider and not another one with same text.
String messageBody = smsMessage.getMessageBody();
//Pass on the text to our listener.
mListener.messageReceived(messageBody);
}
}
public static void bindListener(SmsListener listener) {
mListener = listener;
}}
here is interface
public interface SmsListener {
public void messageReceived(String messageText);
}
and this is my activity
public class MyOTP extends BaseActivity implements View.OnClickListener {
EditText txtotp;
Button btnSubmitOtp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_otp);
txtotp = (EditText) findViewById(R.id.txtOtp);
btnSubmitOtp = (Button) findViewById(R.id.btnSubmit);
btnSubmitOtp.setOnClickListener(this);
SmsReceiver.bindListener(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Log.d("Text",messageText);
Toast.makeText(MyOTP.this,"Message: "+messageText,Toast.LENGTH_LONG).show();
}
});
}
}
Here is my working Broadcast receiver class which will read digits from message body & broadcast with OTP code to related class
You need to add these permissions in menifest file
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission-sdk-23 android:name="android.permission.READ_SMS" />
<uses-permission-sdk-23 android:name="android.permission.RECEIVE_SMS" />
Here is my receiver class
public class SmsListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras(); //---get the SMS message passed in---
SmsMessage[] msgs = null;
String msg_from;
if (bundle != null) {
//---retrieve the SMS message received---
try {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
if (Build.VERSION.SDK_INT <= 22) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
} else {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i], bundle.getString("format"));
}
msg_from = msgs[i].getOriginatingAddress();
if (msg_from.contains("PINSMS")) {
String msgBody = msgs[i].getMessageBody();
//String pinNo = msgBody.substring(msgBody.indexOf('"') + 1, msgBody.indexOf('"', msgBody.indexOf('"') + 2));
String pinNo = msgBody.replaceAll("[^0-9]", "");
Log.d("SMS", "From -" + msg_from + " : Body- " + msgBody);
//CodeVerification.insertCode(pinNo);
// Broadcast to Auto read Code sms
final String DISPLAY_MESSAGE_ACTION = context.getPackageName() + ".CodeSmsReceived";
Intent intentCodeSms = new Intent(DISPLAY_MESSAGE_ACTION);
intentCodeSms.putExtra("varificationCode", pinNo);
context.sendBroadcast(intentCodeSms);
}
}
} catch (Exception e) {
Log.d("Exception caught", e.getMessage());
}
}
}
}
}
I have registered this receiver in my class programmatic because i know OTP sms will come after my submit button click & i unregister it after OTP read as i dont want to trigger this receiver for every SMS by registering it in menifest.
SmsListener smsListener = new SmsListener();
try {
unregisterReceiver(smsListener);
} catch (Exception e) {
}
registerReceiver(smsListener, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
EDIT
Put below receiver in your activity to get OTP code
final String DISPLAY_MESSAGE_ACTION = activity.getPackageName() + ".CodeSmsReceived";
try {
activity.unregisterReceiver(mHandleMessageReceiver);
} catch (Exception e) {
}
activity.registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION));
On receiving code below method will be called
/**
* Receiving Call Log Changed broadcast
*/
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.hasExtra("varificationCode")) {
String youtOTPcode = intent.getStringExtra("varificationCode"));
}
}
};
For Marshmallow you have to ask users to give permissions. It's not given by default even if you declare it in manifest. You need to add code to get runtime permission for marshmallow devices.
For now just for checking you can go to settings --> Apps --> go to your in the list --> click on permissions --> Enable SMS permission. Then restart your app and check is it working.
Hope it will help you.
Change MyOtpActivity to
public class MyOTP extends BaseActivity{
EditText txtotp;
Button btnSubmitOtp;
private UpdateOTPReceiver mUpdateOtpReceiver;
private SMSReceiver mSmsReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_otp);
txtotp = (EditText) findViewById(R.id.txtOtp);
btnSubmitOtp = (Button) findViewById(R.id.btnSubmit);
btnSubmitOtp.setOnClickListener(this);
}
#Override
protected void onStart() {
super.onStart();
mUpdateOtpReceiver = new UpdateOTPReceiver();
registerReceiver(mUpdateOtpReceiver, new IntentFilter("UPDATE_OTP"));
registerSMSReceiver();
}
private void registerSMSReceiver() {
mSmsReceiver = new SMSReceiver();
registerReceiver(mSmsReceiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
}
private class UpdateOTPReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
String msg = intent.getStringExtra("msg");
Toast.makeText(MyOTP.this,"Message: "+msg,Toast.LENGTH_LONG).show();
}
}
}
}
}
In SmsReceiver
Public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getExtras();
Object[] pdus = (Object[]) data.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = smsMessage.getDisplayOriginatingAddress();
//ToDo check your sender
String messageBody = smsMessage.getDisplayMessageBody();
Intent updateTokenIntent = new Intent("UPDATE_OTP");
updateTokenIntent.putExtra("msg", getVerificationCode(messageBody));
context.sendBroadcast(updateTokenIntent);
}
}
private String getVerificationCode(String message) {
if (message == null) {
return null;
}
int index = message.indexOf("is");
int index_last_length = message.indexOf(".");
if (index != -1) {
int start = index + 3;
return message.substring(start, index_last_length);
}
return null;
}
}
You Cannot Read a SMS having OTP word in it through broadcast receiver because of google policy.
You Cannot Read a SMS having OTP word in it through broadcast receiver because of google policy is well said by Ridhika....
OTP messages can only be read by app that has its HashCode in the message body.