3

Im trying to send a SMS message from my own app using 'sendTextMessage' or 'sendMultipartTextMessage'. For phones higher then API 19 (KitKat) this message is then saved to the sent folder. However on my Android 8.0 Oreo Phone it is not saving to the sent items.

I have created a very basic Test Application for purposes of posting here. This App will simply check permissions and send a text when the Resume function fires for the MainActivity. Here is the code.

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.focus4software.www.myapplicationtest">

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

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

Build.Grade

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.focus4software.www.myapplicationtest2"
        minSdkVersion 14
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

MainActivity:

package com.focus4software.www.myapplicationtest;

import android.Manifest;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Telephony;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_RESULTCODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onResume(){
        super.onResume();


        //Check Permissions first
        if (android.os.Build.VERSION.SDK_INT >= 23) {
            if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
                //Permissions not found..  request them
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.SEND_SMS}, REQUEST_RESULTCODE);
            }
            else {
                this.SendSMS();
            }
        }
        else {
            this.SendSMS();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_RESULTCODE: {
                if (grantResults.length == 1) {
                    //Make sure none of the permissions were denied
                    boolean somethingDenied = false;
                    for (int result : grantResults){
                        if (result != PackageManager.PERMISSION_GRANTED){
                            somethingDenied = true;
                        }
                    }

                    if (somethingDenied){
                        //a permission was denied
                        Toast.makeText(getApplicationContext(), "Failed to Send The TEST SMS, Permission was denied", Toast.LENGTH_SHORT).show();
                    }
                    else {
                        //turn the app on.. permissions accepted
                        this.SendSMS();
                    }
                }
                else {
                    Toast.makeText(getApplicationContext(), "Failed to Send The TEST SMS, incorrect amount of permissions returned.", Toast.LENGTH_SHORT).show();
                }
                return;
            }
        }
    }

    private void SendSMS (){
        String phone = "[INSERT PHONE NUMBER]";
        String message = "InCodeTestExtra";

        //send sms
        SmsManager sms = SmsManager.getDefault();
        sms.sendTextMessage(phone, null, message, null, null);

        //Show we got here
        Toast.makeText(getApplicationContext(), "Code Executed...  SMS Passed on.", Toast.LENGTH_SHORT).show();

        //Save SMS
        //this.SaveSMS(getApplicationContext(), phone, message);
    }

    private void SaveSMS(Context inContext, String inAddress, String inBody) {
        try {
            ContentValues values = new ContentValues();
            values.put("address", inAddress);
            values.put("body", inBody);
            values.put("read", 1);
            values.put("date", System.currentTimeMillis());
            //values.put("status", delivered);

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                Uri uri = Telephony.Sms.Sent.CONTENT_URI;
                inContext.getApplicationContext().getContentResolver().insert(uri, values);
            }
            else {
                inContext.getApplicationContext().getContentResolver().insert(Uri.parse("content://sms/sent"), values);
            }

            //notify of the save
            Toast.makeText(getApplicationContext(), "SMS SAVED (Maybe)", Toast.LENGTH_SHORT).show();
        } catch (Exception ex) {
            //notify of the Failure
            Toast.makeText(getApplicationContext(), "SMS Failed to save (" + ex.getMessage() + ")", Toast.LENGTH_SHORT).show();
        }
    }
}

As Mentioned this is not saving the Message to the Send folder for my Android Oreo Phone.

According the the Android documentation this is meant to happen.

Note: Beginning with Android 4.4 (API level 19), if and only if an app is not selected as the default SMS app, the system automatically writes messages sent using this method to the SMS Provider (the default SMS app is always responsible for writing its sent messages to the SMS Provider). For information about how to behave as the default SMS app, see Telephony.

As a workaround I tried to save the message manually. At the bottom of the SendSMS function this is commented out. However running this code did not cause an exception but did not save the SMS to the send folder either. This also works fine on older phones. I am unsure if this is a related issue.

Am I missing anything here?? Can anyone help? :)

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • Does the message send successfully? That is, does the recipient actually get it? What is the make/model of the phone you're testing on? – Mike M. Jul 26 '18 at 11:42
  • Yes the message sends fine. it is just not in the sent folder after. I'm using a Huawei Honor 9 as test. – Nick Hayward Jul 26 '18 at 11:58
  • Well, I would have to say this particular issue is specific to that model, inasmuch as I've not heard of that exact behavior for any others. There was a bug in 8.0 that would throw a `SecurityException` if an app didn't hold the `READ_PHONE_STATE` permission as well, but I wouldn't think this is a manifestation of that, since that Exception should break the whole send, and is not silent. The only other vaguely similar issue I've heard of was reportedly solved by passing the send and delivery `PendingIntent`s in that method, but that was a custom ROM. Long shots, but you might give 'em a try. – Mike M. Jul 26 '18 at 12:38
  • 1
    I will have a go at trying this on another model. Will have to hunt one down and ill update here when I have. In regards to the READ_PHONE_STATE and using the Pending Intents, this issue has been taken from a much bigger app that uses 'sendMultipartTextMessage' while having that permission and passing in the intents and the issue still persists. I will go down the road of trying other devices with android 8.0 installed and see what happens. I will also try this out on some emulators to see if it happens there. Ill update here when I have, thanks for the tips :):) – Nick Hayward Jul 26 '18 at 13:50
  • I have the same problem with HUAWEI Honor ... – rafaelphp Jun 28 '19 at 14:33

1 Answers1

1

Just thought id update this thread to what i found.

It SEEMS that Mike M was correct in that this is specific to certain models. I was using the Honor 9 and another stack overflow user had similar issues with the p20 lite.. both Hwawei. I did many many tests on many many models that were not Hwawei and never managed to replicate the issue.

As mentioned in my question, using code to manually save the SMS if it is not present also failed to save the sms… Perhaps this works for other users in this situation.

The only workaround I found that worked was to show the SMS Activity and let the user send the sms themselves. Downside is it requires user input and you simply populate the SMS Activity for them to send the message. Heres a usefull Link on how to do that: launch sms application with an intent

For people with similar issues it could be possible to only Popup the SMS Activity Certain models with some funky code.. or detect if this issue is present by trying to save a dummy sms and seeing if it worked (remember to remove it if it did work).. and if it failed show the SMS activity ….

IMO every workaround is uncomfortably messy and i'm open to any suggestions anyone has. : )