客户端接入指南更新时间: 2025-03-31 17:26:00

一、使用说明

  • 小米动态照片SDK 基于安卓平台,提供了小米动态照片相关的接口能力,开发者可以根据接口能力,实现自己的动态照片相关的业务功能
  • 小米动态照片是由一个Jpeg文件和一个MP4文件合成的特殊结构的文件

二、接入方式

  • 开发者于开放平台发起申请->审核通过后咨询客服获取接入所需账号、密码->开发者接入SDK->联调测试->功能上线
  • 申请通过后,请咨询客服获取maven或AAR文件的账号及密码

三、调用方法说明

1、maven依赖

repositories {
maven{
url"https://repos.xiaomi.com/maven"
credentials{
username="*************"
password="**************************"
}
}
}

// 正式版本 
implementation 'com.xiaomi.camera:livephoto:1.0.0'

2、AAR文件下载到本地引入

AAR下载地址:

https://repos.xiaomi.com/maven/com/xiaomi/camera/livephoto/1.0.0/livephoto-1.0.0.aar
username="*************"
password="**************************"

SDK需要依赖com.adobe.xmp:xmpcore包:

implementation("com.adobe.xmp:xmpcore:5.1.3")

3、权限依赖

<uses-permission 
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />

4、调用方法说明

动态照片SDK 采用静态方式调用,无需初始化。请在调用SDK前确保已获取对应的读写权限

4.1 判断本机设备是否支持动态照片

/**
* 返回本机设备是否支持LivePhoto
*
* @return true=支持,fasle=不支持
*/
public static boolean isDeviceSupportLivePhoto();

调用示例

boolean isSupport = MiLivePhotoTools.isDeviceSupportLivePhoto();

4.2 识别一个文件是否是动态照片

动态照片SDK提供2种方式来识别单个文件是否是Livephoto:
1、通过查询媒体数据库识别。会占用较低的内存,提供更快的识别速度,但是会被系统照明弹记录到访问媒体库的次数

2、通过读取文件头信息识别。会占用IO资源,识别速度取决的设备的IO速度,但是不会被系统照明弹记录到

4.2.1 通过查询媒体数据库识别

/**
* 识别文件是否属于livephoto照片
*
* @param context
* @param path 文件路径
* @return 是否是livephoto类型的照片
*/
public static boolean isLivePhoto(Context context, String path);

/**
* 识别文件是否属于livephoto照片
*
* @param context
* @param 文件Uri
* @return 是否是livephoto类型的照片
*/
public static boolean isLivePhoto(Context context, Uri uri);

调用示例

// path类型参数
boolean isLivephoto = MiLivePhotoTools.isLivePhoto(getBaseContext(), imagePath);
// uri类型参数
boolean isLivephoto = MiLivePhotoTools.isLivePhoto(getBaseContext(), imageUri);

4.2.2 通过文件IO方式,读取文件头信息识别

/**  
* 识别是否是Livephoto文件
* 内部通过IO访问文件,寻找文件头中Livephoto相关的xmp信息。
* @param path
* @return
*/
public static boolean isLivePhotoFile(String path);

/**  
* 识别是否是Livephoto文件
* 内部通过IO访问文件,寻找文件头中Livephoto相关的xmp信息。
* @param context
* @param uri
* @return
*/
public static boolean isLivePhotoFile(Context context, Uri uri);

调用示例

// path类型参数 
boolean isLivephoto = MiLivePhotoTools.isLivePhotoFile(imagePath);
// uri类型参数
boolean isLivephoto = MiLivePhotoTools.isLivePhotoFile(getBaseContext(), imageUri);

4.3 拆解视频和图片部分

/**
* 将动态照片的Jpeg部分和Video拆出来
* 如果jpeg或者Video输入为Null,则不拆解对应的文件。
*
* @param livePhotoPath 输入的Livephoto文件
* @param jpegOutPath 输出的jpeg文件,传Null不输出
* @param videoOutPath 输出的Video部分的文件,传Null不输出
* @return 解码后的Livephoto信息,解码失败时返回Null
*/
public static LivePhotoInfo decodeLivephoto(String livePhotoPath, String jpegOutPath, String videoOutPath);

/**
* 将动态照片的Jpeg部分和Video拆出来
* 如果jpeg或者Video输入为Null,则不拆解对应的文件。
*
* @param context
* @param livePhotoUri 输入的Livephoto文件
* @param jpegOutUri 输出的jpeg文件,传Null不输出
* @param videoOutUri 输出的Video部分的文件,传Null不输出
* @return 解码后的Livephoto信息,解码失败时返回Null
*/
public static LivePhotoInfo decodeLivephoto(Context context, Uri livePhotoUri, Uri jpegOutUri, Uri videoOutUri);

返回一个MiLivePhotoInfo对象记录了一些解码信息,如下:

/**
* LivePhoto照片的封装对象,包含Livephoto的一些信息。
*/
public class MiLivePhotoInfo {
/**
* 类型
* 1 = 动态照片
* 0 = 非动态照片
*/
private int type;
/**
* 版本
*/
private int version;
/**
* 视频部分相对于图片数据尾部的偏移量,等于视频部分的字节大小
*/
private int videoOffset;
/**
* 表示图片在视频中对应帧的时间戳(单位:微秒)
*/
private long videoPresentationTimestampUs;

public MiLivePhotoInfo(){

}
public MiLivePhotoInfo(int type,int version, int videoOffset, long videoPresentationTimestampUs) {
this.type = type;
this.version = version;
this.videoOffset = videoOffset;
this.videoPresentationTimestampUs = videoPresentationTimestampUs;
}

public int getType() {
return type;
}

public void setType(int type) {
this.type = type;
}

public int getVersion() {
return version;
}

public void setVersion(int version) {
this.version = version;
}

public int getVideoOffset() {
return videoOffset;
}

public void setVideoOffset(int videoOffset) {
this.videoOffset = videoOffset;
}

public long getVideoPresentationTimestampUs() {
return videoPresentationTimestampUs;
}

public void setVideoPresentationTimestampUs(long videoPresentationTimestampUs) {
this.videoPresentationTimestampUs = videoPresentationTimestampUs;
}
}

调用示例

// path类型参数
LivePhotoInfo info = MiLivePhotoTools.decodeLivephoto(srcPath,decodeImagePath,decodeVideoPath);
// uri类型参数
LivePhotoInfo info = MiLivePhotoTools.decodeLivephoto(getBaseContext(),srcUri,decodeImageUri,decodeVideoUri);

4.4 合成动态照片

提供合成动态照片的能力,接口描述如下
其中videoPresentationTimestampUs参数是必传的参数,表示与jpeg对应的视频帧的显示时间戳。如果不确定该值,开发者可以传入0,但是不能保证合成后的照片在相册中正常播放和编辑。如果开发者希望合成后的图能够在小米相册中正确播放和编辑,那么开发者必须传入正确的值

/**  
* 根据输入的jpeg图像和Video文件,生成一张Livephoto格式的jpeg文件,输出到outFilePath对应的File中
* 并返回合成是否成功
*
* @param jpegPath 要合成的Jpeg文件
* @param videoPath 要合成的Video文件
* @param videoPresentationTimestampUs jpeg在Video中对应帧的时间戳
* @param outFilePath 合成后的文件路径
* @param insertMediaStore (可选参数)是否插入媒体库,默认true
* @return 合成是否成功
*/
public static boolean muxLivephoto(String jpegPath, String videoPath, long videoPresentationTimestampUs, String outFilePath, boolean insertMediaStore);

/**
* 根据输入的jpeg图像和Video文件,生成一张Livephoto格式的jpeg文件,输出到outFileUri描述的File中
* 并返回合成是否成功
*
* @param context
* @param jpegUri 要合成的Jpeg文件
* @param videoUri 要合成的Video文件
* @param videoPresentationTimestampUs jpeg在Video中对应帧的时间戳
* @param outFileUri 合成后的文件Uri
* @param insertMediaStore (可选参数)是否插入媒体库,默认true
* @return 合成是否成功
*/
public static boolean muxLivephoto(Context context, Uri jpegUri, Uri videoUri, long videoPresentationTimestampUs, Uri outFileUri, boolean insertMediaStore);

调用示例

// path类型参数
boolean succ = MiLivePhotoTools.muxLivephoto(getBaseContext(),jpegPath,videoPath,videoPresentationTimestampUs,imageOutPath);
// uri类型参数
boolean succ = MiLivePhotoTools.muxLivephoto(getBaseContext(),jpegUri,videoUri,videoPresentationTimestampUs,imageOutUri);

4.4.1 合成动图的设备兼容性

  • 仅Xiaomi HyperOS系统支持

当前仅Xiaomi HyperOS版本的系统,支持播放三方合成的动图,MIUI系统不识别三方合成的动图,建议三方开发者,先判断本机设备的系统是否满足条件

Xiaomi HyperOS判断方法:

1. 读取系统属性[ro.miui.ui.version.code],取值是816的就是Xiaomi HyperOS

2. 取值小于816的就是MIUI14及之前的版本

  • 系统相册的versionCode大于407621,才能支持播放三方合成的动图

包名:com.miui.gallery

versionCode:> 407621

/**
* 判断当前设备是否是Xiaomi HyperOS系统
*
* @return
*/
public static boolean isHyperOs() {
try {
String code = com.xiaomi.exif.SystemProperties.get("ro.miui.ui.version.code");
if (Integer.valueOf(codeStr) >= 816) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

/**
* 返回相册是否支持播放三方的动图
* @param context
* @return
*/
public static boolean isMiuiGallerySupport(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo("com.miui.gallery", 0);
if (packageInfo != null) {
return packageInfo.versionCode > 407621;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

4.5 获取设备的全部动图

这里仅提供示例代码,开发者根据自己需求,选择增加分页或者查询更多的字段信息

/**
* 从媒体数据库中查询出所有的动图记录
* @param context
* @return List<String>
*/
public static List < String > listAllLivePhoto(Context context) {
List < String > resultList = new ArrayList();
Cursor cursor = null;
try {
String[] projection = {
MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA, MediaStore.Images.Media.XMP
};
// 查询数据库的XMP字段,并按照16进制搜索是否包含livephoto的相关信息
String selection = "HEX(" + MediaStore.Images.Media.XMP + ") LIKE '%" + stringToHex("MicroVideo") + "%' or " +
"HEX(" + MediaStore.Images.Media.XMP + ") LIKE '%" + stringToHex("MotionPhoto") + "%'";
String[] selectionArgs = null;
cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null);
if (cursor.moveToFirst()) {
do {
String path = cursor.getString(cursor.getColumnIndexOrThrow(projection[1]));
resultList.add(path);
} while (cursor.moveToNext());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
return resultList;
}

public static String stringToHex(String str) {
StringBuilder hex = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
hex.append(Integer.toHexString((int) c));
}
return hex.toString();
}

4.6 动态照片的展示

不带水印的动态照片,封面图片和视频的比例是一致的。但是带徕卡水印的动态照片,封面图片和视频的比例不一致,其中视频部分的比例跟封面图片去掉水印部分后的比例是一致的
为了保证播放的封面到视频部分的展示体验,开发者需要自行适配,可参考小米系统相册的展示效果

文档内容是否有帮助?
有帮助
无帮助