有头像的联系人来电,界面不显示头像:
1 查看头像保存流程:原图,剪切的方形图,保存的头像
进入联系人编辑界面的ContactEditorFragment后
==》bindEditors
==》gernateRawContactView
==》bindPhotoHandler
(
初始化PhotoHandler:
在PhotoHandler中初始化mTempPhotoUri和mCroppedPhotoUri
当图片不是DrmImage的时候需要将原图读取到一个临时地方, mTempPhotoUri用来表示这个临时地方的uri
如果是DrmImage或者拍摄的图片则直接使用原图的Uri: 其作用是作为剪切动作中的输入源。
mCroppedPhotoUri是剪切动作中的输出源,将剪切好的图片放到该uri下面。
)
==》拍摄的图片会放到content://com.android.contacts.files/my_cache/路径下,直接当作剪切图片输入源。
选择的图片查看是否DrmImage,如果不是则先读取放到mTempPhotoUri,再作为剪切图片输入源,如果是则同上直接作为剪切图片的输入源
==》剪切后会放到mCroppedPhotoUri中,路径也是content://com.android.contacts.files/my_cache/
==》点击剪切,ContactEditorFragment.PhotoHandler.PhotoEditorListener.onPhotoSelected
==》setPhoto(....)
(
该函数会将剪切的头像的uri更新到mUpdatedPhotos中,如下
(Bundlle)mUpdatedPhotos.putParcelable(String.valueOf(rawContact), photoUri);
)
==》点击保存
==》start ContactSaveService
==》saveContact
(
先保存非头像数据拿到insertedRawContactId,
然后从上面mUpdatedPhotos获取parceable数据photoUri,即存在content://com.android.contacts.files/my_cache/路径下的资源,
ContactPhotoUtils.savePhotoFromUriToUri通过stream将头像数据写入db
写入方式如下:
outputUri= content://com.android.contacts/raw_contacts/34/display_photo
getContentResolver()
.openAssetFileDescriptor(outputUri, "rw").createOutputStream();
最后删除存在content://com.android.contacts.files/my_cache/路径下的photo资源
)
==》到这里App端的保存动作结束,如果发生IO异常会导致头像保存失败。
那么ContactsProvider是怎么将保存的图片放到/data/data/com.android.providers.contacts/files/目录下呢??
App端调用openAssetFileDescriptor(outputUri, "rw")之后binder到ContactsProvider.openAssetFile
=》openAssetFileLocal
=》openAssetFileInner
(
在返回FileDescriptor之前会先查询传入的uri中的id是否有效,如果有效则代表存在有效的联系人,然后返回有效的descriptor
如果无效则抛出异常。
这说明头像的插入必须在联系人建立之后,这也是为什么上层App在存储完毕非头像数据后才去存储头像的原因。
)
=》创建ParcelFileDescriptor数组,个数为2,
第一个用来读,封装成PipeMonitor(继承AsyncTask),
第二个用来写,用来写的封装成AssetFileDescriptor(实现parceable接口)返回给用户,
写入完毕后PipeMonitor在后台通过stream创建缩略图和原图。
创建原图的时候先写入一个临时文件,等图片信息插入photo_files后,拿到返回的id,再将前面的临时文件重命名为id,
至此我们就看到data/data/com.android.providers.contacts/files/photo/下面全是以数字命名的图片。
=》到了这里联系人的头像就插入完毕了
可以看出联系人头像插入失败的两个原因:
原因一:联系人的非头像数据保存的时候失败,没有产生有效的rawContactId,导致后续插入头像数据的时候无有效id而异常。
原因二:写入的时候IO异常
2 查看头像读取流程:小头像读取,大头像读取,原图读取
3 怀疑是剪切后的头像没有保存成功
Wilson 头像拉伸问题:
1 原图是非裁剪过的原图
2 db里面存储的也是非裁剪过的图片
疑问:
为何联系人里面显示的是正确的?
备注:
头像大小的定义在ContactsProvider的下述文件中
ContactsProvider/src/com/android/providers/contacts/PhotoProcessor.java
定义了如下两个变量:
sMaxThumbnailDim:缩略图大小,如果property值有定义contacts.thumbnail_size则取这个值,不然使用默认值96
sMaxDisplayPhotoDim:大头像大小,如果property值有定义contacts.display_photo_size则取这个值,不然使用默认值,
默认值根据手机内存大小决定,大于680M的手机使用720, 否则使用480
发现的可优化点:
1 拍摄的图片直接用原资源进行剪切,不用先存储到一个临时地方。
2 去掉MTK相关的静态代码,从ContactsSystemProperties.java查起
3 BaseRawContactEditorView.setState有耗时操作
Debug信息:
拍摄后拿到的Uri:
content://com.android.contacts.files/my_cache/ContactPhoto-IMG_20180621_165824.jpg
剪切时的信息:
ClipData:
ClipData { text/uri-list "output" {U:content://com.android.contacts.files/my_cache/ContactPhoto-IMG_20180621_165824-cropped.jpg} }
mExtras:
Bundle[{outputX=720, outputY=720, output=content://com.android.contacts.files/my_cache/ContactPhoto-IMG_20180621_165824-cropped.jpg, aspectX=1, aspectY=1, crop=true, scale=true, scaleUpIfNeeded=true}]
mData :
content://com.android.contacts.files/my_cache/ContactPhoto-IMG_20180621_165824.jpg
待研究问题:
1 需要研究下content://com.android.contacts.files/指向哪里
2 研究下PipeMonitor是怎么监听pipe写入完毕的
网友评论