Android6.0以上需要添加运行时权限,为了方便处理,将它们归于一个类,需要调用权限时使用就好
BaseActivity.java
package com.example.aimee.sendmessage; import android.content.DialogInterface; import android.content.pm.PackageManager; import android.os.Build; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.widget.Toast; /** * @author Admin * @version $Rev$ * @des ${TODO} * @updateAuthor $Author$ * @updateDes ${TODO} */ public class BaseActivity extends AppCompatActivity { //**************** Android M Permission (Android 6.0权限控制代码封装) private int permissionRequestCode = 88; private PermissionCallback permissionRunnable; public interface PermissionCallback { void hasPermission(); void noPermission(); } /** * Android M运行时权限请求封装 * * @param permissionDes 权限描述 * @param runnable 请求权限回调 * @param permissions 请求的权限(数组类型),直接从Manifest中读取相应的值,比如Manifest.permission.WRITE_CONTACTS */ public void performCodeWithPermission(@NonNull String permissionDes, PermissionCallback runnable, @NonNull String... permissions) { if (permissions == null || permissions.length == 0) return; // this.permissionrequestCode = requestCode; this.permissionRunnable = runnable; if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M) || checkPermissionGranted(permissions)) { if (permissionRunnable != null) { permissionRunnable.hasPermission(); permissionRunnable = null; } } else { //permission has not been granted. requestPermission(permissionDes, permissionRequestCode, permissions); } } private boolean checkPermissionGranted(String[] permissions) { boolean flag = true; for (String p : permissions) { if (ActivityCompat.checkSelfPermission(this, p) != PackageManager.PERMISSION_GRANTED) { flag = false; break; } } return flag; } private void requestPermission(String permissionDes, final int requestCode, final String[] permissions) { if (shouldShowRequestPermissionRationale(permissions)) { /*1. 第一次请求权限时,用户拒绝了,下一次:shouldShowRequestPermissionRationale() 返回 true,应该显示一些为什么需要这个权限的说明 2.第二次请求权限时,用户拒绝了,并选择了“不在提醒”的选项时:shouldShowRequestPermissionRationale() 返回 false 3. 设备的策略禁止当前应用获取这个权限的授权:shouldShowRequestPermissionRationale() 返回 false*/ // Provide an additional rationale to the user if the permission was not granted // and the user would benefit from additional context for the use of the permission. // For example, if the request has been denied previously. // Snackbar.make(getWindow().getDecorView(), requestName, // Snackbar.LENGTH_INDEFINITE) // .setAction(R.string.common_ok, new View.OnClickListener() { // @Override // public void onClick(View view) { // ActivityCompat.requestPermissions(BaseAppCompatActivity.this, // permissions, // requestCode); // } // }) // .show(); //如果用户之前拒绝过此权限,再提示一次准备授权相关权限 new AlertDialog.Builder(this) .setTitle("提示") .setMessage(permissionDes) .setPositiveButton("授权", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode); } }).show(); } else { // Contact permissions have not been granted yet. Request them directly. ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode); } } private boolean shouldShowRequestPermissionRationale(String[] permissions) { boolean flag = false; for (String p : permissions) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, p)) { flag = true; break; } } return flag; } /** * Callback received when a permissions request has been completed. */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == permissionRequestCode) { if (verifyPermissions(grantResults)) { if (permissionRunnable != null) { permissionRunnable.hasPermission(); permissionRunnable = null; } } else { Toast.makeText(this, "暂无权限执行相关操作!", Toast.LENGTH_SHORT).show(); if (permissionRunnable != null) { permissionRunnable.noPermission(); permissionRunnable = null; } } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } public boolean verifyPermissions(int[] grantResults) { // At least one result must be checked. if (grantResults.length < 1) { return false; } // Verify that each required permission has been granted, otherwise return false. for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } //********************** END Android M Permission **************************************** }
但是值得注意的是,不要忘记在Manifest中添加相应的权限。
发送短信需要的权限是
<uses-permission android:name="android.permission.SEND_SMS"/>
界面设计的代码就不写了,自行设计。主要是两个编辑文本和一个发送Button
MainActivity.java
package com.example.aimee.sendmessage; import android.Manifest; import android.os.Bundle; import android.telephony.SmsManager; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends BaseActivity { private EditText mEtPhone; private EditText mEtMessage; private Button mBtSend; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //1.获取到界面上的控件et_phone mEtPhone = findViewById(R.id.et_phone); //2.获取到界面上的控件et_message mEtMessage = findViewById(R.id.et_message); //3.获取到见面上的控件bt_send,并设置监听 mBtSend = findViewById(R.id.bt_send); mBtSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String phoneNum = mEtPhone.getText().toString().trim();//trim final String message = mEtMessage.getText().toString().trim(); if ("".equals(phoneNum) || "".equals(message)){ Toast.makeText(MainActivity.this,"号码和内容不能为空",Toast.LENGTH_SHORT).show(); return; } System.out.println(phoneNum + ":" + message); performCodeWithPermission("发送短信权限", new PermissionCallback() { @Override public void hasPermission() { SmsManager smsManager = SmsManager.getDefault(); smsManager.sendTextMessage(phoneNum, null,message,null,null); } @Override public void noPermission() { Toast.makeText(MainActivity.this,"未授权",Toast.LENGTH_SHORT).show(); } }, Manifest.permission.SEND_SMS); } }); } }
另外补充一个单元测试小知识:
ExampleUnitTest.java这个文件是每次新建项目的时候就有的,这个文件的作用是可以进行单元测试。
双击addition_isCorrect,右击run就会运行这部分代码
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
默认的是这个,因为4=2+2,所以不会报错,当你将后面改成3就会报错了,我们可以在下面写函数,然后放在这个函数里面调用,就可以实现单元测试了。
如果你写了一段代码,然后又想把它分离出去当做一个函数,可以使用ctrl+alt+m快捷键,第一个可以选择private,public.....第二个可以写准备取的函数名。
package com.aimee.android.play.junit; import android.content.Context; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; public class MainActivity extends AppCompatActivity { private EditText et_text; String text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_text = findViewById(R.id.et_text); writeFile();//ctrl+alt+m创建一个方法 readFile(); } private void readFile() { try { FileInputStream fis = openFileInput("file.txt"); File file = new File("file.txt"); text = file.getAbsolutePath(); byte[] bytes = new byte[20]; fis.read(bytes); et_text.setText(text); fis.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 写入文件 * */ private void writeFile() { //创建一个文件,程序自身可以读写 try { FileOutputStream fos = openFileOutput("file.txt", Context.MODE_PRIVATE); fos.write("data111".getBytes()); fos.close(); } catch (Exception e) { e.printStackTrace(); } } }
注意:一般android程序的默认安装位置是/data/data/包名,但是这个里面的文件是被保护的,不可以打开,所以如果想要看文件的内容,可以选择路径的时候getExternalFilesDir() 这个路径,它的路径一般是/storage/data/0/android/包名。