001package com.aispeech.dui.dds.update;
002
003import android.app.Dialog;
004import android.app.Notification;
005import android.app.NotificationManager;
006import android.content.Context;
007import android.os.Handler;
008import android.text.TextUtils;
009
010import com.aispeech.dui.manager.AILog;
011import com.aispeech.dui.BusClient;
012import com.aispeech.dui.dds.DDSConfig;
013import com.aispeech.dui.dds.R;
014import com.aispeech.dui.dds.agent.Agent;
015import com.aispeech.dui.dds.agent.MessageObserver;
016import com.aispeech.dui.dds.utils.AssetsUtil;
017import com.aispeech.libcomm.business.LocalKeys;
018import com.aispeech.libcomm.business.LocalKeysUtil;
019import com.aispeech.libcomm.business.topic.AgentTopicUtil;
020import com.aispeech.libcomm.business.topic.Topic;
021
022import org.json.JSONException;
023import org.json.JSONObject;
024
025
026public class DDSUpdater {
027    public static final String TAG = "DDSUpdater";
028
029    private Context context;
030
031    private DDSConfig configs;
032
033    private DDSUpdateListener listener;
034
035    private Agent agent;
036
037    private Notification.Builder builder;
038
039    private Dialog dialog;
040
041    private String[] ddsUpdateResultMsg = new String[]{
042            "资源加载成功",
043            "服务授权失败",
044            "解码失败",
045            "未发现新的版本",
046            "请先升级您的客户端",
047            "网络异常, 无法连接至服务器",
048            "解码失败",
049            "补丁安装失败",
050            "备份压缩文件不存在",
051            "提取压缩文件失败",
052            "还未设置产品ID,请先扫码绑定",
053            "无效客户端版本",
054            "无效用户ID",
055            "无效设备ID",
056            "资源地址无效",
057            "无效的产品分支",
058            "无法找到资源",
059            "资源校验失败",
060            "无效的授权token",
061            "当前产品中内核资源版本过低,请前往DUI控制台对应的产品中,选择最新的内核资源版本并重新发布产品。",
062            "未知错误"
063    };
064
065    public void release() {
066        agent = null;
067        context = null;
068    }
069
070    /**
071     * 构造方法,开发者可以不关注该构造方法,
072     * 而是可以通过{@link com.aispeech.dui.dds.DDS#getUpdater}获取DDSUpdater实例
073     *
074     * @param context context
075     * @param configs DDSConfig配置
076     * @param agent   agent
077     */
078    public DDSUpdater(Context context, DDSConfig configs, Agent agent) {
079        this.context = context;
080        this.configs = configs;
081        this.agent = agent;
082        agent.subscribe(new String[]{
083                Topic.Update.UpdateFound.TOPIC_NAME,
084                Topic.Update.UpdateFinish.TOPIC_NAME,
085                Topic.Update.UpdatePercentage.TOPIC_NAME
086        }, messageObserver);
087    }
088
089    private boolean isUseNotificationBar() {
090        String value = configs.getConfig(DDSConfig.K_USE_UPDATE_NOTIFICATION);
091        return TextUtils.equals(value, "true");
092    }
093
094    private BusClient getBusClient() {
095        if (agent != null) {
096            return agent.getBusClient();
097        }
098        return null;
099    }
100
101    /**
102     * 请求开始检测以及更新
103     *
104     * @param ddsUpdateListener 更新回调监听器
105     */
106    public void update(final DDSUpdateListener ddsUpdateListener) {
107        AILog.userI(TAG, "DDSUpdater.update input =", (ddsUpdateListener == null));
108        this.listener = ddsUpdateListener;
109        try {
110            JSONObject obj = new JSONObject();
111            obj.put(Topic.Agent.AgentEvent.EVENT, "update.start");
112            BusClient bc = getBusClient();
113            if (bc != null) {
114                LocalKeysUtil.getInstance().put(LocalKeys.Update.LOCAL_KEYS_AVAILABLE_STORAGE, String.valueOf(getAvailableStorage()), false);
115                AgentTopicUtil.publishAgentEvent(bc, obj);
116            }
117        } catch (Exception e) {
118            com.aispeech.dui.manager.AIJavaException.printException(e);
119        }
120    }
121
122    private long getAvailableStorage() {
123        long available = 0;
124        available = AssetsUtil.getAvailableInternalMemorySize();
125        AILog.i(TAG, "available space->", String.valueOf(available));
126
127        return available;
128    }
129
130    private MessageObserver messageObserver = new MessageObserver() {
131
132        @Override
133        public void onMessage(String message, String data) {
134            AILog.d(TAG, "onMessage->", message);
135            if (Topic.Update.UpdateFound.TOPIC_NAME.equals(message)) {
136                JSONObject args = null;
137                try {
138                    args = new JSONObject(data);
139                    final String title = "发现新的更新资源, 正在为您更新...";
140                    final String changeLogs = args.optString(Topic.Update.UpdateFound.CHANGE_LOGS);
141                    if (isUseNotificationBar()) {
142                        AILog.d(TAG, "use notification bar");
143                        showUpdatingNotification(title, changeLogs);
144                    }
145                    if (listener != null) {
146                        listener.onUpdateFound(changeLogs);
147                    }
148                } catch (JSONException e) {
149                    com.aispeech.dui.manager.AIJavaException.printException(e);
150                }
151
152            } else if (Topic.Update.UpdateFinish.TOPIC_NAME.equals(message)) {
153                JSONObject args = null;
154                try {
155                    args = new JSONObject(data);
156                    BusClient bc = getBusClient();
157                    if (bc == null) {
158                        return;
159                    }
160                    if ("success".equals(args.optString(Topic.Update.UpdateFinish.STATE))) {
161//                        RecorderTopicUtil.publishRecorderCtrl(bc, "stopall", "", false);
162
163                        if (isUseNotificationBar()) {
164                            showUpdateResultNotification("资源加载成功");
165                        }
166                        if (listener != null) {
167                            listener.onUpdateFinish();
168                        }
169                    } else if ("070303".equals(args.optString(Topic.Update.UpdateFinish.ERR_ID))) {
170                        //no new version found, do nothing
171                    } else if ("070304".equals(args.optString(Topic.Update.UpdateFinish.ERR_ID))) {
172                        if (listener != null) {
173                            listener.onUpgrade("");
174                        }
175                    } else {
176                        int errId = Integer.valueOf(TextUtils.isEmpty(args.optString(Topic.Update.UpdateFinish.ERR_ID)) ? "0" : args
177                                .optString(Topic.Update.UpdateFinish.ERR_ID));
178                        int index = errId - 70300;
179                        int length = ddsUpdateResultMsg.length;
180                        if (index < 0 || index >= length) {
181                            index = length - 1;
182                        }
183                        String msg = ddsUpdateResultMsg[index];
184                        if (isUseNotificationBar()) {
185                            showUpdateResultNotification(msg);
186                        }
187                        if (listener != null) {
188                            listener.onError(errId, msg);
189                        }
190                    }
191                } catch (Exception e) {
192                    com.aispeech.dui.manager.AIJavaException.printException(e);
193                }
194
195            } else if (Topic.Update.UpdatePercentage.TOPIC_NAME.equals(message)) {
196                try {
197                    JSONObject jsonObject = new JSONObject(data);
198                    float progress = Float.valueOf(jsonObject.optString(Topic.Update.UpdatePercentage.PROGRESS));
199                    if (isUseNotificationBar()) {
200                        updateProgress(progress);
201                    }
202                    if (listener != null) {
203                        listener.onDownloadProgress(progress);
204                    }
205                } catch (Exception e) {
206                    com.aispeech.dui.manager.AIJavaException.printException(e);
207                }
208            }
209        }
210    };
211
212    private void showUpdatingNotification(final String title, final String info) {
213        Handler handler = new Handler(context.getMainLooper());
214        handler.post(new Runnable() {
215            @Override
216            public void run() {
217                builder = new Notification.Builder(context)
218                        .setSmallIcon(R.drawable.icon)
219                        .setContentTitle(title)
220                        .setContentText(info).setAutoCancel(false);
221                builder.setProgress(0, 0, false);
222                NotificationManager mNotificationManager =
223                        (NotificationManager) context.getSystemService(Context
224                                .NOTIFICATION_SERVICE);
225                mNotificationManager.notify(1024, builder.getNotification());
226            }
227        });
228    }
229
230    private void updateProgress(final Float percentage) {
231        Handler handler = new Handler(context.getMainLooper());
232        handler.post(new Runnable() {
233            @Override
234            public void run() {
235                AILog.i(TAG, "update, ", percentage);
236                if (builder == null) {
237                    AILog.w(TAG, "builder is null, renew one.");
238                    builder = new Notification.Builder(context)
239                            .setSmallIcon(R.drawable.icon).setAutoCancel(false);
240                }
241                builder.setProgress(100, percentage.intValue(), false);
242                builder.setContentTitle("正在更新资源..." +
243                        percentage + "%");
244                NotificationManager mNotificationManager =
245                        (NotificationManager) context.getSystemService(Context
246                                .NOTIFICATION_SERVICE);
247                mNotificationManager.notify(1024, builder.getNotification());
248            }
249        });
250    }
251
252    private void showUpdateResultNotification(final String info) {
253        Handler handler = new Handler(context.getMainLooper());
254        handler.post(new Runnable() {
255            @Override
256            public void run() {
257                builder = new Notification.Builder(context)
258                        .setSmallIcon(R.drawable.icon)
259                        .setContentTitle("更新结果:")
260                        .setContentText(info).setAutoCancel(true);
261                NotificationManager mNotificationManager =
262                        (NotificationManager) context.getSystemService(Context
263                                .NOTIFICATION_SERVICE);
264                mNotificationManager.notify(1024, builder.getNotification());
265            }
266        });
267    }
268
269}