Android开发 day12

1. ContentObserver

内容观察器ContentObserver给目标内容注册一个观察器,目标内容的数据一旦发生变化,观察器规定好的动作马山触发,从而执行开发者预先定义的代码。

 代码示例(利用ContentObserver监听短信)

public class MonitorSmsActivity extends AppCompatActivity {
    private SmsGetObserver mObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_monitor_sms);
        //给指定uri注册内容观察器,一旦发生数据变化,就触发观察器的onChange方法
        Uri uri = Uri.parse("content://sms");
        // notifyForDescendents:
        // false :表示精确匹配,即只匹配该Uri,true :表示可以同时匹配其派生的Uri
        // 假设UriMatcher 里注册的Uri共有一下类型:
        // 1.content://AUTHORITIES/table
        // 2.content://AUTHORITIES/table/#
        // 3.content://AUTHORITIES/table/subtable
        // 假设我们当前需要观察的Uri为content://AUTHORITIES/student:
        // 如果发生数据变化的 Uri 为 3。
        // 当notifyForDescendents为false,那么该ContentObserver会监听不到,但是当notifyForDescendents 为ture,能捕捉该Uri的数据库变化。
        mObserver = new SmsGetObserver(this);
        getContentResolver().registerContentObserver(uri, true, mObserver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getContentResolver().unregisterContentObserver(mObserver);
    }

    private static class SmsGetObserver extends ContentObserver{

        private final Context mContext;


        public SmsGetObserver(Context context) {
            super(new Handler(Looper.getMainLooper()));
            this.mContext = context;
        }
        @SuppressLint("Range")
        @Override
        public void onChange(boolean selfChange, @Nullable Uri uri) {
            super.onChange(selfChange,uri);
            // onChange会多次调用,收到一条短信会调用两次onChange
            // mUri===content://sms/raw/20
            // mUri===content://sms/inbox/20
            // 安卓7.0以上系统,点击标记为已读,也会调用一次
            // mUri===content://sms
            // 收到一条短信都是uri后面都会有确定的一个数字,对应数据库的_id,比如上面的20
            if (uri == null) {
                return;
            }
            if (uri.toString().contains("content://sms/raw") ||
                    uri.toString().equals("content://sms")) {
                return;
            }

            Cursor cursor = mContext.getContentResolver().query(uri, new String[]{"address", "body", "date"}, null, null, "date DESC");
            if(cursor.moveToNext()){
                String sender = cursor.getString(cursor.getColumnIndex("address"));
                String body = cursor.getString(cursor.getColumnIndex("body"));

                Log.d("lzk", "onChange: "+sender+" "+body);
            }
            cursor.close();
        }
    }
}

2. 使用图片发送彩信

public class SendMmsActivity extends AppCompatActivity implements View.OnClickListener {
    private ImageView iv_appendix;
    private ActivityResultLauncher<Intent> mResultLauncher;
    private EditText et_phone;
    private EditText et_title;
    private EditText et_message;
    private Uri picUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_send_mms);
        iv_appendix = findViewById(R.id.iv_appendix);
        et_phone = findViewById(R.id.et_phone);
        et_title = findViewById(R.id.et_title);
        et_message = findViewById(R.id.et_message);
        iv_appendix.setOnClickListener(this);
        findViewById(R.id.btn_send_mms).setOnClickListener(this);
        mResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {
                if(result.getResultCode()==RESULT_OK){
                    Intent intent = result.getData();
                    if(intent!=null){
                        //获取选择的图片
                         picUri= intent.getData();
                       if(picUri!=null){
                           iv_appendix.setImageURI(picUri);
                           Log.d("lzk", "onActivityResult: "+picUri);
                       }
                    }
                }

            }
        });

    }

    @Override
    public void onClick(View view) {
        if(view.getId() == R.id.iv_appendix){
            //跳转到系统相册,选择图片,并返回
            Intent intent=new Intent(Intent.ACTION_GET_CONTENT);
            //设置内容为图片
            intent.setType("image/*");

            mResultLauncher.launch(intent);


        }else if(view.getId() == R.id.btn_send_mms){
            sendMms(et_phone.getText().toString(),
                    et_title.getText().toString(),
                    et_message.getText().toString());
        }

    }

    private void sendMms(String phone, String title, String message) {
        Intent intent=new Intent(Intent.ACTION_SEND);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        // 彩信发送的目标号码
        intent.putExtra("address", phone);
        // 彩信的标题
        intent.putExtra("subject", title);
        // 彩信的内容
        intent.putExtra("sms_body", message);
        // 彩信的图片附件
        intent.putExtra(Intent.EXTRA_STREAM, picUri);
        // 彩信的附件为图片
        intent.setType("image/*");
        startActivity(intent);
        ToastUtil.show(this,"请在弹窗中选择短信或者信息应用");


    }
}

3.FileProvider

public class ProviderMmsActivity extends AppCompatActivity {
    private static final String[] PERMISSIONS = new String[]{
            Manifest.permission.READ_EXTERNAL_STORAGE
    };
    private EditText et_phone;
    private EditText et_title;
    private EditText et_message;
    private static final int PERMISSION_REQUEST_CODE = 1;
    private List<ImageInfo> mImageList = new ArrayList<>();
    private GridLayout gl_appendix;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        et_phone = findViewById(R.id.et_phone);
        et_title = findViewById(R.id.et_title);
        et_message = findViewById(R.id.et_message);
        setContentView(R.layout.activity_provider_mms);
        gl_appendix = findViewById(R.id.gl_appendix);
        //手动让MediaStore扫描入库
        //手动让MediaStore扫描入库
        MediaScannerConnection.scanFile(this,
                new String[]{Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()},
                null, null);

        if(PermissionUtil.checkPermission(this,PERMISSIONS,PERMISSION_REQUEST_CODE)){
            //加载图片列表
            loadImageList();
            showImageGrid();
        }
    }
    private void sendMms(String phone, String title, String message,String path) {
        Uri uri=Uri.parse(path);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // 通过FileProvider获得文件的Uri访问方式
            uri = FileProvider.getUriForFile(this, getString(R.string.file_provider), new File(path));
            Log.d("ning", String.format("new uri:%s", uri.toString()));
        }
        Intent intent=new Intent(Intent.ACTION_SEND);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        // 彩信发送的目标号码
        intent.putExtra("address", phone);
        // 彩信的标题
        intent.putExtra("subject", title);
        // 彩信的内容
        intent.putExtra("sms_body", message);
        // 彩信的图片附件
        intent.putExtra(Intent.EXTRA_STREAM,uri);
        // 彩信的附件为图片
        intent.setType("image/*");
        startActivity(intent);
        ToastUtil.show(this,"请在弹窗中选择短信或者信息应用");
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode == PERMISSION_REQUEST_CODE&&
                PermissionUtil.checkGrant(grantResults)){
            loadImageList();
            showImageGrid();
        }
    }

    private void showImageGrid() {
        gl_appendix.removeAllViews();
        for (ImageInfo imageInfo : mImageList) {
            ImageView imageView = new ImageView(this);
            Bitmap bitmap = BitmapFactory.decodeFile(imageInfo.path);
            imageView.setImageBitmap(bitmap);
            imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
            int px = Utils.dip2px(this, 110);
            ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(px, px);
            imageView.setLayoutParams(params);
            int padding=Utils.dip2px(this, 5);
            imageView.setPadding(padding,padding,padding,padding);
            imageView.setOnClickListener(v -> {
                 sendMms(et_phone.getText().toString(),
                         et_title.getText().toString(),
                         et_message.getText().toString(),
                         imageInfo.path);
            });
            gl_appendix.addView(imageView);
        }
    }

    @SuppressLint("Range")
    //加载图片列表
    private void loadImageList() {
        String[] columns = new String[]{
                MediaStore.Images.Media._ID,
                MediaStore.Images.Media.TITLE,
                MediaStore.Images.Media.DATA,
                MediaStore.Images.Media.SIZE,
        };
        //300kb以内的图片
        Cursor cursor = getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                columns,
                "_size<307200",
                null,
                "_size DESC"
        );
        int count = 0;
        if (cursor != null) {
            while (cursor.moveToNext() && count < 6) {
                ImageInfo image = new ImageInfo();
                image.id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID));
                image.name = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.TITLE));
                image.path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                image.size = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.SIZE));
                if(FileUtil.checkFileUri(this,image.path)){
                    count++;
                    mImageList.add(image);
                    Log.d("lzk", image.toString());
                }
            }
        }
    }
}

4. APK文件应用安装

public class ProviderApkActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String[] PERMISSIONS = new String[]{
            Manifest.permission.READ_EXTERNAL_STORAGE
    };
    private static final int PERMISSION_REQUEST_CODE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_provider_apk);
        findViewById(R.id.btn_install).setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
            checkAndInstall();
        }else{
            if(PermissionUtil.checkPermission(this, PERMISSIONS, PERMISSION_REQUEST_CODE)){
                installApk();
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode==PERMISSION_REQUEST_CODE&&PermissionUtil.checkGrant(grantResults)){
            installApk();
        }
    }
    @RequiresApi(api=Build.VERSION_CODES.R)
    private void checkAndInstall() {
        if(!Environment.isExternalStorageManager()){
            Intent intent=new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setData(Uri.fromParts("package",getPackageName(),null));
            startActivity(intent);
        }else{
            installApk();
        }
    }
    private void installApk() {
        String apkPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/chapter06-release.apk";

        PackageManager pm = getPackageManager();
        PackageInfo pi = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES);
        if(pi==null){
            ToastUtil.show(this,"安装文件已经损坏");
            return;
        }
        Uri uri = Uri.parse(apkPath);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // 通过FileProvider获得文件的Uri访问方式
            uri = FileProvider.getUriForFile(this, getString(R.string.file_provider), new File(apkPath));
            Log.d("ning", String.format("new uri:%s", uri.toString()));
        }
        Intent intent=new Intent(Intent.ACTION_SEND);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
        startActivity(intent);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值