web-dev-qa-db-ja.com

ADBを介してSMS on Android

次のADBコマンドを使用して、コンピューターに接続しているときに、SMS電話からAndroidを送信できるようにしたい

adb Shell am start -a Android.intent.action.SENDTO -d sms:CCXXXXXXXXXX --es sms_body "SMS BODY GOES HERE" --ez exit_on_sent true
adb Shell input keyevent 22
adb Shell input keyevent 66

私はこれを機能させていますが、電話では、本文が入力されたテキストメッセージが受信者にポップアップ表示され、送信ボタンをクリックして元の場所に戻ります。これを完全にバックグラウンドで実行して、電話で発生することを妨げないようにする方法はありますか?

11
user790995

ショートバージョン:

Android 5以前(ここではAndroid 4):

_adb Shell service call isms 5 s16 "com.Android.mms" s16 "+01234567890" s16 "+01SMSCNUMBER" s16 "Hello world !" i32 0 i32 0
_

Android 5以降(ここではAndroid 9):

_adb Shell service call isms 7 i32 0 s16 "com.Android.mms.service" s16 "+1234567890" s16 "null" s16 "Hey\ you\ !" s16 "null" s16 "null"
_

Ismsメソッド番号(上記の5および7)は、Androidバージョンで変更される可能性があります。完全な説明を読んで理解してください。


すべての完全な説明Androidバージョン:

はい、存在します!ただし、これらの入力イベントはスリープモードでブロックされるため、このコマンドでは使用できません。この解決策はあなたのAndroidバージョンに依存するので、ほぼすべてのバージョンについて説明します...

まず、次のコマンドを実行して、サービスismがあるかどうかを確認します。

_adb Shell service check isms
Service isms: found
_

答えは見つかりました、良いです、動き続けてください。サービスismには、構文が次のようなさまざまな「オプション」があります。

_service call name_service option args
_

サービス名は、次のように入力して見つけることができます。

_adb Shell service list
_

利用可能な多くのサービスが表示されますが、興味深い行は次のとおりです。

_5       isms: [com.Android.internal.telephony.ISms]
_

Com.Android.internal.telephony.Ismsが表示されるので、これについて リンク Androidバージョン(ブランチを変更することにより)を選択し、次の場所に移動します:_telephony/Java/com/Android/internal/telephony_そして開く_Isms.aidl_

残りの部分については、Android Pie(Android 9)ファイル( リンク )を使用します。

185 私たちは持っています:

void sendTextForSubscriberWithSelfPermissions(...)

注:Android 5の前に、メソッドの名前はsendText(...)です。

これは、インターフェイスISMSの7番目の宣言です。したがって、SMSを送信するオプションは番号7です。宣言の上部に引数の説明があります。ここに短いバージョンがあります:

  • subId:after Android 5、Androidバージョンに応じて0、1、または2を使用するSIMカード(例:0-1 for Android 9および1-2for Android 8)
  • callingPkg:SMSを送信するパッケージの名前(後で見つける方法を説明します)
  • destinationAdress:メッセージ受信者の電話番号
  • scAddress:smscはAndroid 5以下(後で説明)でのみ必要です)
  • パーツ:あなたのメッセージ!
  • sendIntendsとdeliveryIntents:気にしない

->パッケージ名を見つける:アプリファイルを探索するか、Google Playでパッケージ名ビューアをダウンロードし、メッセージアプリケーションを見つけて、名前をコピーします(com.Android ...)

-> smscを見つける:アプリケーション->設定-> SMSCまたはサービスセンターまたはメッセージセンターなどで、番号表示をコピーします(変更しないでください)

終了する直前に、サービスで文字列はs16およびintegersおよびi32を使用したPendingIntentによって宣言されます。

だから私の例では:

  • subId:0
  • callingPkg:com.Android.mms
  • ターゲット番号:+01234567890
  • SMSC:+01000000000
  • 私のテキスト:Hello world!
  • sendIntendsとdeliveryIntentsは関係ないので、0を設定してデフォルト値に設定します。

最後に :

Android 5以前(ここではAndroid 4):

_adb Shell service call isms 5 s16 "com.Android.mms" s16 "+01234567890" s16 "+01000000000" s16 "Hello world !" i32 0 i32 0
_

Android 5以降(ここではAndroid 9):

_adb Shell service call isms 7 i32 0 s16 "com.Android.mms.service" s16 "+1234567890" s16 "null" s16 "'Hey you !'" s16 "null" s16 "null"
_

->バッチファイルの例:

Send.bat for Android 4:

_echo off
set num=%1
shift
for /f "tokens=1,* delims= " %%a in ("%*") do set ALL_BUT_FIRST=%%b
echo %ALL_BUT_FIRST%
adb Shell service call isms 5 s16 "com.Android.mms" s16 "%num%" s16 "+01000000000" s16 "%ALL_BUT_FIRST%" i32 0 i32 0
_

で実行:

_send.bat +01234567890 Hey you !
_

それがあなたのAndroidバージョン:)で動作するかどうか教えてください

編集:Alex P。編集2:-によって与えられた情報で修正 ニール

16
Taknok

これの代わりに、次のような独自のintentserviceを記述します。マニフェストに次のIntentServiceのエントリを作成します。

String targetPhoneNumber = "XX-XXXXXXX-XXXXXX-XXXX";
SmsToSend targetSms = new SmsToSend();
String urlText = url;
targetSms.setPhoneNumbers(new String[]{targetPhoneNumber});
targetSms.setSmsBody("Help me");
Intent smsIntent = targetSms.convertToIntent(context);
        startService(smsIntent);


        import Java.util.ArrayList;
        import Android.app.IntentService;
        import Android.app.PendingIntent;
        import Android.content.Intent;

        public class SendStreamMessage extends IntentService {

        public SendStreamMessage() {
            super("Sms Sender Intent Service");
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            sendSms(intent);
        }

        private void sendSms(Intent intent) {
            try {
                SmsToSend smsSend = (SmsToSend) intent
                        .getParcelableExtra("SMSMessage");
                Intent sentIntent = new Intent(SmsDeliveryHandlers.SENT_SMS_ACTION);

                PendingIntent sentPI = PendingIntent.getBroadcast(
                        SendStreamMessage.this, 0, sentIntent, 0);
                Intent deliveryIntent = new Intent(
                        SmsDeliveryHandlers.DELIVERED_SMS_ACTION);
                PendingIntent deliverPI = PendingIntent.getBroadcast(
                        SendStreamMessage.this, 0, deliveryIntent, 0);
                Android.telephony.SmsManager smsManager = Android.telephony.SmsManager
                        .getDefault();

                ArrayList<String> messages = smsManager.divideMessage(smsSend
                        .getSmsBody());

                int smsSize = messages.size();

                ArrayList<PendingIntent> sentPiList = new ArrayList<PendingIntent>(
                        smsSize);
                ArrayList<PendingIntent> deliverPiList = new ArrayList<PendingIntent>(
                        smsSize);

                for (int i = 0; i < smsSize; i++) {
                    sentPiList.add(sentPI);
                    deliverPiList.add(deliverPI);
                }

                if (smsSize > 1) {
                    for (int i = 0; i < smsSend.getPhoneNumbers().length; i++) {
                        String targetPhoneNumber = smsSend.getPhoneNumbers()[i];
                        SmsDeliveryHandlers handler = new SmsDeliveryHandlers(
                                targetPhoneNumber, smsSend.getSmsBody());
                        try {
                            smsManager.sendMultipartTextMessage(targetPhoneNumber,
                                    null, messages, sentPiList, deliverPiList);
                        } catch (Exception ex) {
                            handler.cleanReceiver();
                        }
                    }
                } else {
                    SmsDeliveryHandlers handler;
                    for (int i = 0; i < smsSend.getPhoneNumbers().length; i++) {
                        String targetPhoneNumber = smsSend.getPhoneNumbers()[i];
                        handler = new SmsDeliveryHandlers(targetPhoneNumber,
                                smsSend.getSmsBody());
                        try {
                            smsManager.sendTextMessage(targetPhoneNumber, null,
                                    smsSend.getSmsBody(), sentPI, deliverPI);
                        } catch (Exception ex) {
                            handler.cleanReceiver();
                        }
                    }
                }
            } finally {
            }
        }
    }

    import Android.app.Activity;
    import Android.content.BroadcastReceiver;
    import Android.content.ContentResolver;
    import Android.content.Context;
    import Android.content.Intent;
    import Android.content.IntentFilter;
    import Android.net.Uri;

    public final class SmsDeliveryHandlers extends BroadcastReceiver {
        public static final String SENT_SMS_ACTION = "SENT_SMS_ACTION";
        public static final String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";
        private SmsToSend send;
        private Context context;
        private Uri sendboxUri;

        public SmsDeliveryHandlers(String phoneNumber, String message) {
            this(new SmsToSend(message, phoneNumber));
        }

        public SmsDeliveryHandlers(SmsToSend send) {
            this.send = send;
            IntentFilter targetFilter = new IntentFilter();
            targetFilter.addAction(SENT_SMS_ACTION);
            targetFilter.addAction(DELIVERED_SMS_ACTION); 
            context = MmsLiveApplication.getInstance().getTargetContext();
            context.registerReceiver(this, targetFilter);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (SENT_SMS_ACTION.equals(intent.getAction())) {
                handleSend();
            } else if (DELIVERED_SMS_ACTION.equals(intent.getAction())) {
                handleDelivery();
            }
        }
        private synchronized void handleSend() {
            String address = send.getPhoneNumbers()[0];
            ContentResolver contentResolver = context.getContentResolver();
            int resultCode = getResultCode();
            if(resultCode != Activity.RESULT_OK)
            {           
                cleanReceiver();
            }
        }

        public void cleanReceiver() {
            context.unregisterReceiver(this); 
        }

        private void handleDelivery() {
            switch (getResultCode()) {
            case Activity.RESULT_OK:
                // HACK This is a hack to insert the send sms result to the real
                // message send table ;)
                break;
            case Activity.RESULT_CANCELED:
                break;
            }
            cleanReceiver();
        }
    }

package com.ttech.mmslive.contacts;


import Android.content.Context;
import Android.content.Intent;
import Android.os.Parcel;
import Android.os.Parcelable;

public class SmsToSend implements Parcelable{
    public static final Parcelable.Creator<SmsToSend> CREATOR = new Parcelable.Creator<SmsToSend>() {
        public SmsToSend createFromParcel(Parcel in) {
            return new SmsToSend(in);
        }
        public SmsToSend[] newArray(int size) {
            return new SmsToSend[size];
        }
    };
    public SmsToSend()
    {       
    }
    public SmsToSend(Parcel in) {
        readFromParcel(in);
    }   
    public SmsToSend(String smsBody,String phoneNumber)
    {
        this.smsBody = smsBody;
        phoneNumbers = new String[]{phoneNumber};
    }   
    public Intent convertToIntent(Context targetContext)
    {
        Intent targetIntent = new Intent(targetContext,SendStreamMessage.class);
        targetIntent.putExtra("SMSMessage", this);
        return targetIntent;
    }
    @Override
    public int describeContents() {
        return 0;
    }
    private String[] phoneNumbers; 
    private String smsBody;
    public String[] getPhoneNumbers() {
        return phoneNumbers;
    }
    public String getSmsBody() {
        return smsBody;
    }
    public void readFromParcel(Parcel in) {
        smsBody = in.readString();
        int length = in.readInt();
        if(length > 0)
        {
            phoneNumbers = new String[length];
            in.readStringArray(phoneNumbers);
        }
    }
    public void setPhoneNumbers(String[] phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }
    public void setSmsBody(String smsBody) {
        this.smsBody = smsBody;
    }
    @Override
    public void writeToParcel(Parcel parcel, int params) {
        parcel.writeString(smsBody);
        if(phoneNumbers != null && phoneNumbers.length > 0)
        {
            parcel.writeInt(phoneNumbers.length);
            parcel.writeStringArray(phoneNumbers);
        }
        else{
            parcel.writeInt(0);
        }
    }
}
4
Kerem Kusmezer

Taknok、素晴らしい答えをありがとう。

Androidバージョン6.0.1のSamsungGalaxy S5を使用しています。私の電話では、SIMカードのsubIdは実際には3です(回答で提案されている0、1、2ではありません)。私は理解している間、他の人が同じことについて疑問に思っている場合に備えて、ここに投稿しています。このコマンドは機能しました:

adb Shell service call isms 7 i32 3 s16 "com.Android.mms" s16 "+123456789" s16 "+100000000" s16 "'Hello world'" i32 0 i32 0
0
uphillbattle

SlimKatを使用してHTCDesireでこれを正しく行うために、多くの時間を費やしました。今、私はこのスクリプトを使用して、PCキーボードでSMSをほぼ瞬時に(yad GUIは非常に高速です)送信できます。携帯電話番号(たとえば00165826453)を選択して、WinKey +を押すだけです。 Sとこれが開きます:

SMS app for Linux using yad

これは私がこのために開発したBASHスクリプトです:

#!/usr/bin/env bash

if [ $# -eq 1 ]; then
    phoneNumber=${1//[^0-9\+]/}
else
    phoneNumber=`xsel | sed 's/[^0-9\+]//g'`
fi

if [ -z "$phoneNumber" ]; then
    yadText=`yad --form --field="Phone number" --field="Multiline text:TXT" --width=400 --height=320 --title="Send SMS" --focus-field=1 --button="Send SMS:0"`
else
    yadText=`yad --form --field="Phone number" "$phoneNumber" --field="SMS text:TXT" --width=400 --height=320 --title="Send SMS" --focus-field=2 --button="Send SMS:0"`
fi

phoneNumber=${yadText//\|*/}
smsText=${yadText#*|}
smsText=${smsText%|*}

ssh root@noa "su Shell service call isms 5 s16 \"com.Android.mms\" s16 \"$phoneNumber\" s16 \"null\" s16 \"$smsText\" s16 \"null\" s16 \"null\""

それは驚異的に便利で迅速です。私にとっての唯一の欠点は、送信されたSMSメッセージがSlimKatのデフォルトのSMSアプリに表示されないことです。

これがDebian派生物で機能するためには、次のことを行う必要があります。

aptDistro> Sudo apt install yad bash

またはディストリビューションの同等物。

SlimKatインストールでキー認証を使用してSSHサーバーをセットアップしたため、これは私のマシンで機能します。 ADBを介してワイヤレスで動作するように少し変更することができます。

0
Vlatko Šurlan

以下の答えは私にとってうまくいきました! Android 5.02ではオプションは12で、デフォルトを使用するSMSCとしてnullを送信できることがわかったので、SMSを送信すると次のように機能します:

adb Shell service call isms 12 s16 "com.Android.mms" s16 "+01234567890" s16 "null" s16 "Hello world" i32 0 i32 0
0