LicenseManager.java 10.1 KB
package com.ectrip.checkincar.license;

import android.content.Context;
import android.text.TextUtils;

import com.baidu.vis.ocrgve.plate.OcrgveEnginePlate;
import com.baidu.vis.unified.license.AndroidLicenser;
import com.baidu.vis.unified.license.BDLicenseAuthInfo;
import com.baidu.vis.unified.license.BDLicenseActivator;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * 百度离线授权 + 模型初始化管理(单例)。
 * 所有方法必须在后台线程调用;SDK 全部调用用 try/catch 兜底,防止 so 异常导致崩溃。
 */
public class LicenseManager {

    /** 正式授权拿到后在此配置(license.license 内容中的 key 与 assets 中的文件名),一期留空 */
    private static final String LICENSE_KEY = "";
    private static final String LICENSE_FILE = "ocrgve.license";

    private static volatile LicenseManager instance;

    private OcrgveEnginePlate engine;
    private int algId = -1;
    private String lastError = "未授权";

    private LicenseManager() {
    }

    public static LicenseManager get() {
        if (instance == null) {
            synchronized (LicenseManager.class) {
                if (instance == null) {
                    instance = new LicenseManager();
                }
            }
        }
        return instance;
    }

    public OcrgveEnginePlate getEngine() {
        return engine;
    }

    public int getAlgId() {
        if (algId < 0) {
            try {
                algId = OcrgveEnginePlate.getAlgorithmId();
                android.util.Log.i("LicenseManager", "getAlgorithmId() = " + algId);
            } catch (Throwable t) {
                algId = 0;
                android.util.Log.e("LicenseManager", "getAlgorithmId() failed", t);
            }
        }
        return algId;
    }

    public String getLastError() {
        return lastError;
    }

    /** 设备指纹(授权绑定依据,非硬件 SN)。失败返回空串。 */
    public String getDeviceId(Context context) {
        try {
            String id = AndroidLicenser.getDeviceId(context.getApplicationContext());
            return id == null ? "" : id.trim().toUpperCase(Locale.US);
        } catch (Throwable t) {
            return "";
        }
    }

    /**
     * 确保授权有效并完成模型初始化(只初始化一次)。
     * @return true 引擎可识别
     */
    public synchronized boolean ensureReady(Context context) {
        if (engine != null) {
            return true;
        }
        Context app = context.getApplicationContext();
        try {
            // 1. 已有授权(上次在线激活缓存)
            if (checkAuthSuccess(app)) {
                return initEngine(app);
            }
            // 2. assets 离线授权文件(正式部署方式)
            if (!TextUtils.isEmpty(LICENSE_KEY)) {
                AndroidLicenser.ErrorCode code =
                        AndroidLicenser.getInstance().authFromFile(app, LICENSE_KEY, LICENSE_FILE, true, getAlgId());
                if (code == AndroidLicenser.ErrorCode.SUCCESS) {
                    return initEngine(app);
                }
                lastError = explain(code);
                return false;
            }
            lastError = "未授权(请在设置中输入序列号联网激活,或放入正式授权文件)";
            return false;
        } catch (Throwable t) {
            lastError = "授权初始化异常: " + t.getMessage();
            return false;
        }
    }

    /**
     * 序列号联网激活,成功后立即初始化模型。
     * @return 0 成功;其余为 SDK 错误码
     */
    public synchronized int activateOnline(Context context, String serial) {
        Context app = context.getApplicationContext();
        String sn = serial.trim();
        String deviceId = getDeviceId(app);
        int alg = getAlgId();
        android.util.Log.i("LicenseManager", "=== 联网激活开始 ===");
        android.util.Log.i("LicenseManager", "  serial=[" + sn + "] len=" + sn.length());
        android.util.Log.i("LicenseManager", "  algId=" + alg);
        android.util.Log.i("LicenseManager", "  packageName=" + app.getPackageName());
        android.util.Log.i("LicenseManager", "  deviceFingerprint=" + deviceId);
        try {
            int ret = BDLicenseActivator.initLicenseOnLine(app, sn, "", alg);
            android.util.Log.i("LicenseManager", "  initLicenseOnLine ret=" + ret);
            if (ret == 0) {
                android.util.Log.i("LicenseManager", "=== 联网激活成功,开始初始化模型 ===");
                if (!initEngine(app)) {
                    android.util.Log.e("LicenseManager", "=== 模型初始化失败: " + lastError + " ===");
                    return -100;
                }
                android.util.Log.i("LicenseManager", "=== 全部成功 ===");
                return 0;
            }
            // SDK 返回错误码,把完整信息拼到 lastError 供界面展示
            lastError = "在线激活失败(ret=" + ret + ")\n"
                    + "序列号: " + sn + "\n"
                    + "算法ID: " + alg + "\n"
                    + "包名: " + app.getPackageName() + "\n"
                    + "设备指纹: " + deviceId;
            android.util.Log.e("LicenseManager", "=== 激活失败 ===\n" + lastError);
            return ret;
        } catch (Throwable t) {
            // 完整堆栈输出到 logcat
            android.util.Log.e("LicenseManager", "=== 激活异常 ===", t);
            android.util.Log.e("LicenseManager", "  serial=" + sn + " algId=" + alg
                    + " pkg=" + app.getPackageName() + " device=" + deviceId);
            // 把异常完整信息存入 lastError 供界面展示
            java.io.StringWriter sw = new java.io.StringWriter();
            t.printStackTrace(new java.io.PrintWriter(sw));
            lastError = "在线激活异常: " + t.getClass().getName() + ": " + t.getMessage()
                    + "\n\n序列号: " + sn
                    + "\n算法ID: " + alg
                    + "\n包名: " + app.getPackageName()
                    + "\n设备指纹: " + deviceId
                    + "\n\n完整堆栈:\n" + sw.toString();
            return -1;
        }
    }

    private boolean checkAuthSuccess(Context app) {
        try {
            return AndroidLicenser.getInstance().getAuthStatus(getAlgId())
                    == AndroidLicenser.ErrorCode.SUCCESS;
        } catch (Throwable t) {
            return false;
        }
    }

    private boolean initEngine(Context app) {
        try {
            OcrgveEnginePlate e = new OcrgveEnginePlate();
            OcrgveEnginePlate.setPreFiltering(false);
            int ret = e.initFromAssets(app);
            // 0 成功;多线程/重复初始化时也视为成功
            if (ret == 0) {
                engine = e;
                lastError = "";
                return true;
            }
            lastError = "模型初始化失败(" + initErrText(ret) + ")";
            return false;
        } catch (Throwable t) {
            lastError = "模型初始化异常: " + t.getMessage();
            return false;
        }
    }

    /** 授权状态摘要(设置页展示) */
    public String getStatusText(Context context) {
        if (engine != null) {
            return "已授权 · 模型已加载";
        }
        try {
            AndroidLicenser.ErrorCode code =
                    AndroidLicenser.getInstance().getAuthStatus(getAlgId());
            if (code == AndroidLicenser.ErrorCode.SUCCESS) {
                return "已授权 · 模型未加载";
            }
            return explain(code);
        } catch (Throwable t) {
            android.util.Log.w("LicenseManager", "getAuthStatus: " + t.getClass().getSimpleName()
                    + " " + t.getMessage());
            return "未授权(待激活)";
        }
    }

    /** 授权到期时间 yyyy-MM-dd,取不到返回空串。注意:未授权时 authGetAuthInfo 会 native 崩溃,必须先判状态 */
    public String getExpireText(Context context) {
        try {
            if (!checkAuthSuccess(context.getApplicationContext())) {
                return "";
            }
            BDLicenseAuthInfo info =
                    AndroidLicenser.getInstance().authGetAuthInfo(context.getApplicationContext(), getAlgId());
            if (info != null && info.expireTime > 0) {
                return new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA).format(new Date(info.expireTime));
            }
        } catch (Throwable t) {
            // ignore
        }
        return "";
    }

    public synchronized void release() {
        if (engine != null) {
            try {
                engine.uninit();
            } catch (Throwable ignored) {
            }
            engine = null;
        }
    }

    private static String initErrText(int code) {
        switch (code) {
            case 0:
                return "成功";
            case 4:
                return "鉴权失败";
            case 6:
                return "重复初始化";
            case 9:
                return "模型文件未找到";
            default:
                return "错误码" + code;
        }
    }

    private static String explain(AndroidLicenser.ErrorCode code) {
        if (code == null) {
            return "未知授权错误";
        }
        switch (code) {
            case SUCCESS:
                return "已授权";
            case LICENSE_DEVICE_ID_CHECK_ERROR:
                return "设备指纹不匹配";
            case LICENSE_PACKAGE_NAME_CHECK_ERROR:
                return "包名不匹配";
            case LICENSE_EXPIRED_TIME_CHECK_ERROR:
            case LICENSE_TIME_EXPIRED:
                return "授权已过期";
            case LICENSE_REMOTE_DATA_ERROR:
                return "远程授权失败(检查网络/序列号)";
            case LICENSE_LOCAL_FILE_ERROR:
            case LICENSE_KEY_FILE_ERROR:
                return "授权文件缺失";
            case LICENSE_NOT_INIT_ERROR:
                return "授权未初始化";
            default:
                return code.name();
        }
    }
}