2013-11-21 11 views

Trả lời

57

Để bắt đầu, điều này sẽ yêu cầu hai quyền; một để gửi tin nhắn SMS và một để nhận tin nhắn. Sau đây cần phải có trong AndroidManifest.xml của bạn, giữa các thẻ <manifest>, nhưng bên ngoài các thẻ <application>.

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

Cả hai đều là quyền nguy hiểm, vì vậy bạn sẽ cần phải xử lý chúng cho phù hợp nếu ứng dụng của bạn là để chạy trên Marshmallow (cấp API 23) hoặc cao hơn, và có một targetSdkVersion của 23+. Thông tin về cách yêu cầu các quyền này trong thời gian chạy có thể được tìm thấy trên this developer page.


Các lớp Java bạn cần có trong gói android.telephony; cụ thể là android.telephony.SmsManagerandroid.telephony.SmsMessage. Hãy chắc chắn rằng bạn đã nhập đúng các lớp học cho cả hai.

Để gửi tin nhắn SMS gửi đi, bạn sẽ sử dụng phương pháp sendTextMessage()SmsManager 's, trong đó có chữ ký sau đây:

sendTextMessage(String destinationAddress, String scAddress, String text, 
       PendingIntent sentIntent, PendingIntent deliveryIntent) 

Chỉ có hai đối số được yêu cầu trong lời gọi phương thức này - destinationAddresstext; đầu tiên là số điện thoại, số thứ hai là nội dung tin nhắn. null có thể được chuyển cho phần còn lại. Ví dụ:

String number = "1234567890"; 
String message = "Verification message."; 
SmsManager sm = SmsManager.getDefault(); 
sm.sendTextMessage(number, null, message, null, null); 

Điều quan trọng là để giữ cho nội dung bài viết tương đối ngắn, như sendTextMessage() thường sẽ thất bại âm thầm nếu độ dài văn bản vượt quá giới hạn ký tự cho một tin nhắn đơn.


Tiếp nhận và đọc tin nhắn gửi đến, bạn sẽ cần phải đăng ký một BroadcastReceiver với một IntentFilter cho hành động "android.provider.Telephony.SMS_RECEIVED". Người nhận này có thể được đăng ký tĩnh trong tệp kê khai hoặc động trên Context khi chạy.

  • Tĩnh đăng ký lớp người nhận trong tệp kê khai sẽ cho phép ứng dụng của bạn nhận được tin nhắn đến ngay cả khi ứng dụng của bạn bị giết trước khi nhận. Tuy nhiên, có thể mất thêm một chút công sức để có được kết quả mà bạn muốn. Giữa <application> tags:

    <receiver 
        android:name=".SmsReceiver" 
        android:enabled="false"> 
        <intent-filter> 
         <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
        </intent-filter> 
    </receiver> 
    

    Phương pháp PackageManager#setComponentEnabledSetting() thể được sử dụng để kích hoạt và vô hiệu hóa <receiver> này khi cần thiết.

  • Tự động đăng ký phiên bản Người nhận trên Context có thể dễ quản lý hơn một chút, vì lớp Người nhận có thể được tạo thành lớp bên trong trên bất kỳ thành phần nào đăng ký nó và do đó có quyền truy cập trực tiếp vào thành viên của thành phần đó . Tuy nhiên, phương pháp này có thể không đáng tin cậy như đăng ký tĩnh, vì một vài điều khác nhau có thể ngăn Người nhận nhận được phát sóng; ví dụ: quá trình ứng dụng của bạn bị giết, người dùng điều hướng khỏi đăng ký Activity, v.v.

    SmsReceiver receiver = new SmsReceiver(); 
    IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); 
    registerReceiver(receiver, filter); 
    

    Hãy nhớ hủy đăng ký người nhận khi thích hợp.


Trong phương pháp onReceive() của Receiver, thông điệp thực tế được đưa ra khi một mảng của mảng byte gắn liền với Intent như thêm. Chi tiết giải mã khác nhau tùy thuộc vào phiên bản Android, nhưng kết quả ở đây là một đối tượng SmsMessage duy nhất sẽ có số điện thoại và tin nhắn bạn đang theo dõi.

class SmsReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     SmsMessage msg; 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 
      SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent); 
      msg = msgs[0]; 
     } else { 
      Object pdus[] = (Object[]) intent.getExtras().get("pdus"); 
      msg = SmsMessage.createFromPdu((byte[]) pdus[0]); 
     } 

     String number = msg.getOriginatingAddress(); 
     String message = msg.getMessageBody(); 
     ... 
    } 
} 

Tại thời điểm này, bạn chỉ cần so sánh number đây để là người truyền cho sendTextMessage() gọi. Bạn nên sử dụng PhoneNumberUtils.compare() vì điều này, vì số được truy xuất trong Bộ thu có thể ở định dạng khác với định dạng được giải quyết.


Ghi chú:

  • Ví dụ chứng minh ở đây là sử dụng một thông điệp duy nhất một phần, vì vậy tại sao các tin nhắn văn bản nên được giới hạn trong một thời gian tương đối ngắn. Nếu bạn muốn gửi một tin nhắn dài hơn, vì một số lý do, phương pháp sendMultipartTextMessage() có thể được sử dụng thay thế. Trước tiên, bạn cần phân tách văn bản bằng cách sử dụng SmsManager#divideMessage() và chuyển kết quả ArrayList sang phương thức đó, thay cho thông báo String. Để tập hợp lại thông điệp hoàn chỉnh trong Bộ thu, bạn phải giải mã từng số byte[] thành một số SmsMessage và nối các nội dung thư.

  • Vì KitKat (API cấp 19), nếu ứng dụng của bạn không phải là ứng dụng nhắn tin mặc định, các tin nhắn được sử dụng ở đây sẽ được lưu vào Nhà cung cấp SMS bởi ứng dụng mặc định và hệ thống. ứng dụng khác sử dụng Nhà cung cấp. Không có nhiều bạn có thể làm về điều đó, nhưng nếu bạn thực sự muốn tránh nó, kỹ thuật tương tự này có thể được sử dụng với dữ liệu SMS, không kích hoạt ứng dụng mặc định và sẽ không được lưu vào Nhà cung cấp.

    Đối với điều này, phương pháp sendDataMessage() được sử dụng, mà sẽ cần một short luận bổ sung cho (tùy ý) số cổng, và thông điệp được truyền như một byte[], chứ không phải là một String. Hành động lọc là "android.intent.action.DATA_SMS_RECEIVED" và bộ lọc sẽ cần một lược đồ dữ liệu và quyền (máy chủ và cổng) được đặt. Trong tệp kê khai, nó sẽ trông giống như:

    <intent-filter> 
        <action android:name="android.intent.action.DATA_SMS_RECEIVED" /> 
        <data 
         android:scheme="sms" 
         android:host="localhost" 
         android:port="1234" /> 
    </intent-filter> 
    

    và có phương pháp tương ứng trong lớp IntentFilter để đặt các phương thức này theo kiểu động.

    Giải mã SmsMessage giống nhau, nhưng thông báo byte[] được truy xuất với getUserData(), thay vì getMessageBody().

  • Trước KitKat, ứng dụng chịu trách nhiệm viết thư gửi đi của riêng mình, vì vậy bạn không thể làm điều đó trên các phiên bản đó, nếu bạn không muốn bất kỳ bản ghi nào của nó.

    Tin nhắn đến có thể bị chặn và các chương trình phát sóng của chúng bị hủy trước khi ứng dụng nhắn tin chính có thể nhận và ghi chúng. Để thực hiện việc này, ưu tiên của bộ lọc được đặt ở mức tối đa và abortBroadcast() được gọi trong Bộ thu.Trong tùy chọn tĩnh, thuộc tính android:priority="999" được thêm vào thẻ mở <intent-filter>. Tự động, phương thức IntentFilter#setPriority() có thể thực hiện tương tự.

    Điều này hoàn toàn không đáng tin cậy, vì ứng dụng khác có thể có ưu tiên cao hơn của bạn luôn có thể.

  • Tôi đã bỏ qua việc bảo vệ Người nhận bằng quyền của truyền thông trong các ví dụ này, một phần vì sự đơn giản và rõ ràng, và một phần vì bản chất của điều đó thực sự không để bạn mở bất kỳ loại giả mạo nào có thể gây hại . Tuy nhiên, nếu bạn muốn bao gồm điều này, thì bạn chỉ cần thêm thuộc tính android:permission="android.permission.BROADCAST_SMS" vào thẻ mở <receiver> cho tùy chọn tĩnh. Đối với động, sử dụng quá tải bốn tham số của phương pháp registerReceiver(), chuyển quyền đó String làm đối số thứ ba và null làm phương thức thứ tư.

+7

Cảm ơn bạn rất nhiều vì câu trả lời chi tiết và đầy đủ. –

3

Sinch SDK cho phép bạn xác minh số điện thoại của người dùng bằng cách sử dụng công nghệ cuộc gọi flash. Nó dựa trên mạng điện thoại thông thường vì vậy nếu số điện thoại của người dùng hợp lệ, bạn sẽ nhận được một cuộc gọi nhỡ.

private void startVerification(String phoneNumber) { 
Config config = SinchVerification.config().applicationKey("your_app_key").context(getApplicationContext()).build(); 
VerificationListener listener = new MyVerificationListener(); 
verification = SinchVerification.createFlashCallVerification(config, phoneNumber, listener); 
verification.initiate(); 
} 

Để biết thêm thông tin bạn có thể xem hướng dẫn này:

https://www.sinch.com/tutorials/android-flash-call-verification/

+0

Không chỉ đăng lại những gì một người kiểm duyệt đã xóa mà không cần giải quyết nhận xét. Bạn có thể vui lòng bao gồm [tiết lộ liên kết] (https://stackoverflow.com/help/promotion) trong bài đăng của mình không? Nếu không, bài đăng này cũng sẽ bị xóa là spam. –

Các vấn đề liên quan