I already have an activity in my app that sends an SMS message so I thought it would be easy to copy some code across to another activity, but no! I am trying to put two buttons on MainActivity to send pre-written SMS messages. The full MainActivity.java is:
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import android.telephony.SmsManager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private int MY_PERMISSIONS_REQUEST_SMS_RECEIVE = 10;
private int MY_PERMISSIONS_REQUEST_SMS_SEND = 20;
Button button_8;
Button button_9;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkPermission();
}
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
button_8 = findViewById(R.id.availability_8);
button_8.setOnClickListener(view -> sendSMS8());
button_9 = findViewById(R.id.availability_9);
button_9.setOnClickListener(view -> sendSMS9());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_most_recent_tasking:
Intent intent1 = new Intent(this, ShoutActivity.class);
startActivity(intent1);
break;
case R.id.action_settings:
Intent intent2 = new Intent(this, SettingsActivity.class);
startActivity(intent2);
break;
case R.id.action_about:
Intent intent3 = new Intent(this, AboutActivity.class);
startActivity(intent3);
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
protected void sendSMS8() {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(getString(R.string.at_number), null, "8", null, null);
Toast.makeText(getApplicationContext(), R.string.a_sent,
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), R.string.a_failed,
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
protected void sendSMS9() {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(getString(R.string.at_number), null, "9", null, null);
Toast.makeText(getApplicationContext(), R.string.a_sent,
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), R.string.a_failed,
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
public void checkPermission() {
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED)) {
requestPermissions(new String[]{Manifest.permission.RECEIVE_SMS}, MY_PERMISSIONS_REQUEST_SMS_RECEIVE);
}
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED)) {
requestPermissions(new String[]{Manifest.permission.SEND_SMS}, MY_PERMISSIONS_REQUEST_SMS_SEND);
}
}
}
The AndroidManifest file includes
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
and
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/Theme.CgPager.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I just cannot see why this is not working. (Each time I run it, the toast reports "Availability failed to send" ie string.a_failed.
For comparison, this code is working on another activity:
protected void sendSMS1() {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(getString(R.string.at_number), null, "1", null, null);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean partner_text = sharedPreferences.getBoolean("partner", false);
if(partner_text){
String text_message = sharedPreferences.getString("partner_textmessage", "");
String partner_telno = sharedPreferences.getString("partner_phone", "");
smsManager.sendTextMessage(partner_telno, null, text_message, null, null);
}
Intent intent = getIntent();
String shoutContent = intent.getStringExtra(ReceiveAlertActivity.EXTRA_MESSAGE);
Intent secondintent = new Intent(this, ShoutActivity.class);
secondintent.putExtra(MESSAGE, shoutContent);
startActivity(secondintent);
Toast.makeText(getApplicationContext(), R.string.r_sent,
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), R.string.r_failed,
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
UPDATE
The code you wrote shows that the android.Manifest.permission.RECEIVE_SMS
permission is obtained when you open the file for the first time, not the permission to send SMS messages.
The android.Manifest.permission.SEND_SMS permission
is obtained only when you open the file for the second time.
The solution is to add the callback method (onRequestPermissionsResult
) of the request permission result. The next permission can be applied only after the callback method is executed for multiple times.
The following provides a simple solution to this problem by implementing the onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
method.
a. Obtain the permission in the Activity.
The following is a complex method of obtaining permissions in batches. The following is an example.
a. Add the permission to be dynamically obtained to the AndroidManifest.xml file.
b. Obtain permissions in batches in Activity:
c. Perform the processing after obtaining the permission in the onRequestPermissionsResult
method.
You are advised to view the logs about SMS message sending failures to locate the cause. You can view logs on the Android Studio console. The filtering field is SMS.
For example, if you do not have the permission to send SMS messages, the following log is generated when the code for sending SMS messages is invoked:
You can also change the Msg in the Toast message so that you can view the cause of the SMS message sending failure through the Toast message.
Toast Msg can be changed to ""+e.getMessage()
Error message:
Take a Huawei phone as an example. After the app obtains the permission to send SMS messages, a warning dialog box is displayed when you send the message for the first time, as shown in the following figure.
so It's recommended that you to view the logs to find the cause of the failure to send SMS messages.