说明:由于在测试的时候使用的是Android 7.1的机器,代码会出现以下问题,
(1)APP安装在机器上实测会出现调用相机无法打开的现象;
(2)APP调用裁剪工具的时候会有Toast提示“无法加载此图片”。
Step 1. 新建一个activity_main.xml布局,这个没什么问题。
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:id="@+id/take_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="拍照"/>
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/>
Step 2. 新建MainActivity,以下是郭霖大神书中原来的代码。代码中比较难以理解的地方注释都写的很详细。
public class MainActivity extends AppCompatActivity {
public static final int TAKE_PHOTO = 1
public static final int CROP_PHOTO = 2
private Button takePhoto
private ImageView imageView
private Uri imageUri
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
takePhoto = (Button)findViewById(R.id.take_photo)
imageView = (ImageView)findViewById(R.id.image_view)
takePhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
File outputImage = new File(Environment.getExternalStorageDirectory(),
"maybe.jpg")
if(outputImage.exists()){
outputImage.delete()
}
try {
outputImage.createNewFile()
} catch (IOException e) {
e.printStackTrace()
}
//将File对象转换成Uri对象,因为Uri对象标识着maybe.jpg这张图片的唯一地址。
//由于Intent能传递的数据空间有限,所以需要转化成Uri
//大图片用Uri,小图片用Bitmap
//以下代码解决了Android 7.0 打开相机崩溃的问题
if(Build.VERSION.SDK_INT >24){
imageUri = FileProvider.getUriForFile(MainActivity.this,
"com.example.android.choosepicdemo.fileprovider",outputImage)
}else{
imageUri = Uri.fromFile(outputImage)
}
//Intent intent = new Intent("android.media.action.IMAGE_CAPTURE")
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)
//第一个参数:一个Intent对象
//第二个参数:如果>= 0,当Activity结束时requestCode将归还在onActivityResult()中,
//以便确定返回的数据是从哪个Activity中返回
startActivityForResult(intent,TAKE_PHOTO)
}
})
}
/*第一个参数:这个整数requestCode提供给onActivityResult,是以便确认返回的数据是从哪个Activity返回的。
这个requestCode和startActivityForResult中的requestCode相对应。
第二个参数:这整数resultCode是由子Activity通过其setResult()方法返回。
第三个参数:一个Intent对象,带有返回的数据。*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data)
switch (requestCode){
case TAKE_PHOTO:
if(resultCode == RESULT_OK){
Intent intent = new Intent("com.android.camera.action.CROP")
//以下两行代码适配Android 7.0 解决了无法加载图片的问题
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
intent.setDataAndType(imageUri,"image/*")
intent.putExtra("scale",true)
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)
startActivityForResult(intent,CROP_PHOTO)
}
break
case CROP_PHOTO:
if(resultCode == RESULT_OK){
// 因为imageUri是Uri类型的,需要转换才能被decodeStream使用
// 使用getContentResolver()
// 因为在Android系统里面,数据库是私有的。
// 一般情况下外部应用程序是没有权限读取其他应用程序的数据。
// 如果你想公开你自己的数据,你有两个选择:
// 你可以创建你自己的内容提供器(一个ContentProvider子类)或者
// 你可以给已有的提供器添加数据-如果存在一个控制同样类型数据的内容提供器且你拥有写的权限。
// 外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,
// 在Activity当中通过getContentResolver()可以得到当前应用的 ContentResolver实例
try {
//解析成Bitmap
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri))
imageView.setImageBitmap(bitmap)
} catch (FileNotFoundException e) {
e.printStackTrace()
}
}
break
default:
break
}
}
}
需要注意的是以下代码是增加了的内容:
//以下代码解决了Android 7.0 打开相机崩溃的问题
if(Build.VERSION.SDK_INT >24){
imageUri = FileProvider.getUriForFile(MainActivity.this,
"com.example.android.choosepicdemo.fileprovider",outputImage)
}else{
imageUri = Uri.fromFile(outputImage)
}
如果不这么处理的话,会导致在调用相机获取 Uri 的时候发生崩溃。
原因很明显,file:// 不被允许作为一个附加的 Uri 的意图,否则会抛出 FileUriExposedException 。其实背后有一个很好的理由,如果文件路径被发送到目标应用程序(相机应用程序在这种情况下),文件将完全访问通过相机应用程序的过程,而不仅仅只有发起者能收到。但让我们考虑一下,实际上是由我们的应用程序去启动摄像头拍照,并保存作为我们的应用程序的代表文件。因此,该文件的访问权限应该是我们的应用程序而不是摄像头应用程序本身。这就是为什么现在 file:// 在 targetSdkVersion 24 中要求每一位开发者都去完成这个任务。参考博文:http://www.sohu.com/a/136282885_659256
所以需要采用FileProvider来处理。
具体的步骤如下:
首先在AndroidManifest.xml中声明provider。这里要注意android:authorities要是你的包名一致,其他固定。
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:authorities="com.example.android.choosepicdemo.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
在res文件夹下创建xml文件夹,并创建provide_paths.xml(该名称应与上述android:resource里一致),maybe为图片保存时的名称,根据你自己命名而定。
修改java代码如下
//以下代码解决了Android 7.0 打开相机崩溃的问题
if(Build.VERSION.SDK_INT >24){
imageUri = FileProvider.getUriForFile(MainActivity.this,
"com.example.android.choosepicdemo.fileprovider",outputImage)
}else{
imageUri = Uri.fromFile(outputImage)
1、提升加载速度
2017年,百度推出闪电算法,相信很多的站长都清楚!甚至不少站长也因此遭受到了搜索引擎的打击。而MIP-Cache是将静态文件以相对路径储存在百度CDN中;为减少网络传输耗时,MIP-JS控制静态资源的按需加载,MIP-Cache系统优先从CDN读取文件;为减少浏览器渲染重绘耗时,MIP-HTML对<img>,<video>等造成浏览器重绘的标签进行了封装控制。
根据2016年8月数据统计,页面MIP化之后,页面展现时间减少了30%-80%。如果您的页面只有简单交互,却引用了庞杂的前端代码库,那么尝试MIP之后速度能够得到显著提升。
2、提升到达率+用户体验,减少网站IP流失
如果一个页面需要3秒来打开,用户就需要盯着白屏等待三秒,这很容易引起用户的不耐和放弃。也就是说,一个页面能在眨眼之间打开,意味着更少的用户放弃。所以说,对于页面来讲,速度是一切的基础。
使用MIP规范之后页面的打开速度会大幅提高,减少用户的等待时间,减少用户放弃。
3、网站提权,增加用户量
众所周知,百度的自然结果是根据用户点击和页面质量排名的。在2015年年底,百度搜索引擎推出了《百度搜索MobileFriendly标准》(下文简称《MF标准》),在站长平台的说明中,《MF标准》也会作为页面排序的参考因素。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)