Android - आने वाले एसएमएस संदेशों के लिए सुनो


155

मैं आने वाले एसएमएस संदेशों की निगरानी के लिए एक एप्लिकेशन बनाने की कोशिश कर रहा हूं, और आने वाले एसएमएस के माध्यम से एक प्रोग्राम लॉन्च कर सकता हूं, यह भी एसएमएस से सामग्री को पढ़ना चाहिए।

कार्यप्रवाह:

  • एंड्रॉइड डिवाइस पर एसएमएस भेजा गया
  • आत्म निष्पादन योग्य अनुप्रयोग
  • एसएमएस की जानकारी पढ़ें

1
मैं एसएमएस भेजने के लिए एक ऐप बनाना जानता हूं, लेकिन यहां मुझे एक एसएमएस ऐप बनाने की आवश्यकता है जो एसएमएस से जानकारी प्राप्त करता है और इसे SQLite डेटाबेस में सहेजता है ..... मैं इस तरह के ऐप को कैसे विकसित कर सकता हूं
iShader

@iShader मुझे आशा है कि आप ऐप बनाने में सफल हो गए हैं, बस यह जानना चाहते हैं कि आपने डिवाइस और सर्वर को msgs b / w को सिंक करने का प्रबंधन कैसे किया
John x

जवाबों:


265
public class SmsListener extends BroadcastReceiver{

    private SharedPreferences preferences;

    @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++){
                        msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
                        msg_from = msgs[i].getOriginatingAddress();
                        String msgBody = msgs[i].getMessageBody();
                    }
                }catch(Exception e){
//                            Log.d("Exception caught",e.getMessage());
                }
            }
        }
    }
}

नोट: अपनी मैनिफ़ेस्ट फ़ाइल में BroadcastReceiver- जोड़ें

<receiver android:name=".listener.SmsListener">
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

यह अनुमति जोड़ें:

<uses-permission android:name="android.permission.RECEIVE_SMS" />

2
क्या आप मुझे बता सकते हैं कि आप एक माध्यमिक रिसीवर का उपयोग क्यों करते हैं?
विंडराइडर

2
@VineetShukla क्या आप बता सकते हैं कि क्या है पीडीएस ??
theGraduateGuy

11
हार्ड कोडित के बजाय Int.S.S_RECEIVED_ACTION का उपयोग करें।
अहमद कायली

6
उपरोक्त टिप्पणी सही नहीं है। किसी भी ऐप को अभी भी SMS_RECEIVED4.4+ में प्रसारण मिल सकता है , और, अब उस प्रसारण को समाप्त नहीं किया जा सकता है, यह पिछले संस्करणों की तुलना में अधिक निश्चित है।
माइक एम।

3
@ रुचिरबोरोनिया मल्टीपार्ट संदेश। एक एसएमएस संदेश की एक चरित्र सीमा होती है (यह आपके द्वारा उपयोग किए जा रहे वर्ण सेट के आधार पर भिन्न होता है, लेकिन सामान्य सीमाएं 70, 140, 160 वर्ण हैं)। यदि कोई संदेश उस सीमा से अधिक है, तो उसे कई संदेशों, भागों में विभाजित किया जा सकता है। वह सरणी भागों का वह सरणी है जिसे आपको पूरा संदेश प्राप्त करने के लिए संक्षिप्त करने की आवश्यकता है। आपका रिसीवर केवल एक समय में एक ही पूरा संदेश प्राप्त करेगा; यह सिर्फ कई हिस्सों में हो सकता है।
माइक एम।

65

ध्यान दें कि कुछ उपकरणों पर आपका कोड एंड्रॉइड के बिना काम नहीं करेगा : इरादे फ़िल्टर में प्राथमिकता = "1000" :

<receiver android:name=".listener.SmsListener">
    <intent-filter android:priority="1000">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

और यहाँ कुछ अनुकूलन है:

public class SmsListener extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {
            for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
                String messageBody = smsMessage.getMessageBody();
            }
        }
    }
}

नोट :
मान एक पूर्णांक होना चाहिए, जैसे कि "100"। उच्च संख्या की उच्च प्राथमिकता है। डिफ़ॉल्ट मान है 0. मान 1000 से अधिक और 1000 से कम होना चाहिए।

यहाँ एक लिंक है।


30
यह उत्तर अधिक सुरुचिपूर्ण हो सकता है, लेकिन इसके लिए API 19 की आवश्यकता होती है। दूसरों के लिए बस एक FYI करें।
baekacaek

10
के अनुसार इस , android:priorityसे अधिक नहीं हो सकता है 1000(या कम से कम -1000)।
craned

2
यह एंड्रायड 5.1 के साथ Xiaomi Redmi Note 3 Pro पर काम नहीं करता है। हर कोई यह समाधान प्रदान कर रहा है, लेकिन यह मेरे लिए काम नहीं करता है।
सिंदूर

मैनिफ़ेस्ट फ़ाइल में <रिसीवर ... मार्कअप कहाँ डाला गया है?
जॉन वार्ड

3
@Sermilion आपको मोबाइल के एप्लिकेशन मैनेजर में एसएमएस को मैन्युअल रूप से पढ़ने की अनुमति देनी होगी।
संजय कुशवाह

6

@ माइक एम और मुझे स्वीकृत उत्तर के साथ एक मुद्दा मिला (हमारी टिप्पणियाँ देखें):

मूल रूप से, लूप के माध्यम से जाने का कोई मतलब नहीं है, अगर हम हर बार मल्टीपार्ट संदेश को साझा नहीं कर रहे हैं:

for (int i = 0; i < msgs.length; i++) {
    msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
    msg_from = msgs[i].getOriginatingAddress();
    String msgBody = msgs[i].getMessageBody();
}

ध्यान दें कि हम सिर्फ msgBodyसंदेश के संबंधित भाग के स्ट्रिंग मान पर सेट होते हैं, चाहे हम किसी भी सूचकांक पर हों, जो कि एसएमएस संदेश के विभिन्न हिस्सों के माध्यम से लूपिंग के पूरे बिंदु को बेकार कर देता है, क्योंकि यह बस बहुत पर सेट हो जाएगा अंतिम सूचकांक मूल्य। इसके बजाय हमें उपयोग करना चाहिए +=, या जैसा कि माइक ने उल्लेख किया है StringBuilder:

सब सब में, यहाँ मेरा एसएमएस प्राप्त कोड जैसा दिखता है:

if (myBundle != null) {
    Object[] pdus = (Object[]) myBundle.get("pdus"); // pdus is key for SMS in bundle

    //Object [] pdus now contains array of bytes
    messages = new SmsMessage[pdus.length];
    for (int i = 0; i < messages.length; i++) {
         messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); //Returns one message, in array because multipart message due to sms max char
         Message += messages[i].getMessageBody(); // Using +=, because need to add multipart from before also
    }

    contactNumber = messages[0].getOriginatingAddress(); //This could also be inside the loop, but there is no need
}

इस उत्तर को किसी अन्य भ्रम की स्थिति में होने पर बस वहीँ रख देना चाहिए।


4

यह मैं क्या इस्तेमाल किया है!

public class SMSListener extends BroadcastReceiver {

    // Get the object of SmsManager
    final SmsManager sms = SmsManager.getDefault();
String mobile,body;

    public void onReceive(Context context, Intent intent) {

        // Retrieves a map of extended data from the intent.
        final Bundle bundle = intent.getExtras();

        try {

            if (bundle != null) {

                final Object[] pdusObj = (Object[]) bundle.get("pdus");

                for (int i = 0; i < pdusObj.length; i++) {

                    SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
                    String phoneNumber = currentMessage.getDisplayOriginatingAddress();

                    String senderNum = phoneNumber;
                    String message = currentMessage.getDisplayMessageBody();
                     mobile=senderNum.replaceAll("\\s","");
                     body=message.replaceAll("\\s","+");


                    Log.i("SmsReceiver", "senderNum: "+ senderNum + "; message: " + body);


                    // Show Alert
                    int duration = Toast.LENGTH_LONG;
                    Toast toast = Toast.makeText(context,
                            "senderNum: "+ mobile+ ", message: " + message, duration);
                    toast.show();

                } // end for loop
            } // bundle is null

        } catch (Exception e) {
            Log.e("SmsReceiver", "Exception smsReceiver" +e);

        }
    }
}

2

यदि आप खुली हुई गतिविधि पर इरादे को संभालना चाहते हैं, तो आप PendintIntent (नीचे दिए गए पूर्ण चरण) का उपयोग कर सकते हैं:

public class SMSReciver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        final Bundle bundle = intent.getExtras();
        try {
            if (bundle != null) {
                final Object[] pdusObj = (Object[]) bundle.get("pdus");
                for (int i = 0; i < pdusObj.length; i++) {
                    SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
                    String phoneNumber = currentMessage.getDisplayOriginatingAddress();
                    String senderNum = phoneNumber;
                    String message = currentMessage.getDisplayMessageBody();
                    try {
                        if (senderNum.contains("MOB_NUMBER")) {
                            Toast.makeText(context,"",Toast.LENGTH_SHORT).show();

                            Intent intentCall = new Intent(context, MainActivity.class);
                            intentCall.putExtra("message", currentMessage.getMessageBody());

                            PendingIntent pendingIntent= PendingIntent.getActivity(context, 0, intentCall, PendingIntent.FLAG_UPDATE_CURRENT);
                            pendingIntent.send();
                        }
                    } catch (Exception e) {
                    }
                }
            }
        } catch (Exception e) {
        }
    }
} 

प्रकट:

<activity android:name=".MainActivity"
            android:launchMode="singleTask"/>
<receiver android:name=".SMSReciver">
            <intent-filter android:priority="1000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>

onNewIntent:

 @Override
         protected void onNewIntent(Intent intent) {
                super.onNewIntent(intent);
                Toast.makeText(this, "onNewIntent", Toast.LENGTH_SHORT).show();

                onSMSReceived(intent.getStringExtra("message"));

            }

अनुमतियाँ:

<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />

Google Play Store के लिए Google व्यवस्थापक RECEIVE_SMS की अनुमति (आपके द्वारा उल्लेखित ट्यूटोरियल में) को खतरनाक मानते हैं। नतीजतन, एक ऐप जिसमें अनुमति शामिल है उसे अस्वीकार कर दिया जाएगा। तब डेवलपर को अनुमोदन के लिए Google Play व्यवस्थापकों को एक फ़ॉर्म सबमिट करना होगा। अन्य डेवलपर्स ने इस प्रक्रिया का उल्लेख किया है कि यह प्रतिक्रिया सप्ताह के दौरान भयानक है और किसी भी स्पष्टीकरण या सामान्य प्रतिक्रिया के साथ एकमुश्त अस्वीकृति प्राप्त करना। कैसे से बचने के लिए पर कोई विचार?
AJW

2

अगर कोई मेरी तरह Xamarin Android पर एक ही सुविधा (प्राप्त एसएमएस का उपयोग करके ओटीपी पढ़ रहा है) का संदर्भ देता है:

  1. इस कोड को अपने AndroidManifest.xml फ़ाइल में जोड़ें:

    <receiver android:name=".listener.BroadcastReveiverOTP">
    <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.BROADCAST_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />
  2. फिर अपने एंड्रॉइड प्रोजेक्ट में अपना ब्रॉडकास्टइवर क्लास बनाएं।

    [BroadcastReceiver(Enabled = true)] [IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" }, Priority = (int)IntentFilterPriority.HighPriority)] 
    public class BroadcastReveiverOTP : BroadcastReceiver {
            public static readonly string INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED";
    
            protected string message, address = string.Empty;
    
            public override void OnReceive(Context context, Intent intent)
            {
                if (intent.HasExtra("pdus"))
                {
                    var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus");
                    foreach (var item in smsArray)
                    {
                        var sms = SmsMessage.CreateFromPdu((byte[])item);
                        address = sms.OriginatingAddress;
                        if (address.Equals("NotifyDEMO"))
                        {
                            message = sms.MessageBody;
                            string[] pin = message.Split(' ');
                            if (!string.IsNullOrWhiteSpace(pin[0]))
                            { 
                                    // NOTE : Here I'm passing received OTP to Portable Project using MessagingCenter. So I can display the OTP in the relevant entry field.
                                    MessagingCenter.Send<object, string>(this,MessengerKeys.OnBroadcastReceived, pin[0]);
                            }
                            }
                    }
                }
            }
    }
  3. एंड्रॉइड प्रोजेक्ट पर अपने ब्रॉडएक्टिविटी वर्ग में इस ब्रॉडकास्टसीवर क्लास को पंजीकृत करें:

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity {
    
            // Initialize your class
            private BroadcastReveiverOTP _receiver = new BroadcastReveiverOTP ();
    
            protected override void OnCreate(Bundle bundle) { 
                    base.OnCreate(bundle);
    
                    global::Xamarin.Forms.Forms.Init(this, bundle);
                    LoadApplication(new App());
    
                    // Register your receiver :  RegisterReceiver(_receiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
    
            }
    }

"Android.permission.BROADCAST_SMS" कहते हुए एक कंपाइलर त्रुटि मिली है जो केवल सिस्टम ऐप्स को दी गई है।
committedandroider

2

@ विनीत शुक्ला (स्वीकृत उत्तर) और @ रुचिर बरोनिया (स्वीकृत उत्तर में समस्या पाया गया) के लिए धन्यवाद, नीचे Kotlinसंस्करण है:

अनुमति जोड़ें:

<uses-permission android:name="android.permission.RECEIVE_SMS" />

AndroidManifest में प्रसारण ब्रॉडकास्टर पंजीकृत करें:

<receiver
    android:name=".receiver.SmsReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter android:priority="2332412">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

BroadcastReceiver के लिए कार्यान्वयन जोड़ें:

class SmsReceiver : BroadcastReceiver() {
    private var mLastTimeReceived = System.currentTimeMillis()

    override fun onReceive(p0: Context?, intent: Intent?) {
        val currentTimeMillis = System.currentTimeMillis()
        if (currentTimeMillis - mLastTimeReceived > 200) {
            mLastTimeReceived = currentTimeMillis

            val pdus: Array<*>
            val msgs: Array<SmsMessage?>
            var msgFrom: String?
            var msgText: String?
            val strBuilder = StringBuilder()
            intent?.extras?.let {
                try {
                    pdus = it.get("pdus") as Array<*>
                    msgs = arrayOfNulls(pdus.size)
                    for (i in msgs.indices) {
                        msgs[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray)
                        strBuilder.append(msgs[i]?.messageBody)
                    }

                    msgText = strBuilder.toString()
                    msgFrom = msgs[0]?.originatingAddress

                    if (!msgFrom.isNullOrBlank() && !msgText.isNullOrBlank()) {
                        //
                        // Do some thing here
                        //
                    }
                } catch (e: Exception) {
                }
            }
        }
    }
}

कुछ समय के लिए घटना दो बार फायर करती है इसलिए मैं जोड़ देता हूं mLastTimeReceived = System.currentTimeMillis()


1

Kotlin पर प्रसारण कार्यान्वयन:

 private class SmsListener : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        Log.d(TAG, "SMS Received!")

        val txt = getTextFromSms(intent?.extras)
        Log.d(TAG, "message=" + txt)
    }

    private fun getTextFromSms(extras: Bundle?): String {
        val pdus = extras?.get("pdus") as Array<*>
        val format = extras.getString("format")
        var txt = ""
        for (pdu in pdus) {
            val smsmsg = getSmsMsg(pdu as ByteArray?, format)
            val submsg = smsmsg?.displayMessageBody
            submsg?.let { txt = "$txt$it" }
        }
        return txt
    }

    private fun getSmsMsg(pdu: ByteArray?, format: String?): SmsMessage? {
        return when {
            SDK_INT >= Build.VERSION_CODES.M -> SmsMessage.createFromPdu(pdu, format)
            else -> SmsMessage.createFromPdu(pdu)
        }
    }

    companion object {
        private val TAG = SmsListener::class.java.simpleName
    }
}

नोट: अपनी मैनिफ़ेस्ट फ़ाइल में BroadcastReceiver- जोड़ें

<receiver android:name=".listener.SmsListener">
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

यह अनुमति जोड़ें:

<uses-permission android:name="android.permission.RECEIVE_SMS" />

1

स्वीकृत उत्तर सही है और एंड्रॉइड के पुराने संस्करणों पर काम करता है जहां एंड्रॉइड ओएस ऐप इंस्टॉल पर अनुमति मांगता है, हालांकि नए संस्करणों पर एंड्रॉइड यह सीधे काम नहीं करता है क्योंकि नए एंड्रॉइड ओएस रनटाइम के दौरान अनुमति मांगते हैं जब ऐप को उस सुविधा की आवश्यकता होती है । इसलिए स्वीकार किए गए उत्तर प्रोग्रामर में वर्णित तकनीक का उपयोग करके एंड्रॉइड के नए संस्करणों पर एसएमएस प्राप्त करने के लिए भी कोड को लागू करना होगा जो रनटाइम के दौरान उपयोगकर्ता से अनुमति मांगेगा। इस स्थिति में कार्यक्षमता / कोड की जांच करने की अनुमति ऐप की पहली गतिविधि के ऑनक्रिएट () में लागू की जा सकती है। बस अपनी पहली गतिविधि में दो तरीकों का पालन करें और कॉपी करें और onCreate () के अंत में checkForSmsReceivePiers () विधि को कॉल करें।

    void checkForSmsReceivePermissions(){
    // Check if App already has permissions for receiving SMS
    if(ContextCompat.checkSelfPermission(getBaseContext(), "android.permission.RECEIVE_SMS") == PackageManager.PERMISSION_GRANTED) {
        // App has permissions to listen incoming SMS messages
        Log.d("adnan", "checkForSmsReceivePermissions: Allowed");
    } else {
        // App don't have permissions to listen incoming SMS messages
        Log.d("adnan", "checkForSmsReceivePermissions: Denied");

        // Request permissions from user 
        ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.RECEIVE_SMS}, 43391);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == 43391){
        if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            Log.d("adnan", "Sms Receive Permissions granted");
        } else {
            Log.d("adnan", "Sms Receive Permissions denied");
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.