运行有问题或需要源码请点赞关注收藏后评论区留言~~~~
一、使用相册图片发送彩信
不同应用之间可以共享数据,当然也能共享文件,比如系统相册保存着用户拍摄的照片,这些照片理应分享给其他App使用。 下面通过利用相册图片发送彩信的例子讲解
代码
java类代码
package com.example.chapter07; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import androidx.appcompat.app.AppCompatActivity; import com.example.chapter07.util.ToastUtil; import com.example.chapter07.util.ViewUtil; public class SendMmsActivity extends AppCompatActivity implements View.OnClickListener { private final static String TAG = "SendMmsActivity"; private EditText et_phone; private EditText et_title; private EditText et_message; private ImageView iv_appendix; private Uri mUri; // 文件的路径对象 private int CHOOSE_CODE = 3; // 选择照片的请求码 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_send_mms); et_phone = findViewById(R.id.et_phone); et_title = findViewById(R.id.et_title); et_message = findViewById(R.id.et_message); iv_appendix = findViewById(R.id.iv_appendix); iv_appendix.setOnClickListener(this); findViewById(R.id.btn_send_mms).setOnClickListener(this); } @Override public void onClick(View v) { if (v.getId() == R.id.iv_appendix) { ViewUtil.hideOneInputMethod(this, et_message); // 隐藏输入法软键盘 // 创建一个内容获取动作的意图 Intent albumIntent = new Intent(Intent.ACTION_GET_CONTENT); albumIntent.setType("image/*"); // 设置内容类型为图像 startActivityForResult(albumIntent, CHOOSE_CODE); // 打开系统相册,并等待图片选择结果 } else if (v.getId() == R.id.btn_send_mms) { if (TextUtils.isEmpty(et_phone.getText())) { ToastUtil.show(this, "请填写对方号码"); return; } if (TextUtils.isEmpty(et_title.getText())) { ToastUtil.show(this, "请填写彩信标题"); return; } if (TextUtils.isEmpty(et_message.getText())) { ToastUtil.show(this, "请填写彩信内容"); return; } if (mUri == null) { ToastUtil.show(this, "请选择附件图片"); return; } // 发送带图片的彩信 sendMms(et_phone.getText().toString(), et_title.getText().toString(), et_message.getText().toString()); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if (resultCode == RESULT_OK && requestCode == CHOOSE_CODE) { // 从相册选择一张照片 if (intent.getData() != null) { // 数据非空,表示选中了某张照片 mUri = intent.getData(); // 获得选中照片的路径对象 iv_appendix.setImageURI(mUri); // 设置图像视图的路径对象 Log.d(TAG, "uri.getPath="+mUri.getPath()+",uri.toString="+mUri.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, mUri); // mUri为彩信的图片附件 intent.setType("image/*"); // 彩信的附件为图片 // 部分手机无法直接跳到彩信发送页面,故而需要用户手动选择彩信应用 //intent.setClassName("com.android.mms","com.android.mms.ui.ComposeMessageActivity"); startActivity(intent); // 因为未指定要打开哪个页面,所以系统会在底部弹出选择窗口 ToastUtil.show(this, "请在弹窗中选择短信或者信息应用"); } }
XML文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="对方号码:" android:textColor="@color/black" android:textSize="17sp" /> <EditText android:id="@+id/et_phone" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_margin="3dp" android:background="@drawable/editext_selector" android:inputType="number" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="彩信标题:" android:textColor="@color/black" android:textSize="17sp" /> <EditText android:id="@+id/et_title" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_margin="3dp" android:background="@drawable/editext_selector" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="100dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="彩信内容:" android:textColor="@color/black" android:textSize="17sp" /> <EditText android:id="@+id/et_message" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_margin="3dp" android:gravity="left|top" android:background="@drawable/editext_selector" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="top|center" android:text="图片附件:" android:textColor="@color/black" android:textSize="17sp" /> <ImageView android:id="@+id/iv_appendix" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:scaleType="fitStart" android:src="@drawable/add_pic"/> </LinearLayout> <Button android:id="@+id/btn_send_mms" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="发送彩信" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout>
二、借助FileProvider安装应用
除了发送彩信需要文件提供器,安装应用也需要FileProvider,不单单彩信的附件图片能到媒体库中查询,应用的APK安装包也可以在媒体库中找到,查看安装包依然借助于内容解析器。
通过系统相册固然可以获得照片的路径对象,但是却无法知晓更多的详细信息,例如照片名称,文件大小,文件路径等消息,也就无法进行个性化的定制开发,为了把更多的文件信息开放出来,Android设计了专门的媒体共享库,允许开发者通过内容组件从中获取更多详细的媒体信息。
有了安装包的文件路径之后,就能打开系统自带的安装程序执行安装操作了,此时一样要把安装包的Uri对象传进去
代码
Java类代码
package com.example.chapter07; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Color; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.FileProvider; import com.example.chapter07.bean.ApkInfo; import com.example.chapter07.util.FileUtil; import com.example.chapter07.util.ToastUtil; import com.example.chapter07.util.Utils; import java.io.File; import java.util.ArrayList; import java.util.List; public class ProviderApkActivity extends AppCompatActivity { private final static String TAG = "ProviderApkActivity"; private TextView tv_title; private LinearLayout ll_list; // 安装包列表的线性布局 private List<ApkInfo> mApkList = new ArrayList<ApkInfo>(); // 安装包列表 private Uri mFilesUri = MediaStore.Files.getContentUri("external"); // 存储卡的Uri private String[] mFilesColumn = new String[]{ // 媒体库的字段名称数组 MediaStore.Files.FileColumns._ID, // 编号 MediaStore.Files.FileColumns.TITLE, // 标题 MediaStore.Files.FileColumns.SIZE, // 文件大小 MediaStore.Files.FileColumns.DATA, // 文件路径 MediaStore.Files.FileColumns.MIME_TYPE}; // 媒体类型 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_provider_apk); tv_title = findViewById(R.id.tv_title); ll_list = findViewById(R.id.ll_list); loadApkList(); // 加载安装包列表 if (mApkList.size() == 0) { tv_title.setText("未找到任何apk文件"); } else { showApkList(); // 显示安装包列表 } } // 加载安装包列表 private void loadApkList() { mApkList.clear(); // 清空安装包列表 // 查找存储卡上所有的apk文件,其中mime_type指定了APK的文件类型,或者判断文件路径是否以.apk结尾 Cursor cursor = getContentResolver().query(mFilesUri, mFilesColumn, "mime_type=\"application/vnd.android.package-archive\" or _data like '%.apk'", null, null); if (cursor != null) { // 下面遍历结果集,并逐个添加到安装包列表。简单起见只挑选前十个文件 for (int i=0; i<10 && cursor.moveToNext(); i++) { ApkInfo apk = new ApkInfo(); // 创建一个安装包信息对象 apk.setId(cursor.getLong(0)); // 设置安装包编号 apk.setName(cursor.getString(1)); // 设置安装包名称 apk.setSize(cursor.getLong(2)); // 设置安装包的文件大小 apk.setPath(cursor.getString(3)); // 设置安装包的文件路径 Log.d(TAG, apk.getName() + ", " + apk.getSize() + ", " + apk.getPath()+", "+cursor.getString(4)); if (!FileUtil.checkFileUri(this, apk.getPath())) { // 检查该路径是否合法 i--; continue; // 路径非法则再来一次 } mApkList.add(apk); // 添加至安装包列表 } cursor.close(); // 关闭数据库游标 } } // 显示APK文件列表 private void showApkList() { for (int i=0; i<mApkList.size(); i++) { final ApkInfo apkInfo = mApkList.get(i); String desc = String.format("%s,文件大小%d", apkInfo.getName(), apkInfo.getSize()); TextView tv_apk = new TextView(this); // 创建一个文本视图 tv_apk.setText(desc); tv_apk.setTextColor(Color.BLACK); tv_apk.setTextSize(17); int pad = Utils.dip2px(this, 5); tv_apk.setPadding(pad, pad, 0, 0); // 设置文本视图的内部间距 final int pos = i; tv_apk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showAlert(apkInfo); // 显示安装apk的提示对话框 } }); ll_list.addView(tv_apk); // 把文本视图添加至安装包列表的线性布局 } } // 显示安装apk的提示对话框 private void showAlert(final ApkInfo apkInfo) { PackageManager pm = getPackageManager(); // 获取应用包管理器 // 获取apk文件的包信息 PackageInfo pi = pm.getPackageArchiveInfo(apkInfo.getPath(), PackageManager.GET_ACTIVITIES); if (pi != null) { // 能找到包信息 Log.d(TAG, "packageName="+pi.packageName+", versionName="+pi.versionName+", versionCode="+pi.versionCode); String desc = String.format("应用包名:%s\n版本名称:%s\n版本编码:%s\n文件路径:%s", pi.packageName, pi.versionName, pi.versionCode, apkInfo.getPath()); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("是否安装该应用?"); // 设置提醒对话框的标题 builder.setMessage(desc); // 设置提醒对话框的消息内容 builder.setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { installApk(apkInfo.getPath()); // 安装指定路径的APK } }); builder.setNegativeButton("否", null); builder.create().show(); // 显示提醒对话框 } else { // 未找到包信息 ToastUtil.show(this, "该安装包已经损坏,请选择其他安装包"); } } // 安装指定路径的APK private void installApk(String path) { Log.d(TAG, "path="+path); Uri uri = Uri.parse(path); // 根据指定路径创建一个Uri对象 // 兼容Android7.0,把访问文件的Uri方式改为FileProvider if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 通过FileProvider获得安装包文件的Uri访问方式 uri = FileProvider.getUriForFile(this, "com.example.chapter07.fileProvider", new File(path)); } Intent intent = new Intent(Intent.ACTION_VIEW); // 创建一个浏览动作的意图 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 另外开启新页面 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 需要读权限 // 设置Uri的数据类型为APK文件 intent.setDataAndType(uri, "application/vnd.android.package-archive"); startActivity(intent); // 启动系统自带的应用安装程序 } }
XML文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="点击下列包名即可安装APP" android:textColor="@color/black" android:textSize="17sp" /> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/ll_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> </ScrollView> </LinearLayout>
创作不易 觉得有帮助请点赞关注收藏~~~