Dana
2025-11-30 23041aaa47f97c167306d997cb9515740359d6aa
1.加两个类
2个文件已添加
363 ■■■■■ 已修改文件
app/src/main/java/com/anyun/h264/model/ResourceInfo.java 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/anyun/h264/service/H264EncodeServiceClient.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/anyun/h264/model/ResourceInfo.java
New file
@@ -0,0 +1,157 @@
package com.anyun.h264.model;
import android.os.Parcel;
import android.os.Parcelable;
/**
 * 音视频资源信息(根据JT/T 1076-2016表23定义)
 * 终端上传音视频资源列表格式
 */
public class ResourceInfo implements Parcelable {
    /** 逻辑通道号(根据JT/T 1076—2016表2) */
    private byte logicalChannelNumber;
    /** 开始时间(BCD[6]格式:YY-MM-DD-HH-MM-SS) */
    private String startTime; // BCD编码的6字节,格式:YYMMDDHHmmss
    /** 结束时间(BCD[6]格式:YY-MM-DD-HH-MM-SS) */
    private String endTime; // BCD编码的6字节,格式:YYMMDDHHmmss
    /** 报警标志(64位) */
    private long alarmFlag;
    /** 音视频资源类型:0-音视频,1-音频,2-视频 */
    private byte resourceType;
    /** 码流类型:1-主码流,2-子码流 */
    private byte streamType;
    /** 存储器类型:1-主存储器,2-灾备存储器 */
    private byte storageType;
    /** 文件大小(单位:字节) */
    private long fileSize;
    public ResourceInfo() {
    }
    protected ResourceInfo(Parcel in) {
        logicalChannelNumber = in.readByte();
        startTime = in.readString();
        endTime = in.readString();
        alarmFlag = in.readLong();
        resourceType = in.readByte();
        streamType = in.readByte();
        storageType = in.readByte();
        fileSize = in.readLong();
    }
    public static final Creator<ResourceInfo> CREATOR = new Creator<ResourceInfo>() {
        @Override
        public ResourceInfo createFromParcel(Parcel in) {
            return new ResourceInfo(in);
        }
        @Override
        public ResourceInfo[] newArray(int size) {
            return new ResourceInfo[size];
        }
    };
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeByte(logicalChannelNumber);
        dest.writeString(startTime);
        dest.writeString(endTime);
        dest.writeLong(alarmFlag);
        dest.writeByte(resourceType);
        dest.writeByte(streamType);
        dest.writeByte(storageType);
        dest.writeLong(fileSize);
    }
    @Override
    public int describeContents() {
        return 0;
    }
    // Getters and Setters
    public byte getLogicalChannelNumber() {
        return logicalChannelNumber;
    }
    public void setLogicalChannelNumber(byte logicalChannelNumber) {
        this.logicalChannelNumber = logicalChannelNumber;
    }
    public String getStartTime() {
        return startTime;
    }
    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
    public String getEndTime() {
        return endTime;
    }
    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }
    public long getAlarmFlag() {
        return alarmFlag;
    }
    public void setAlarmFlag(long alarmFlag) {
        this.alarmFlag = alarmFlag;
    }
    public byte getResourceType() {
        return resourceType;
    }
    public void setResourceType(byte resourceType) {
        this.resourceType = resourceType;
    }
    public byte getStreamType() {
        return streamType;
    }
    public void setStreamType(byte streamType) {
        this.streamType = streamType;
    }
    public byte getStorageType() {
        return storageType;
    }
    public void setStorageType(byte storageType) {
        this.storageType = storageType;
    }
    public long getFileSize() {
        return fileSize;
    }
    public void setFileSize(long fileSize) {
        this.fileSize = fileSize;
    }
    @Override
    public String toString() {
        return "ResourceInfo{" +
                "logicalChannelNumber=" + logicalChannelNumber +
                ", startTime='" + startTime + '\'' +
                ", endTime='" + endTime + '\'' +
                ", alarmFlag=" + alarmFlag +
                ", resourceType=" + resourceType +
                ", streamType=" + streamType +
                ", storageType=" + storageType +
                ", fileSize=" + fileSize +
                '}';
    }
}
app/src/main/java/com/anyun/h264/service/H264EncodeServiceClient.java
New file
@@ -0,0 +1,206 @@
package com.anyun.h264.service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.anyun.h264.IH264EncodeService;
import com.anyun.h264.model.ResourceInfo;
import java.util.List;
/**
 * H264编码服务客户端
 * 用于绑定服务并调用AIDL接口
 *
 * 使用示例:
 * <pre>
 * // 创建客户端
 * H264EncodeServiceClient client = new H264EncodeServiceClient(context);
 *
 * // 绑定服务
 * client.bindService();
 *
 * // 等待服务绑定完成后,调用接口
 * // 开启文件编码(带配置参数)
 * String jsonConfig = "{\"width\":640,\"height\":480,\"framerate\":25}";
 * int result = client.controlEncode(0, jsonConfig);
 *
 * // 开启网络推送(带配置参数)
 * String networkConfig = "{\"ip\":\"192.168.1.100\",\"port\":8888,\"width\":1280,\"height\":720,\"framerate\":30}";
 * result = client.controlEncode(2, networkConfig);
 *
 * // 停止编码(不需要配置参数)
 * client.controlEncode(1, null);
 *
 * // 获取资源列表
 * List<ResourceInfo> resources = client.getResourceList("240101000000", "240101235959");
 *
 * // 解绑服务
 * client.unbindService();
 * </pre>
 */
public class H264EncodeServiceClient {
    private static final String TAG = "H264EncodeClient";
    private Context context;
    private IH264EncodeService service;
    private boolean isBound = false;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            Log.d(TAG, "Service connected");
            service = IH264EncodeService.Stub.asInterface(binder);
            isBound = true;
            // 可以在这里添加服务连接成功的回调
            if (onServiceConnectedListener != null) {
                onServiceConnectedListener.onConnected();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "Service disconnected");
            service = null;
            isBound = false;
            // 可以在这里添加服务断开连接的回调
            if (onServiceDisconnectedListener != null) {
                onServiceDisconnectedListener.onDisconnected();
            }
        }
    };
    // 服务连接回调接口
    public interface OnServiceConnectedListener {
        void onConnected();
    }
    public interface OnServiceDisconnectedListener {
        void onDisconnected();
    }
    private OnServiceConnectedListener onServiceConnectedListener;
    private OnServiceDisconnectedListener onServiceDisconnectedListener;
    public H264EncodeServiceClient(Context context) {
        this.context = context.getApplicationContext();
    }
    /**
     * 设置服务连接监听器
     */
    public void setOnServiceConnectedListener(OnServiceConnectedListener listener) {
        this.onServiceConnectedListener = listener;
    }
    /**
     * 设置服务断开连接监听器
     */
    public void setOnServiceDisconnectedListener(OnServiceDisconnectedListener listener) {
        this.onServiceDisconnectedListener = listener;
    }
    /**
     * 绑定服务
     * @return 是否成功启动绑定
     */
    public boolean bindService() {
        if (isBound) {
            Log.w(TAG, "Service is already bound");
            return true;
        }
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(context, "com.anyun.h264.H264EncodeService"));
        boolean result = context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
        if (!result) {
            Log.e(TAG, "Failed to bind service");
        }
        return result;
    }
    /**
     * 解绑服务
     */
    public void unbindService() {
        if (isBound) {
            context.unbindService(connection);
            isBound = false;
            service = null;
            Log.d(TAG, "Service unbound");
        }
    }
    /**
     * 检查服务是否已绑定
     */
    public boolean isServiceBound() {
        return isBound && service != null;
    }
    /**
     * 控制H264编码
     * @param action 操作类型:0-开启h264文件写入,1-停止h264编码并停止写入文件,2-开启网络推送h264(不写入文件),3-停止h264编码并停止网络推送
     * @param jsonConfig JSON格式的配置参数,包含:ip(服务器IP)、port(服务器端口)、width(视频宽度)、height(视频高度)、framerate(帧率)
     *                  示例:{"ip":"192.168.1.100","port":8888,"width":640,"height":480,"framerate":25}
     *                  如果action为1或3(停止操作),此参数可为null
     * @return 0-成功,1-失败
     */
    public int controlEncode(int action, String jsonConfig) {
        if (!isServiceBound()) {
            Log.e(TAG, "Service is not bound");
            return 1; // 失败
        }
        try {
            int result = service.controlEncode(action, jsonConfig);
            Log.d(TAG, "controlEncode(" + action + ", " + jsonConfig + ") returned: " + result);
            return result;
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling controlEncode", e);
            return 1; // 失败
        }
    }
    /**
     * 控制H264编码(重载方法,兼容旧代码,使用null作为jsonConfig)
     * @param action 操作类型:0-开启h264文件写入,1-停止h264编码并停止写入文件,2-开启网络推送h264(不写入文件),3-停止h264编码并停止网络推送
     * @return 0-成功,1-失败
     * @deprecated 建议使用 controlEncode(int action, String jsonConfig) 方法,传入完整的配置参数
     */
    @Deprecated
    public int controlEncode(int action) {
        return controlEncode(action, null);
    }
    /**
     * 获取资源列表
     * @param startTime 开始时间(格式:YYMMDDHHmmss,例如:240101000000)
     * @param endTime 结束时间(格式:YYMMDDHHmmss,例如:240101235959)
     * @return 资源列表,如果失败返回null
     */
    public List<ResourceInfo> getResourceList(String startTime, String endTime) {
        if (!isServiceBound()) {
            Log.e(TAG, "Service is not bound");
            return null;
        }
        try {
            List<ResourceInfo> result = service.getResourceList(startTime, endTime);
            Log.d(TAG, "getResourceList returned " + (result != null ? result.size() : 0) + " resources");
            return result;
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling getResourceList", e);
            return null;
        }
    }
}