অ্যান্ড্রয়েড - আগত এসএমএস বার্তাগুলির জন্য শোনো Listen


155

আমি আগত এসএমএস বার্তাগুলি পর্যবেক্ষণ করার জন্য একটি অ্যাপ্লিকেশন তৈরি করার চেষ্টা করছি, এবং আগত এসএমএসের মাধ্যমে একটি প্রোগ্রাম চালু করব, এটি এসএমএসের সামগ্রীটিও পড়তে হবে।

কর্মধারা:

  • অ্যান্ড্রয়েড ডিভাইসে এসএমএস পাঠানো হয়েছে
  • স্ব নির্বাহযোগ্য অ্যাপ্লিকেশন
  • এসএমএস তথ্য পড়ুন

1
আমি এসএমএস প্রেরণের জন্য একটি অ্যাপ্লিকেশন তৈরি করতে জানি, তবে এখানে আমাকে একটি এসএমএস অ্যাপ্লিকেশন তৈরি করতে হবে যা এসএমএস থেকে তথ্য
পেয়ে এসকিউএলাইট

@ আইশ্যাডার আমি আশা করি আপনি অ্যাপটি তৈরিতে সাফল্য পেয়েছেন, আপনি কীভাবে এমএসএসএস বি / ডাব্লুড ডিভাইস এবং সার্ভারকে সিঙ্ক করতে পারবেন তা জানতে চেয়েছিলেন
জন 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());
                }
            }
        }
    }
}

দ্রষ্টব্য: আপনার ম্যানিফেস্ট ফাইলে ব্রডকাস্টার্সিভার- যুক্ত করুন

<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
@ ভিনিটশুকলা আপনি কি দয়া করে ব্যাখ্যা করতে পারবেন পিডিএস কি ??
দ্য গ্র্যাজুয়েট গুয়

11
হার্ড-কোডডটির পরিবর্তে ইনটেন্টস ব্যবহার করুন SSMS_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 হয় The মানটি -1000 এর চেয়ে বেশি এবং 1000 এর চেয়ে কম হতে হবে।

এখানে একটি লিঙ্ক।


30
এই উত্তরটি আরও মার্জিত হতে পারে তবে এপিআই 19 দরকার others অন্যদের জন্য কেবল একটি FYI I
বাইকাচেক

10
মতে এই , android:priorityবেশী হতে পারে না 1000(অথবা কম -1000)।
craned

2
এটি অ্যান্ড্রয়েড 5.1 এর সাথে শাওমি রেডমি নোট 3 প্রোতে কাজ করে না। প্রত্যেকেই এই সমাধান সরবরাহ করছে তবে এটি আমার পক্ষে কার্যকর হবে বলে মনে হয় না।
সেরিলিওন

মেনিফেস্ট ফাইলটিতে <রিসিভার ... মার্কআপ inোকানো হয় কোথায়?
জন ওয়ার্ড

3
@Surilion আপনি ম্যানুয়ালি মোবাইলের অ্যাপ্লিকেশন ম্যানেজারে এসএমএস পড়ার অনুমতি দিতে হবে।
সঞ্জয় কুশওয়াহ

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

আপনি যদি খোলার ক্রিয়াকলাপের উদ্দেশ্যে অভিপ্রায় পরিচালনা করতে চান তবে আপনি পেন্ডিন্টইন্টেন্ট (নীচের সম্পূর্ণ পদক্ষেপ) ব্যবহার করতে পারেন:

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" />

গুগল প্লে স্টোরের গুগল প্রশাসকরা RECEIVE_SMS অনুমতি (আপনার যে টিউটোরিয়ালটিতে উল্লেখ করেছেন) বিপজ্জনক বলে বিবেচনা করে। ফলস্বরূপ, অনুমতি দেওয়া একটি অ্যাপ্লিকেশন প্রত্যাখ্যান করা হবে। তারপরে বিকাশকারীকে অনুমোদনের জন্য গুগল প্লে প্রশাসকদের কাছে একটি ফর্ম জমা দিতে হবে। অন্যান্য বিকাশকারীরা উল্লেখ করেছেন যে প্রক্রিয়াটি কয়েক সপ্তাহ গ্রহণের সাথে প্রতিক্রিয়া এবং কোনও ব্যাখ্যা বা জেনেরিক প্রতিক্রিয়া ছাড়াই প্রত্যক্ষ প্রত্যাখ্যানগুলি পাওয়ার সাথে জঘন্য। কীভাবে এড়ানো যায় এ সম্পর্কে কোনও ধারণা?
এজেডাব্লু

2

যদি কেউ আমার মতো জামারিন অ্যান্ড্রয়েডে একই বৈশিষ্ট্যটি (প্রাপ্ত এসএমএস ব্যবহার করে ওটিপি পড়া) কীভাবে করবেন তা উল্লেখ করে:

  1. এই কোডটি আপনার অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএল ফাইলটিতে যুক্ত করুন:

    <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" বলে একটি সংকলক ত্রুটি পেয়েছে কেবলমাত্র সিস্টেম অ্যাপ্লিকেশনগুলিতে granted
প্রতিশ্রুতিবদ্ধ

2

@ ভিনিত শুক্লাকে (গৃহীত উত্তর) এবং @ রুচির বড়োনিয়া (গৃহীত উত্তরে বিষয়টি পাওয়া গেছে) ধন্যবাদ, নীচে Kotlin সংস্করণটি রয়েছে:

অনুমতি যুক্ত করুন:

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

অ্যান্ড্রয়েড ম্যানিফেস্টে ব্রডকাস্টারসিভার নিবন্ধন করুন:

<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>

ব্রডকাস্টার্সিভারের জন্য বাস্তবায়ন যুক্ত করুন:

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

কোটলিনে সম্প্রচার বাস্তবায়ন:

 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
    }
}

দ্রষ্টব্য: আপনার ম্যানিফেস্ট ফাইলে ব্রডকাস্টার্সিভার- যুক্ত করুন

<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 () এর শেষে চেকফোরএসএমএস রিসিপপ্রেশন () পদ্ধতিতে কল করুন।

    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");
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.