diff --git a/app/build.gradle b/app/build.gradle
index 6af905e9..cdbc1040 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,8 +11,8 @@ android {
 
     defaultConfig {
         applicationId "com.navinfo.omqs"
-        minSdk 24
-        targetSdk 33
+        minSdk 21
+        targetSdk 21
         versionCode 1
         versionName "1.0"
 
@@ -30,8 +30,8 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility JavaVersion.VERSION_11
-        targetCompatibility JavaVersion.VERSION_11
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
     }
     sourceSets {
         main {
@@ -48,9 +48,7 @@ android {
 }
 
 dependencies {
-    implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
     implementation project(':collect-library')
-    api files('libs/BaiduLBS_AndroidSDK_Lib.aar')
     implementation 'androidx.core:core-ktx:1.7.0'
     implementation 'androidx.appcompat:appcompat:1.6.1'
     implementation 'com.google.android.material:material:1.5.0'
diff --git a/app/libs/BaiduLBS_AndroidSDK_Lib.aar b/app/libs/BaiduLBS_AndroidSDK_Lib.aar
deleted file mode 100644
index 18d4fe80..00000000
Binary files a/app/libs/BaiduLBS_AndroidSDK_Lib.aar and /dev/null differ
diff --git a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt
index 27e26fa3..46bcb72e 100644
--- a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt
+++ b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt
@@ -1,18 +1,19 @@
 package com.navinfo.omqs
 
 import android.app.Application
-import android.util.Log
 import com.navinfo.omqs.tools.FileManager
+import com.navinfo.omqs.ui.manager.TakePhotoManager
+import com.navinfo.omqs.util.NetUtils
 import dagger.hilt.android.HiltAndroidApp
-import io.realm.Realm
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-import java.io.File
+import org.videolan.vlc.Util
 
 @HiltAndroidApp
 class OMQSApplication : Application() {
     override fun onCreate() {
-        FileManager.initRootDir(this)
         super.onCreate()
+        FileManager.initRootDir(this)
+        Util.getInstance().init(applicationContext)
+        NetUtils.getInstance().init(this)
+        TakePhotoManager.getInstance().init(this, 1)
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/navinfo/omqs/system/SystemConstant.java b/app/src/main/java/com/navinfo/omqs/system/SystemConstant.java
new file mode 100644
index 00000000..2683529b
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/system/SystemConstant.java
@@ -0,0 +1,42 @@
+package com.navinfo.omqs.system;
+
+import java.util.UUID;
+
+/**
+ * 系统变量对象
+ */
+public class SystemConstant {
+
+    public static String USER_ID = "1";
+
+    //选择相机默认或者外设
+    public static String SELECT_CAMERA_STATE = "select_camera_state";
+    //是否连接
+    public static String CAMERA_CONNECT_STATE = "camera_connect_state";
+    //是否可以点击
+    public static String CAMERA_CLICK_STATE = "camera_click_state";
+    //拍照模式
+    public static String TAKE_CAMERA_MODE = "take_camera_mode";
+
+    public static String TAKE_CAMERA_IP = "take_camera_ip";
+
+    public static String TAKE_CAMERA_MAC = "take_camera_mac";
+
+
+    //选择拍照或者录像
+    public static String SELECT_TAKEPHOTO_OR_RECORD = "select_takephoto_or_record";
+
+    /**
+     * 获取uuid
+     * @param isUpperCase
+     * 			true 大写  false 小写
+     */
+    public static String getUuid(boolean isUpperCase){
+        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
+        if(isUpperCase)
+            uuid = uuid.toUpperCase();
+
+        return uuid;
+    }
+
+}
diff --git a/app/src/main/java/com/navinfo/omqs/system/SystemDateTime.java b/app/src/main/java/com/navinfo/omqs/system/SystemDateTime.java
new file mode 100644
index 00000000..cc0539f3
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/system/SystemDateTime.java
@@ -0,0 +1,799 @@
+package com.navinfo.omqs.system;
+
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @ClassName:     SystemDateTime.java
+ * @author         qj
+ * @version        V1.0
+ * @Date           2023年4月17日 下午1:56:02
+ * @Description:   时间工具类
+ */
+public class SystemDateTime {
+    // 时间字符串
+    private static String systemDate;
+    // 全部时间信息
+    private static String fullTime;
+    // 时间对象
+    static Date date = null;
+
+    /**
+     * 获取时间日期
+     * return
+     */
+    public static String getDate() {
+        date = new Date();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        systemDate = simpleDateFormat.format(date);
+        return systemDate;
+    }
+
+    /**
+     * 时间常量转日期
+     * @param time 时间常量
+     * return
+     */
+    public static String getDateFromTime(long time) {
+        date = new Date(time);
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        systemDate = simpleDateFormat.format(date);
+        return systemDate;
+    }
+
+    /**
+     * 获取时分秒HH:mm:ss
+     * return
+     */
+    public static String getFullTime() {
+        date = new Date();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
+        fullTime = simpleDateFormat.format(date);
+        return fullTime;
+    }
+
+    /**
+     * 格式化时间常量为yyyyMMddHHmmss
+     * @param time 时间常量
+     * return
+     */
+    public static String getFullTimeFromTime(long time) {
+        date = new Date(time);
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+        fullTime = simpleDateFormat.format(date);
+        return fullTime;
+    }
+
+    /**
+     * 获取时间信息 yyyy-MM-dd HH:mm:ss
+     * return
+     */
+    public static String getDataTime() {
+        date = new Date();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
+                "yyyy-MM-dd HH:mm:ss");
+        fullTime = simpleDateFormat.format(date);
+        return fullTime;
+    }
+
+    /**
+     * 简要格式时间HH:mm
+     * return
+     */
+    public static String getShotDataTime() {
+        date = new Date();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
+                "HH:mm");
+        fullTime = simpleDateFormat.format(date);
+        return fullTime;
+    }
+
+    /**
+     * 获取时间信息 yyyyMMddHHmmss
+     * return
+     */
+    public static String getTime() {
+        date = new Date();
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+
+        fullTime = simpleDateFormat.format(date);
+
+        return fullTime;
+    }
+
+
+    /**
+     * 获取时间信息 yyyyMMddHH
+     * return
+     */
+    public static String getTimeyyyyMMddHH() {
+        date = new Date();
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHH");
+
+        fullTime = simpleDateFormat.format(date);
+
+        return fullTime;
+    }
+
+    /**
+     * 获取时间信息 yyyyMMddHHmmssSSS
+     * return
+     */
+    public static String getTimeSSS() {
+        Date date = new Date();
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+
+        fullTime = simpleDateFormat.format(date);
+
+        return fullTime;
+    }
+
+    /**
+     * 获取时间信息 yyyy-MM-dd HH:mm:ss:SSS
+     * return
+     */
+    public static String getTimeMill() {
+        date = new Date();
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+
+        fullTime = simpleDateFormat.format(date);
+
+        return fullTime;
+    }
+
+    /**
+     * 获取时间信息 yyyy-MM-dd HH:mm:ss
+     * return
+     */
+    public static Date getNowDateShort() {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(currentTime);
+        ParsePosition pos = new ParsePosition(8);
+        Date currentTime_2 = formatter.parse(dateString, pos);
+        return currentTime_2;
+    }
+
+    /**
+     * 将yyyyMMddHHmmss转yyyy-MM-dd HH:mm:ss
+     * @param date 时间字符串
+     * return
+     */
+    public static String dateToSimpleDate(String date) throws ParseException {
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
+        Date dDate = format.parse(date);
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String reTime = format2.format(dDate);
+        return reTime;
+    }
+
+    /**
+     * 将yyyyMMddHHmmss转yyyy年MM月dd日
+     * @param date 时间字符串
+     * return
+     */
+    public static String dateToChineseDate(String date) throws ParseException {
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
+        Date dDate = format.parse(date);
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月dd日");
+        String reTime = format2.format(dDate);
+        return reTime;
+    }
+
+    /**
+     * 将yyyy-MM-dd HH:mm:ss.SSS转换为yyyyMMddHHmmssSSS
+     * return
+     */
+    public static String TimePointSSSToTime(String date) throws ParseException{
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+        Date dDate = format.parse(date);
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+        String reTime = format2.format(dDate);
+        return reTime;
+    }
+
+    /**
+     * 将yyyy.MM.dd/HH时转yyyy-MM-dd HH:mm:ss
+     * @param date 时间字符串
+     * return
+     */
+    public static String dateToSimpleDate2(String date) throws ParseException {
+        SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd/HH时");
+        Date dDate = format.parse(date);
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String reTime = format2.format(dDate);
+        return reTime;
+    }
+
+
+    /**
+     * 将yyyyMMddHHmmss转yyyy.MM.dd/HH时
+     * @param date 时间字符串
+     * return
+     */
+    public static String dateToDialogTime(String date) throws ParseException {
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
+        Date dDate = format.parse(date);
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyy.MM.dd/HH时");
+        String reTime = format2.format(dDate);
+        return reTime;
+    }
+
+    /**
+     * 将yyyyMMddHHmmss转yyyy-MM-dd HH:mm:ss:SSS
+     * @param date 时间字符串
+     * return
+     */
+    public static String dateToSimpleDateSSS(String date) throws ParseException {
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
+        Date dDate = format.parse(date);
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+        String reTime = format2.format(dDate);
+        return reTime;
+    }
+
+    /**
+     * 将yyyyMMddHHmmssSSS转yyyy-MM-dd HH:mm:ss:SSS
+     * @param date 时间字符串
+     * return
+     */
+    public static String iosDateToSimpleDateSSS(String date) throws ParseException {
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+        Date dDate = format.parse(date);
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+        String reTime = format2.format(dDate);
+        return reTime;
+    }
+
+    /**
+     * 将yyyyMMddHHmmssSSS转yyyy-MM-dd HH:mm:ss
+     * @param date 时间字符串
+     * return
+     */
+    public static String iosDateToSimpleDate(String date) throws ParseException {
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+        Date dDate = format.parse(date);
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String reTime = format2.format(dDate);
+        return reTime;
+    }
+
+    /**
+     * 获取当前时间yyyy-MM-dd HH:mm:ss
+     * return
+     */
+    public static Date getNowDate() throws ParseException {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(currentTime);
+        ParsePosition pos = new ParsePosition(8);
+        Date currentTime_2 = formatter.parse(dateString);
+        return currentTime_2;
+    }
+
+    /**
+     * 将时间常量转字符串HHmmss.SSS
+     * @param l 时间常量
+     * return
+     */
+    public static String getTime(long l) {
+        if (l > 0) {
+            long utcL = l - 28800;
+            SimpleDateFormat sdf = new SimpleDateFormat("HHmmss.SSS");
+            return sdf.format(utcL);
+        }
+        return null;
+    }
+
+
+    /**
+     * 将时间常量转字符串yyyyMMddHHmmssSSS
+     * @param l 时间常量
+     * return
+     */
+    public static String getDateSimpleTime(long l) {
+        if (l > 0) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            return sdf.format(l);
+        }
+        return null;
+    }
+
+    /**
+     * 将时间常量转字符串yyyy-MM-dd HH:mm:ss:SSS
+     * @param l 时间常量
+     * return
+     */
+    public static String getDateSimpleTimeSSS(long l) {
+        if (l > 0) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+            return sdf.format(l);
+        }
+        return null;
+    }
+
+    /**
+     * 格式化时间
+     *
+     * @param l
+     * @return yyyyMMddHH:mm:ss:SSS
+     */
+    public static String getDateTimeSSS(long l) {
+        if (l > 0) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH:mm:ss:SSS");
+            return sdf.format(l);
+        }
+        return null;
+    }
+
+
+    /**
+     * 将yyyyMMddHHmmss转long
+     *
+     * @param date
+     * @return
+     */
+    public static long getTimeInfo(String date) {
+        if (date == null || date.equals(""))
+            return 0;
+        try {
+            String time = dateToSimpleDate(date);
+            long timeL = getTime(time);
+            return timeL;
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 将yyyy-MM-dd HH:mm:ss时间转常量
+     *
+     * @param date
+     * @return
+     */
+    public static long getTime(String date) {
+        long changeDate = 0;
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        try {
+            Date currentDate = formatter.parse(date);
+            changeDate = currentDate.getTime();
+            if (changeDate != 0) {
+                return changeDate;
+            }
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 将yyyy-MM-dd HH:mm:ss时间转常量
+     *
+     * @param date
+     * @return
+     */
+    public static long getPicTime(String date) {
+        long changeDate = 0;
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
+        try {
+            Date currentDate = formatter.parse(date);
+            changeDate = currentDate.getTime();
+            if (changeDate != 0) {
+                return changeDate;
+            }
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 将yyyy-MM-dd HH:mm:ss.SSS时间转常量
+     *
+     * @param date
+     * @return
+     */
+    public static long getTimePointSSS(String date) {
+        long changeDate = 0;
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+        try {
+            Date currentDate = formatter.parse(date);
+            changeDate = currentDate.getTime();
+            if (changeDate != 0) {
+                return changeDate;
+            }
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 将yyyyMMddHHmmss时间转常量
+     *
+     * @param date
+     * @return
+     */
+    public static long getTimePoint(String date) {
+        long changeDate = 0;
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
+        try {
+            Date currentDate = formatter.parse(date);
+            changeDate = currentDate.getTime();
+            if (changeDate != 0) {
+                return changeDate;
+            }
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 将yyyy-MM-dd HH:mm:ss:SSS时间转常量
+     *
+     * @param date
+     * @return
+     */
+    public static long getTimeSSS(String date) {
+        long changeDate = 0;
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+        try {
+            Date currentDate = formatter.parse(date);
+            changeDate = currentDate.getTime();
+            if (changeDate != 0) {
+                return changeDate;
+            }
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 将yyyyMMddHHmmssSSS时间转常量
+     *
+     * @param date
+     * @return
+     */
+    public static long getTrackTimeSSS(String date) {
+        long changeDate = 0;
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+        try {
+            Date currentDate = formatter.parse(date);
+            changeDate = currentDate.getTime();
+            if (changeDate != 0) {
+                return changeDate;
+            }
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 对比两个时间格式是否超过3000m
+     *
+     * @param startDate
+     *          起始时间
+     *@param endDate
+     *          结束时间
+     * @return  true 是 false 否
+     */
+    public static boolean isTimeOut(long startDate, long endDate)
+            throws ParseException {
+        long result = startDate - endDate;
+        if (result > 300000 || result < -300000) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 对比两个时间格式是否超过3000m
+     *
+     * @param startDate
+     *          起始时间
+     *@param endDate
+     *          结束时间
+     *@param dTime
+     *             时间常量
+     * @return  true 是 false 否
+     */
+    public static boolean isTimeOut(long startDate, long endDate, long dTime)
+            throws ParseException {
+        long result = startDate - endDate;
+        if (result > dTime || result < -dTime) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 对比两个时间间隔多少天yyyy-MM-dd
+     *
+     * @param date1
+     *          起始时间
+     *@param date2
+     *          结束时间
+     * @return
+     *
+     */
+    public static int getDateSpan(String date1, String date2) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            Date start = formatter.parse(date1);
+            Date end = formatter.parse(date2);
+            long span = end.getTime() - start.getTime();
+            float day = span / ((float) 1000 * 3600 * 24);
+            return (int) day;
+        } catch (ParseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+
+    /**
+     * 获取照片的时间
+     * return
+     */
+    public static String getYYYYMMDDDate() {
+        date = new Date();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
+        systemDate = simpleDateFormat.format(date);
+        return systemDate;
+    }
+
+    /**
+     * 获取照片的时间 yyyy年MM月dd日
+     * return  YYYYMMDDD
+     */
+    public static String getYYYYMMDDDateChinese() {
+        date = new Date();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
+        systemDate = simpleDateFormat.format(date);
+        return systemDate;
+    }
+
+    /**
+     * yyyy年MM月dd日 转date
+     *
+     * @param dateString
+     * @return
+     */
+    public static Date stringYYYYMMDDHHToDate(String dateString) {
+        try {
+            SimpleDateFormat sim = new SimpleDateFormat("yyyy/MM/dd/HH时");
+            Date ticDate = sim.parse(dateString);
+            return ticDate;
+        } catch (Exception e) {
+
+        }
+        return null;
+    }
+
+    /**
+     * 当前时间前几天时间
+     * @param day
+     *          天数
+     * return
+     */
+    public static String getCurrentDateBefore(int day) {
+        date = new Date();
+        Calendar now = Calendar.getInstance();
+        now.setTime(date);
+        now.set(Calendar.DATE, now.get(Calendar.DATE) - day);
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
+        systemDate = simpleDateFormat.format(now.getTime());
+        return systemDate;
+    }
+
+    /**
+     * 当前时间前几天时间
+     * @param day
+     *          天数
+     * return
+     */
+    public static String getCurrentDateAfter(String time,int day) {
+        try{
+            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHH");
+            Date dDate = format.parse(time);
+            Calendar now = Calendar.getInstance();
+            now.setTime(dDate);
+            now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
+            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
+            systemDate = simpleDateFormat.format(now.getTime());
+        }catch (Exception e){
+
+        }
+
+        return systemDate;
+    }
+
+    /**
+     * 获取时间
+     * @param time
+     *          时间
+     * return yyyy.MM.dd
+     */
+    public static String getDateYYMMDD(String time) {
+        try {
+            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
+            Date dDate = format.parse(time);
+            SimpleDateFormat format2 = new SimpleDateFormat("yyyy.MM.dd");
+            String reTime = format2.format(dDate);
+            return reTime;
+        } catch (ParseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取时间
+     * @param time
+     *          时间
+     * return yyyy.MM.dd
+     */
+    public static String getDateYYMMDDPoint(String time) throws Exception{
+
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
+        Date dDate = format.parse(time);
+
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyy.MM.dd");
+        String reTime = format2.format(dDate);
+
+        return reTime;
+
+    }
+
+    /**
+     * 获取时间
+     * @param time yyyyMMddHHmmss
+     * return HH:mm:ss
+     */
+    public static String getDateHHMMSS(String time) {
+        try {
+            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
+            Date dDate = format.parse(time);
+            SimpleDateFormat format2 = new SimpleDateFormat("HH:mm:ss");
+            String reTime = format2.format(dDate);
+            return reTime;
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取当前起始时间
+     * return yyyyMMddHHmmss
+     */
+    public static String getCurrentDataStartTimeStr() {
+
+        return getYYYYMMDDDate() + "000000";
+    }
+
+    /**
+     * 获取当天结束时间
+     * return yyyyMMddHHmmss
+     */
+    public static String getCurrentDataEndTimeStr() {
+
+        SimpleDateFormat format = null;
+        Date date = null;
+        Calendar myDate = Calendar.getInstance();
+        myDate.add(Calendar.DAY_OF_MONTH, 1);
+        date = myDate.getTime();
+        format = new SimpleDateFormat("yyyyMMdd000000");
+
+        return format.format(date);
+    }
+
+
+    public static int getDateSpanYYMMDDHHMMSS(String date1, String date2) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
+        try {
+            Date start = formatter.parse(date1);
+            Date end = formatter.parse(date2);
+            long span = end.getTime() - start.getTime();
+            float ss = Math.abs(span);
+            return (int) ss;
+        } catch (ParseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    public static int getDateSpanIOSYYMMDDHHMMSSSSS(String date1, String date2) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+        try {
+            Date start = formatter.parse(date1);
+            Date end = formatter.parse(date2);
+            long span = end.getTime() - start.getTime();
+            float ss = Math.abs(span);
+            return (int) ss;
+        } catch (ParseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 获取时间
+     * return
+     */
+    public static String toDateYYMMDDHHSSMM(String time) {
+        try {
+            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
+            Date dDate = format.parse(time);
+            SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
+            String reTime = format2.format(dDate);
+            return reTime;
+        } catch (ParseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 字符串格式时间转成Date格式
+     *
+     * @param dateString
+     * @return
+     */
+    public static Date stringToDate(String dateString) {
+        try {
+            SimpleDateFormat sim = new SimpleDateFormat("yyyyMMddHHmmss");
+            Date ticDate = sim.parse(dateString);
+            return ticDate;
+        } catch (Exception e) {
+
+        }
+        return null;
+    }
+
+    /**
+     * 字符串格式时间转成Date格式
+     *
+     * @param dateString
+     * @return
+     */
+    public static Date stringFullTimeToDate(String dateString) {
+        try {
+            SimpleDateFormat sim = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            Date ticDate = sim.parse(dateString);
+            return ticDate;
+        } catch (Exception e) {
+
+        }
+        return null;
+    }
+
+    /**
+     * 判断两个日期相差天数
+     * 大的日期放后面
+     *
+     * @param date1
+     * @param date2
+     * @return
+     */
+    public static int differentDays(Date date1, Date date2) {
+        int days = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
+        return days;
+    }
+}
diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt
index cb8bb99c..89b88868 100644
--- a/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt
+++ b/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt
@@ -33,7 +33,7 @@ open class PermissionsActivity : BaseActivity() {
         if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
             permissionList.add(Permission.ACCESS_BACKGROUND_LOCATION)
         }
-        XXPermissions.with(this)
+/*        XXPermissions.with(this)
             // 申请单个权限
             .permission(permissionList)
             // 设置权限请求拦截器(局部设置)
@@ -73,7 +73,7 @@ open class PermissionsActivity : BaseActivity() {
                         onPermissionsDenied()
                     }
                 }
-            })
+            })*/
     }
 
     /**
diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt
index 4126123b..852f92f8 100644
--- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt
+++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt
@@ -1,12 +1,10 @@
 package com.navinfo.omqs.ui.activity.map
 
 import android.os.Bundle
-import android.provider.ContactsContract.Contacts
-import android.util.Log
 import androidx.activity.viewModels
 import androidx.core.view.WindowCompat
 import androidx.databinding.DataBindingUtil
-import androidx.lifecycle.viewModelScope
+import com.blankj.utilcode.util.ToastUtils
 import com.navinfo.collect.library.map.NIMapController
 import com.navinfo.omqs.Constant
 import com.navinfo.omqs.R
@@ -83,4 +81,11 @@ class MainActivity : BaseActivity() {
         binding.mainActivityDrawer.open()
     }
 
+    /**
+     * 打开相机预览
+     */
+    fun openCamera() {
+        binding!!.viewModel!!.onClickCameraButton(this)
+    }
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt
index c052a0f7..8cd97909 100644
--- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt
+++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt
@@ -1,12 +1,18 @@
 package com.navinfo.omqs.ui.activity.map
 
+import android.content.Context
+import android.content.DialogInterface
 import android.util.Log
+import android.view.View
 import androidx.lifecycle.ViewModel
+import com.blankj.utilcode.util.ToastUtils
 import com.navinfo.collect.library.map.NIMapController
+import org.videolan.libvlc.LibVlcUtil
+import com.navinfo.omqs.R
+import com.navinfo.omqs.ui.dialog.CommonDialog
+import com.navinfo.omqs.ui.manager.TakePhotoManager
 import dagger.hilt.android.lifecycle.HiltViewModel
-import dagger.hilt.android.scopes.ActivityRetainedScoped
 import javax.inject.Inject
-import javax.inject.Singleton
 
 /**
  * 创建Activity全局viewmode
@@ -16,6 +22,7 @@ class MainViewModel @Inject constructor(
     private val mapController: NIMapController,
 ) : ViewModel() {
 
+    private var mCameraDialog: CommonDialog? = null
 
     /**
      * 点击我的位置,回到我的位置
@@ -27,4 +34,36 @@ class MainViewModel @Inject constructor(
     override fun onCleared() {
         super.onCleared()
     }
+
+    //点击相机按钮
+    fun onClickCameraButton(context: Context){
+
+        Log.e("qj", LibVlcUtil.hasCompatibleCPU(context).toString())
+
+        ToastUtils.showShort("点击了相机")
+
+        if (mCameraDialog == null) {
+            mCameraDialog = CommonDialog(context, context.resources.getDimension(R.dimen.head_img_width).toInt() * 3 + context.resources.getDimension(R.dimen.ten).toInt() + context.resources.getDimension(R.dimen.twenty_four).toInt(), context.resources.getDimension(R.dimen.head_img_width).toInt() + 10, 1)
+            mCameraDialog!!.setCancelable(true)
+        }
+        mCameraDialog!!.openCamear(mCameraDialog!!.getmShareUtil().continusTakePhotoState)
+        mCameraDialog!!.show()
+        mCameraDialog!!.setOnDismissListener(DialogInterface.OnDismissListener {
+            mCameraDialog!!.hideLoading()
+            mCameraDialog!!.stopVideo()
+            try {
+                if (!mCameraDialog!!.getmShareUtil().connectstate){
+                    mCameraDialog!!.updateCameraResources(1, mCameraDialog!!.getmDeviceNum())
+                }
+                TakePhotoManager.getInstance().getCameraVedioClent(mCameraDialog!!.getmDeviceNum()).StopSearch()
+            } catch (e: Exception) {
+            }
+        })
+        mCameraDialog!!.setOnShowListener(DialogInterface.OnShowListener {
+            mCameraDialog!!.initmTakePhotoOrRecord(mCameraDialog!!.getmShareUtil().selectTakePhotoOrRecord)
+            if (!mCameraDialog!!.isShowVideo && mCameraDialog!!.getmShareUtil().connectstate && mCameraDialog!!.getmShareUtil().continusTakePhotoState) {
+                mCameraDialog!!.playVideo()
+            }
+        })
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/navinfo/omqs/ui/dialog/CommonDialog.java b/app/src/main/java/com/navinfo/omqs/ui/dialog/CommonDialog.java
new file mode 100644
index 00000000..43567e82
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/dialog/CommonDialog.java
@@ -0,0 +1,1608 @@
+package com.navinfo.omqs.ui.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.volley.VolleyError;
+import com.navinfo.collect.library.garminvirbxe.CameraGarminVirbXE;
+import com.navinfo.collect.library.garminvirbxe.CameraEventListener;
+import com.navinfo.collect.library.sensor.ISensor.enmSignalQuality;
+import com.navinfo.collect.library.sensor.ISensor.enmConnectionStatus;
+import com.navinfo.collect.library.sensor.ISensor.SensorWorkingMode;
+import com.navinfo.collect.library.garminvirbxe.SensorParams;
+import com.navinfo.collect.library.garminvirbxe.HostBean;
+import com.navinfo.omqs.Constant;
+import com.navinfo.omqs.R;
+import com.navinfo.omqs.system.SystemConstant;
+import com.navinfo.omqs.system.SystemDateTime;
+import com.navinfo.omqs.ui.activity.map.MainActivity;
+import com.navinfo.omqs.ui.manager.TakePhotoManager;
+import com.navinfo.omqs.ui.other.BaseToast;
+import com.navinfo.omqs.util.FileUtils;
+import com.navinfo.omqs.util.NetUtils;
+import com.navinfo.omqs.util.ShareUtil;
+
+import org.videolan.libvlc.EventHandler;
+import org.videolan.libvlc.IVideoPlayer;
+import org.videolan.libvlc.LibVLC;
+import org.videolan.vlc.Util;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+
+/**
+ * 公共相机对话框
+ *
+ * @author chentao
+ */
+public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVideoPlayer {
+    /**
+     * 上下文环境
+     */
+    private Context context;
+    /**
+     * 拍照控制类
+     */
+    private TakePhotoManager takephotoManager;
+    /**
+     * 相机事件回调
+     */
+    private CameraEventListener listener;
+
+
+    /**
+     * 对话框取消按钮
+     */
+    private ImageView mCancelDialog;
+    /**
+     * 开始/结束拍照按钮
+     */
+    private CheckBox mStartOrEndTakePicture;
+    /**
+     * 一键连接按钮
+     */
+    private TextView mOneBtConnect;
+    /**
+     * GPS连接提示
+     */
+    private TextView mGpsTv;
+
+    /**
+     * 选择使用默认相机还是外接相机
+     */
+    private CheckBox mSelectCamera;
+    /**
+     * 选择录像还是拍照
+     */
+    private CheckBox mTakePhotoOrRecord;
+    /**
+     * 选择相机保持的状态
+     */
+    private boolean bl;
+    /**
+     * 连续拍照的状态
+     */
+    private boolean conbl;
+
+    /**
+     * 录像还是拍照bl
+     */
+    private boolean recordOrTaKebl;
+
+    //相机模式
+    private int mMode;
+
+    //true连接成功,false未连接成功
+    public boolean connectstate = false;
+
+    //true 可点击,false不可点击
+    private boolean click_state = true;
+
+    private boolean isShowVideo;
+    private SurfaceView mSurfaceView;//展示视频的surfaceView
+    private LinearLayout mSurfaceBgLayout;
+    private ImageView mImgView;
+    private LibVLC mMediaPlayer;
+    private SurfaceHolder mSurfaceHolder;
+    private View mLoadingView;
+    private int mVideoHeight;
+    private int mVideoWidth;
+    private int mVideoVisibleHeight;
+    private int mVideoVisibleWidth;
+    private int mSarNum;
+    private int mSarDen;
+    //存储状态信息
+    private ShareUtil mShareUtil;
+
+    private LoadingDialog videoLoadingProDlg = null;
+
+    private int mX, mY;
+    //相机对象
+    private HostBean mHostBean;
+
+    //设备号
+    private int mDeviceNum;
+
+    //是否点击取消
+    private boolean isCancel;
+
+    //开始校验时间
+    private long mStartCheckTime = 0;
+
+    //单拍模式照片名称
+    private String mSinglePhotoName;
+
+    //是否校验了时间
+    private boolean isCheckTime;
+
+    private static int COMMAND_CAMERA_SNAPPICTURE_SINGLE_COUNT = 0;
+
+    private static int COMMAND_CAMERA_MEDIAPLAY_ERROR_COUNT = 0;
+
+    private long mPreTime;
+    boolean isStartThread;
+    boolean isStartThread2;
+
+    public CommonDialog(Context context, int x, int y, int deviceNum) {
+        super(context, R.style.MyCustomDialog);
+        // TODO Auto-generated constructor stub
+        mX = x;
+        mY = y;
+        setmDeviceNum(deviceNum);
+        mShareUtil = new ShareUtil(context, deviceNum);
+        this.context = context;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        // TODO Auto-generated method stub
+        super.onCreate(savedInstanceState);
+        this.setContentView(R.layout.connect_out_camera);
+
+        mSurfaceView = (SurfaceView) findViewById(R.id.video);
+
+        mImgView = (ImageView) findViewById(R.id.video_defalut);
+        try {
+            mMediaPlayer = Util.getInstance().getLibVlcInstance();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        mSurfaceHolder = mSurfaceView.getHolder();
+        mSurfaceHolder.setFormat(PixelFormat.RGBX_8888);
+        mSurfaceHolder.addCallback(this);
+
+        EventHandler em = EventHandler.getInstance();
+        em.addHandler(mVlcHandler);
+
+        this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
+
+        mSurfaceView.setKeepScreenOn(true);
+
+        WindowManager.LayoutParams params = this.getWindow().getAttributes();
+        WindowManager wm = (WindowManager) context
+                .getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+        params.width = (int) (display.getWidth() * 0.3);
+        params.height = (int) (display.getHeight() * 0.8);
+        params.x = mX;
+        params.y = mY;
+        this.getWindow().setGravity(Gravity.LEFT | Gravity.TOP);
+        this.getWindow().setAttributes(params);
+
+        takephotoManager = TakePhotoManager.getInstance();
+
+        listener = new CameraEventListener() {
+
+            @Override
+            public void OnSignalQualityChanged(enmSignalQuality sq) {
+                // TODO Auto-generated method stub
+
+            }
+
+            @Override
+            public void OnSensorEvent() {
+                // TODO Auto-generated method stub
+
+            }
+
+            @Override
+            public void OnConnectionStatusChanged(enmConnectionStatus cs) {
+
+            }
+
+            @Override
+            public void OnConnectionStatusChanged(HostBean hostBean, enmConnectionStatus cs, int tag) {
+
+                if (tag != getmDeviceNum())
+                    return;
+
+                ImageView iv = (ImageView) ((MainActivity) context).findViewById(getResId());
+
+                iv.setBackgroundDrawable(null);
+
+                if (cs == enmConnectionStatus.CONNECTTED) {
+
+                    Log.e("AAA", "连接成功");
+
+                    updateCameraResources(0, getmDeviceNum());
+
+                    //当前是否开始录像或拍照
+                    if (mStartOrEndTakePicture != null) {
+
+                        conbl = mShareUtil.getContinusTakePhotoState();
+
+                        if (mStartOrEndTakePicture.isChecked() != conbl){
+                            mStartOrEndTakePicture.setChecked(conbl);
+                        }
+
+                    }
+
+                    if (conbl && isShowing()) {
+                        startGPSStatus();
+                    }else{
+                        //恢复按钮可用状态
+                        if(mStartOrEndTakePicture!=null)
+                            mStartOrEndTakePicture.setEnabled(true);
+                    }
+
+
+                } else if (cs == enmConnectionStatus.DISCONNECTTED) {
+
+                    connectionFailed("相机丢失连接,请检查网络是否畅通!");
+/*                    if (ShowMode.getInstance().getImageWorkMode().isStartWork()) {
+                        BaseToast.makeText(getContext(), "相机拍摄中断,图像作业已结束!", BaseToast.LENGTH_SHORT).show();
+                        ShowMode.getInstance().getImageWorkMode().endWork();
+                    }*/
+                } else if (cs == enmConnectionStatus.CONNECTTING) {
+
+                    Log.e("AAA", "连接中");
+                    connectstate = false;
+                    mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
+                    mOneBtConnect.setText("连接中");
+                    updateCameraResources(2, getmDeviceNum());
+
+                } else {
+                    connectstate = false;
+                    mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
+                    click_state = true;
+
+                    mOneBtConnect.setEnabled(click_state);
+                    mOneBtConnect.setPressed(false);
+                    mOneBtConnect.setText("一键连接");
+                    mStartOrEndTakePicture.setEnabled(false);
+                    mOneBtConnect.setBackgroundResource(R.drawable.btn_connect_bg_enabled);
+                    updateCameraResources(1, getmDeviceNum());
+
+                    Log.e("AAA", "未知返回");
+
+                    stopVideo();
+                }
+
+            }
+
+            @Override
+            public void OnContinuousPhototTimeLapseRateResponse(HostBean hostBean, int tag) {
+                if (tag != getmDeviceNum())
+                    return;
+                //再次启动命令
+                takephotoManager.StartRecording(mHostBean, getmDeviceNum());
+            }
+
+            @Override
+            public void OnContinuousPhototTimeLapseRateStartResponse(HostBean hostBean, int tag) {
+                if (tag != getmDeviceNum())
+                    return;
+
+                Message msg = new Message();
+                msg.what = 0x55;
+                mHandler.sendMessage(msg);
+            }
+
+            @Override
+            public void OnContinuousPhototTimeLapseRateStopResponse(HostBean hostBean, int tag) {
+                if (tag != getmDeviceNum())
+                    return;
+
+                //启动监控
+                if (connectstate && isShowing()) {
+                    playVideo();
+                    updateCameraResources(0, getmDeviceNum());
+                }
+            }
+
+            @Override  //单拍模式
+            public void OnContinuousPhototSingle(HostBean hostBean, final String url, final String name, int tag) {
+
+                if (tag != getmDeviceNum())
+                    return;
+
+                Log.i("OnGetGpsStatusResponse", "OnContinuousPhototSingle");
+
+
+                if (!TextUtils.isEmpty(url)) {
+
+                    Message msg = new Message();
+                    msg.what = HANDLER_BUFFER_START;
+                    mHandler.sendMessage(msg);
+
+                    new Thread(new Runnable() {
+                        @Override
+                        public void run() {
+
+
+                            Message msg = new Message();
+
+                            String picPath = Constant.DATA_PATH + "/" + SystemConstant.USER_ID + "/pic.jpg";
+
+                            //创建目录
+                            if(!new File(Constant.DATA_PATH + "/" + SystemConstant.USER_ID).exists()){
+                                new File(Constant.DATA_PATH + "/" + SystemConstant.USER_ID).mkdirs();
+                            }
+
+                            //多次获取照片信息,解决概率事件无法获取有效照片问题
+                            for (int i = 0; i < 5; i++) {
+                                if (new File(picPath).exists()) {
+                                    new File(picPath).delete();
+                                }
+
+                                FileUtils.saveImageToDisk(url, picPath);
+
+                                String time = FileUtils.getExifTime(picPath);
+
+                                Log.e("AAA", "获取单张拍照时间" + time+"次数"+i);
+                                if (!TextUtils.isEmpty(time)) {
+                                    long picTime = SystemDateTime.getPicTime(time);
+
+                                    long disTime = mStartCheckTime - picTime / 1000;
+
+                                    Log.i("qj", "OnGetMediaList" + disTime);
+
+                                    if (disTime < 30 && disTime > -30) {
+
+                                        mMode = mShareUtil.getTakeCameraMode();
+
+                                        //恢复模式
+                                        if (mMode == 0) {
+                                            if (takephotoManager.getCameraMode(getmDeviceNum()) != SensorWorkingMode.CAMERA_VEDIO_TIMELAPSE)
+                                                takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMERA_VEDIO_TIMELAPSE);
+                                        } else {
+                                            if (takephotoManager.getCameraMode(getmDeviceNum()) != SensorWorkingMode.CAMEAR_PHOTO_CONTINUOUS_PHOTO)
+                                                takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMEAR_PHOTO_CONTINUOUS_PHOTO);
+                                        }
+
+                                        try {
+                                            //延时1秒发送预览命令
+                                            Thread.sleep(1000);
+                                        } catch (Exception e) {
+
+                                        }
+                                        msg.what = 0x66;
+                                        mHandler.sendMessage(msg);
+                                        return;
+
+                                    }
+                                }
+                            }
+                            msg.what = 0x77;
+                            mHandler.sendMessage(msg);
+                        }
+                    }).start();
+
+                } else {
+                    BaseToast.makeText(context, "校验时间信息失败,请注意核对时间信息!", Toast.LENGTH_SHORT).show();
+                    mGpsTv.setVisibility(View.VISIBLE);
+                    mGpsTv.setText("请在设置中确保PAD/时区与相机/时区保持一致。");
+                }
+            }
+
+            @Override
+            public void OnGetMediaList(HostBean hostBean, String json, int tag) {
+                if (tag != getmDeviceNum())
+                    return;
+
+            }
+
+            @Override
+            public void requestError(HostBean hostBean, VolleyError e, CameraGarminVirbXE.enmCommandType commandType, int tag) {
+
+                if (tag != getmDeviceNum())
+                    return;
+
+                //如果是单拍命令异常时重新再次进行获取
+                if(commandType!=null&&commandType== CameraGarminVirbXE.enmCommandType.COMMAND_CAMERA_SNAPPICTURE_SINGLE&&!isCheckTime&&mOneBtConnect!=null&&mOneBtConnect.getText().toString().contains("断开连接")){
+
+                    COMMAND_CAMERA_SNAPPICTURE_SINGLE_COUNT ++;
+
+                    //连续尝试多次进行获取,如果多次失败则提示
+                    if(COMMAND_CAMERA_SNAPPICTURE_SINGLE_COUNT == 3){
+                        Message msg = new Message();
+                        msg.what = 0x77;
+                        mHandler.sendMessage(msg);
+                        COMMAND_CAMERA_SNAPPICTURE_SINGLE_COUNT = 0;
+                    }else{
+                        BaseToast.makeText(context,"重新获取时间信息。",Toast.LENGTH_SHORT).show();
+                        showLoading();
+                        //重新获取拍照时间
+                        takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMERA_PHOTO_SINGLE);
+                        //启动单拍模式开始校验时间
+                        takephotoManager.SnapShot(getmHostBean(),getmDeviceNum());
+                        //只要秒时间
+                        mStartCheckTime = new Date().getTime() / 1000;
+                    }
+                }
+
+                // BaseToast.makeText(context,"命令异常,请确认网络是否正常。",Toast.LENGTH_SHORT).show();
+
+            }
+
+            @Override
+            public void OnStopRecordResponse(HostBean hostBean, int tag) {
+                if (tag != getmDeviceNum())
+                    return;
+
+                //启动监控
+                if (connectstate && isShowing()) {
+                    playVideo();
+                    updateCameraResources(0, getmDeviceNum());
+                }
+
+
+            }
+
+            @Override
+            public void OnStatusResponse(HostBean hostBean, int tag) {
+
+                if (tag != getmDeviceNum())
+                    return;
+
+                updateCameraResources(0, getmDeviceNum());
+                connectstate = true;
+                mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
+                stopVideo();
+                mOneBtConnect.setPressed(true);
+                mOneBtConnect.setBackgroundResource(R.drawable.btn_red_disconnect_bg);
+                mOneBtConnect.setText("断开连接!");
+                //停止获取GPS状态
+                if (getmDeviceNum() == 1)
+                    isStartThread = false;
+                else
+                    isStartThread2 = false;
+                try {
+                    Thread.sleep(200);
+                } catch (InterruptedException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+                Log.i("chentao", "连接成功");
+                Log.e("AAA", "OnStatusResponse ok ");
+
+            }
+
+            @Override
+            public void OnStartRecordResponse(HostBean hostBean, int tag) {
+
+                if (tag != getmDeviceNum())
+                    return;
+
+                Message msg = new Message();
+                msg.what = 0x55;
+                mHandler.sendMessage(msg);
+
+            }
+
+            @Override
+            public void OnSnapPictureResponse(HostBean hostBean, Bitmap bitmap, String picName, int tag) {
+
+                if (tag != getmDeviceNum())
+                    return;
+
+                if (hostBean != null && mHostBean != null && hostBean.hardwareAddress.equals(mHostBean.hardwareAddress)) {
+
+                }
+            }
+
+            @Override
+            public void OnSearchResponse(int tag, ArrayList<HostBean> listIp) {
+
+                //判断标识
+                if (tag != getmDeviceNum())
+                    return;
+
+                Log.e("AAA", "搜索到完成");
+
+                if (listIp.size() > 0) {
+                    //已连接相机地址
+                    String connectstateMac = ShareUtil.getConnectstateMac(context);
+                    //存在连接设备
+                    if (!TextUtils.isEmpty(connectstateMac)) {
+                        boolean isConn = false;
+                        b:
+                        for (HostBean hostBean : listIp) {
+                            if (!hostBean.hardwareAddress.equalsIgnoreCase(connectstateMac)) {
+                                isConn = true;
+                                connection(hostBean);
+                                break b;
+                            }
+                        }
+                        if (!isConn) {
+                            connectionFailed("无可用设备");
+                        }
+                    } else {
+                        connection(listIp.get(0));
+                    }
+                } else {
+                    connectionFailed("相机丢失连接,请检查网络是否畅通!");
+                }
+            }
+
+            @Override
+            public void OnConnectStatusChanged(HostBean hostBean, enmConnectionStatus connectStatus, int tag) {
+                if (hostBean != null && mHostBean != null && hostBean.hardwareAddress.equals(mHostBean.hardwareAddress)) {
+
+                }
+            }
+
+            @Override
+            public void OnGetDeviceInfo(HostBean hostBean, String devicesId, int tag) {
+                // TODO Auto-generated method stub
+                if (hostBean != null && mHostBean != null && hostBean.hardwareAddress.equals(mHostBean.hardwareAddress)) {
+                    Log.e("AAA", "devicesId" + devicesId);
+                }
+            }
+
+            @Override
+            public void OnGetGpsStatusResponse(HostBean hostBean, boolean status, int tag) {
+
+                if (tag != getmDeviceNum())
+                    return;
+
+                try {
+
+                    if (mShareUtil.getContinusTakePhotoState() && !mStartOrEndTakePicture.isEnabled()) {
+
+                        if (status) {
+
+                            BaseToast.makeText(context, "成功获取相机GPS信号!正在校验时间信息。。。", Toast.LENGTH_SHORT).show();
+
+                            //获取GPS信号停止获取线程
+                            if (getmDeviceNum() == 1) {
+                                isStartThread = false;
+                            } else {
+                                isStartThread2 = false;
+                            }
+
+                            //相机GPS信号差,请稍等片刻,或将相机移到开发地带。
+                            if (!isCheckTime) {
+                                mGpsTv.setText("正在校验时区正确性,请耐心等待!");
+                                showLoading();
+                                mGpsTv.setVisibility(View.VISIBLE);
+                                //初始化
+                                COMMAND_CAMERA_SNAPPICTURE_SINGLE_COUNT = 0;
+                                takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMERA_PHOTO_SINGLE);
+                                //启动单拍模式开始校验时间
+                                takephotoManager.SnapShot(getmHostBean(),getmDeviceNum());
+                                //只要秒时间
+                                mStartCheckTime = new Date().getTime() / 1000;
+                            }
+                            Log.i("qj", "OnGetGpsStatusResponse启动时间校验");
+                        } else {
+                            mGpsTv.setText("相机GPS信号差,请稍等片刻,或将相机移到开发地带。");
+                            mGpsTv.setVisibility(View.VISIBLE);
+                            mStartOrEndTakePicture.setEnabled(status);
+                            mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, true);
+                        }
+
+                    }
+
+                } catch (Exception e) {
+                }
+            }
+        };
+
+        takephotoManager.setOnCameraEventChangeListener(listener);
+
+        bl = mShareUtil.getSelectCameraKind();
+
+        recordOrTaKebl = mShareUtil.getSelectTakePhotoOrRecord();
+
+        conbl = mShareUtil.getContinusTakePhotoState();
+
+        //初始化
+        init();
+
+        //添加监听器
+        addListeners();
+    }
+
+    //初始化
+    private void init() {
+
+        //拍照或录像
+        mTakePhotoOrRecord = (CheckBox) findViewById(R.id.takephoto_or_record);
+        mCancelDialog = (ImageView) findViewById(R.id.cancel_dialog);
+        mStartOrEndTakePicture = (CheckBox) findViewById(R.id.startorendtakepicture);
+        mOneBtConnect = (TextView) findViewById(R.id.one_bt_connect);
+        mGpsTv = (TextView) findViewById(R.id.gps_status_hint);
+        //是否为外设相机拍照
+        mSelectCamera = (CheckBox) findViewById(R.id.select_camera);
+
+        mMode = mShareUtil.getTakeCameraMode();
+
+        if (mMode == 0) {
+            recordOrTaKebl = true;
+            mTakePhotoOrRecord.setText("录像");
+            setmImgViewImageDrawable(0);
+            if (takephotoManager.getCameraMode(getmDeviceNum()) != SensorWorkingMode.CAMERA_VEDIO_TIMELAPSE)
+                takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMERA_VEDIO_TIMELAPSE);
+        } else {
+            recordOrTaKebl = false;
+            if (takephotoManager.getCameraMode(getmDeviceNum()) != SensorWorkingMode.CAMEAR_PHOTO_CONTINUOUS_PHOTO)
+                takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMEAR_PHOTO_CONTINUOUS_PHOTO);
+            mTakePhotoOrRecord.setText("拍照");
+            setmImgViewImageDrawable(1);
+        }
+
+        mSelectCamera.setChecked(bl);
+
+        mTakePhotoOrRecord.setChecked(recordOrTaKebl);
+
+        mOneBtConnect.setEnabled(click_state);
+
+        connectstate = mShareUtil.getConnectstate();
+
+        //当前为连接时启动已有的状态
+        if (connectstate) {
+            mOneBtConnect.setPressed(true);
+
+            mOneBtConnect.setBackgroundResource(R.drawable.btn_red_disconnect_bg);
+
+            mOneBtConnect.setText("断开连接!");
+
+            //启动或关闭拍照模式
+            mStartOrEndTakePicture.setChecked(conbl);
+
+            if (conbl) {
+
+                mStartOrEndTakePicture.setEnabled(false);
+                mHostBean = new HostBean();
+                mHostBean.hardwareAddress = mShareUtil.getTakeCameraMac();
+                mHostBean.ipAddress = mShareUtil.getTakeCameraIP();
+                takephotoManager.getCameraVedioClent(getmDeviceNum()).setmHostBean(mHostBean);
+
+                playVideo();
+
+                startGPSStatus();
+
+            } else {
+                mStartOrEndTakePicture.setEnabled(true);
+            }
+
+        }
+
+    }
+
+    /**
+     * 更新相机状态资源
+     */
+    public void updateCameraResources(int statusType, int indexClentCamera) {
+        int resId = R.id.main_activity_camera;
+
+        if (indexClentCamera == 2)
+            resId = R.id.main_activity_camera2;
+
+        Drawable drawable = context.getResources().getDrawable(R.mipmap.icon_page_video_a0);
+
+        ShareUtil shareUtil = new ShareUtil(context, indexClentCamera);
+        //0为录像模式
+        if (shareUtil.getTakeCameraMode() == 0) {
+            switch (statusType) {
+                case 0:
+                    drawable = context.getResources().getDrawable(R.mipmap.icon_page_video_a0);
+                    break;
+                case 1:
+                    drawable = context.getResources().getDrawable(R.mipmap.icon_page_video_a1);
+                    break;
+                case 2:
+                    drawable = context.getResources().getDrawable(R.mipmap.icon_page_video_a2);
+                    break;
+                case 3:
+                    drawable = context.getResources().getDrawable(R.mipmap.icon_page_video_a3);
+                    break;
+            }
+        } else {
+            switch (statusType) {
+                case 0:
+                    drawable = context.getResources().getDrawable(R.mipmap.icon_page_take_photo_a0);
+                    break;
+                case 1:
+                    drawable = context.getResources().getDrawable(R.mipmap.icon_page_take_photo_a1);
+                    break;
+                case 2:
+                    drawable = context.getResources().getDrawable(R.mipmap.icon_page_take_photo_a2);
+                    break;
+                case 3:
+                    drawable = context.getResources().getDrawable(R.mipmap.icon_page_take_photo_a3);
+                    break;
+            }
+        }
+
+
+        ImageView ivStatus = (ImageView) findViewById(resId);
+        if (ivStatus != null) {
+            try {
+                AnimationDrawable animation = (AnimationDrawable) ivStatus.getBackground();
+                if (animation.isRunning()) {
+                    animation.stop();
+                    ivStatus.setBackground(null);
+                }
+
+            } catch (Exception e) {
+
+            }
+            ivStatus.setImageDrawable(drawable);
+        }
+
+    }
+
+    public void updateCameraBackgroundResources(int drawable, int indexClentCamera) {
+        int resId = R.id.main_activity_camera;
+
+        if (indexClentCamera == 2)
+            resId = R.id.main_activity_camera2;
+
+        ImageView ivStatus = (ImageView) findViewById(resId);
+
+        if (ivStatus != null) {
+            String time = SystemDateTime.getDateSimpleTime(SystemDateTime.getTimeInfo(SystemDateTime.getTime()) - 0/*MainActivity.disGoogleTime*/);
+
+            ivStatus.setImageDrawable(null);
+
+            ivStatus.setBackgroundResource(drawable);
+
+            AnimationDrawable animation = (AnimationDrawable) ivStatus.getBackground();
+
+            animation.start();
+        }
+    }
+
+    //添加监听器
+    private void addListeners() {
+
+        //取消对话框按钮
+        mCancelDialog.setOnClickListener(new View.OnClickListener() {
+
+            @Override
+            public void onClick(View arg0) {
+                dismiss();
+
+            }
+        });
+        //打开/结束连拍
+        mStartOrEndTakePicture.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+
+            @Override
+            public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
+                if (connectstate) {
+
+                    Log.i("chentao", "打开/结束连拍:" + arg1);
+                    mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, arg1);
+
+                    if (!arg1) {
+
+                        stopVideoOrPicture();
+
+                    } else {
+
+                        takephotoManager.StopContinuousTakePhoto(mHostBean, getmDeviceNum());
+
+                        //重新運行
+                        startGPSStatus();
+
+                    }
+
+                } else {
+
+                    mStartOrEndTakePicture.setChecked(true);
+
+                    mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, true);
+
+                    BaseToast.makeText(context, "外接相机没有连接成功!不能进行连续拍照!", Toast.LENGTH_SHORT).show();
+                }
+
+            }
+        });
+        //一键连接按钮
+        mOneBtConnect.setOnClickListener(new View.OnClickListener() {
+
+            @Override
+            public void onClick(View arg0) {
+                if (connectstate) {
+
+                    connectstate = false;
+
+                    mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, true);
+
+                    mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
+
+                    mStartOrEndTakePicture.setChecked(true);
+
+                    //修改为禁用状态
+                    mStartOrEndTakePicture.setEnabled(false);
+
+                    //停止当前活动
+                    takephotoManager.StopContinuousTakePhoto(mHostBean, getmDeviceNum());
+
+                    mOneBtConnect.setBackgroundResource(R.drawable.btn_connect_bg_enabled);
+
+                    mOneBtConnect.setText("一键连接!");
+
+                    mOneBtConnect.setPressed(false);
+
+                    mGpsTv.setVisibility(View.GONE);
+
+                    mGpsTv.setText("相机GPS信号差,请稍等片刻,或将相机移到开发地带。");
+
+                    updateCameraResources(1, getmDeviceNum());
+
+                    stopVideo();
+
+                } else {
+                    if (mOneBtConnect.getText().toString().equals("连接中")) {
+                        mOneBtConnect.setText("一键连接!");
+                        mStartOrEndTakePicture.setEnabled(false);
+                        connectstate = false;
+                        takephotoManager.StopSearchNet(mHostBean,getmDeviceNum());
+                        mGpsTv.setVisibility(View.GONE);
+                        mGpsTv.setText("相机GPS信号差,请稍等片刻,或将相机移到开发地带。");
+                        updateCameraResources(1, getmDeviceNum());
+                    } else {
+
+                        if (NetUtils.getInstance().isExistWifi(false)) {
+                            //搜索相机
+                            takephotoManager.SearchNet(null, getmDeviceNum(), false);
+
+                            mOneBtConnect.setText("连接中");
+
+                            updateCameraResources(2, getmDeviceNum());
+
+                        } else {
+                            connectionFailed("相机丢失连接,请检查网络是否畅通!");
+                        }
+
+                    }
+
+                }
+
+            }
+        });
+        //选择相机
+        mSelectCamera.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+
+
+            @Override
+            public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
+                if (connectstate) {
+                    Log.i("chentao", "选择相机:" + arg1);
+                    mShareUtil.setSelectCameraKind(SystemConstant.USER_ID, arg1);
+                } else {
+                    mSelectCamera.setChecked(false);
+                    mShareUtil.setSelectCameraKind(SystemConstant.USER_ID, false);
+                    BaseToast.makeText(context, "外接相机没有连接成功!只能使用系统相机,谢谢!", Toast.LENGTH_SHORT).show();
+                }
+            }
+        });
+        /**
+         * 选择拍照或者录像
+         */
+        mTakePhotoOrRecord.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+
+            @Override
+            public void onCheckedChanged(CompoundButton arg0, final boolean isCheck) {
+
+                //if (mStartOrEndTakePicture.isChecked()) {
+                //点击取消重置按钮时不进行窗体提示
+                if (isCancel) {
+                    isCancel = false;
+                    return;
+                }
+
+                FirstDialog builder = new FirstDialog(context);
+                builder.setTitle("影响状态切换提示");
+
+                String status = null;
+
+                if (isCheck) {
+                    status = "录像";
+                    setmImgViewImageDrawable(0);
+                } else {
+                    status = "连拍";
+                    setmImgViewImageDrawable(1);
+                }
+
+                mTakePhotoOrRecord.setText(status);
+
+                builder.setMessage("切换影像状态为" + status);
+
+                builder.setPositiveButton("确认", new FirstDialog.OnClickListener() {
+
+                    @Override
+                    public void onClick(Dialog dialog, int arg1) {
+                        dialog.dismiss();
+
+                        //连接状态时先停止录像或者拍照状态
+                        if (connectstate) {
+                            //如果当前为工作状态,先停止
+                            if (!mShareUtil.getContinusTakePhotoState()) {
+                                stopVideoOrPicture();
+                            }
+
+                            //重置拍照按钮
+                            mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, true);
+                        }
+
+                        //设置另外一台相机状态
+                        ShareUtil shareUtilOther = new ShareUtil(context, getmDeviceNum() == 1 ? 2 : 1);
+
+                        //如果另外一个台处于连接并且开始录像或者拍照时需要停止运行
+                        if (shareUtilOther.getConnectstate() && !shareUtilOther.getContinusTakePhotoState()) {
+                            try {
+                                CameraGarminVirbXE cameraGarminVirbXE = takephotoManager.getCameraVedioClent(getmDeviceNum());
+                                cameraGarminVirbXE.StopRecording();
+
+                            } catch (Exception e) {
+
+                            }
+
+                        }
+
+                        shareUtilOther.setSelectTakePhotoOrRecord(SystemConstant.USER_ID, !isCheck);
+
+                        shareUtilOther.setContinusTakePhotoState(SystemConstant.USER_ID, true);
+
+                        mShareUtil.setSelectTakePhotoOrRecord(SystemConstant.USER_ID, isCheck);
+
+                        if (isCheck) {
+
+                            mTakePhotoOrRecord.setText("录像");
+                            setmImgViewImageDrawable(0);
+
+                            takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMERA_VEDIO_TIMELAPSE);
+
+                            mShareUtil.setTakeCameraMode(SystemConstant.USER_ID, 0);
+
+                            shareUtilOther.setTakeCameraMode(SystemConstant.USER_ID, 1);
+
+                        } else {
+
+                            mTakePhotoOrRecord.setText("拍照");
+                            setmImgViewImageDrawable(1);
+
+                            mShareUtil.setTakeCameraMode(SystemConstant.USER_ID, 1);
+
+                            shareUtilOther.setTakeCameraMode(SystemConstant.USER_ID, 0);
+
+                            takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMEAR_PHOTO_CONTINUOUS_PHOTO);
+
+                        }
+                        updateCameraStatusImg();
+                    }
+
+                });
+                builder.setNegativeButton("取消", new FirstDialog.OnClickListener() {
+                    @Override
+                    public void onClick(Dialog dialog, int which) {
+                        dialog.dismiss();
+                        isCancel = true;
+                        if (!isCheck) {
+                            mTakePhotoOrRecord.setText("录像");
+                            setmImgViewImageDrawable(0);
+                        } else {
+                            mTakePhotoOrRecord.setText("连拍");
+                            setmImgViewImageDrawable(1);
+                        }
+                        updateCameraStatusImg();
+                        mTakePhotoOrRecord.setChecked(!isCheck);
+                    }
+                });
+
+                builder.show();
+
+
+                //}
+                /*else {
+
+                    mTakePhotoOrRecord.setChecked(!isCheck);
+
+                    BaseToast.makeText(context, "请先停止当前活动!", Toast.LENGTH_SHORT).show();
+                }*/
+
+            }
+
+        });
+    }
+
+    //更新资源图标
+    private void updateCameraStatusImg() {
+        if (mShareUtil.getConnectstate()) {
+            updateCameraResources(0, getmDeviceNum());
+        } else {
+            updateCameraResources(1, getmDeviceNum());
+        }
+        ShareUtil shareUtilOther = new ShareUtil(context, getmDeviceNum() == 1 ? 2 : 1);
+        if (shareUtilOther.getConnectstate()) {
+            updateCameraResources(0, getmDeviceNum() == 1 ? 2 : 1);
+        } else {
+            updateCameraResources(1, getmDeviceNum() == 1 ? 2 : 1);
+        }
+    }
+
+    /**
+     * @param :
+     * @return :
+     * @method : connectionFailed
+     * @Author : xiaoxiao
+     * @Describe : 外接相机连接失败的处理
+     * @Date : 2018/5/14
+     */
+    private void connectionFailed(String msg) {
+        Log.e("AAA", "连接失败");
+        BaseToast.makeText(context, TextUtils.isEmpty(msg) ? "相机丢失连接,请检查网络是否畅通!" : msg, Toast.LENGTH_SHORT).show();
+
+        connectstate = false;
+        mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
+        mOneBtConnect.setPressed(false);
+        mOneBtConnect.setBackgroundResource(R.drawable.btn_connect_bg_enabled);
+        mOneBtConnect.setText("一键连接");
+        //增加按钮状态控制
+        mStartOrEndTakePicture.setEnabled(false);
+        updateCameraResources(1, getmDeviceNum());
+
+        hideLoading();
+
+        //齐济,连接中断了需要停止当前的拍照流程
+        mStartOrEndTakePicture.setChecked(false);
+    }
+
+    /**
+     * @param :
+     * @return :
+     * @method : isShowVideo
+     * @Author : xiaoxiao
+     * @Describe : 获取当前是否显示视频
+     * @Date : 2018/5/14
+     */
+    public boolean isShowVideo() {
+        return isShowVideo;
+    }
+
+    /**
+     * @param :
+     * @return :
+     * @method : playVideo
+     * @Author : xiaoxiao
+     * @Describe : 播放视频
+     * @Date : 2018/5/14
+     */
+    public void playVideo() {
+        try {
+
+            if (isShowVideo)
+                return;
+
+            if (NetUtils.getInstance().isExistWifi(false)) {
+                showLoading();
+
+                final String ip = mShareUtil.getTakeCameraIP();
+
+                if (TextUtils.isEmpty(ip))
+                    return;
+                final String httpIp = "rtsp://" + ip + "/livePreviewStream";
+                if (mMediaPlayer != null) {
+                    new Thread(new Runnable() {
+                        @Override
+                        public void run() {
+                            if(mMediaPlayer.isPlaying())
+                                mMediaPlayer.stop();
+                            int result = -1;
+                            try {
+                                result = mMediaPlayer.readMedia(httpIp);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                                result = -1;
+                            }
+                            Message msg = new Message();
+                            msg.what = 0x11;
+                            msg.arg1 = result;
+                            Log.e(CommonDialog.class.getName(), "result==" + result);
+                            mHandler.sendMessage(msg);
+                        }
+                    }).start();
+                }
+                isShowVideo = true;
+                mSurfaceView.setVisibility(View.VISIBLE);
+            } else {
+                BaseToast.makeText(context, "网络异常,请检查网络是否畅通!", Toast.LENGTH_SHORT).show();
+            }
+
+        } catch (Exception e) {
+            BaseToast.makeText(context, "网络异常,请检查网络是否畅通!", Toast.LENGTH_SHORT).show();
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * @param :
+     * @return :
+     * @method : stopVideo
+     * @Author : xiaoxiao
+     * @Describe : 停止播放视频
+     * @Date : 2018/5/14
+     */
+    public void stopVideo() {
+        isShowVideo = false;
+        if (mMediaPlayer != null) {
+            if(mMediaPlayer.isPlaying())
+                mMediaPlayer.stop();
+            mSurfaceView.setKeepScreenOn(false);
+            mSurfaceView.setBackgroundColor(getContext().getResources().getColor(R.color.bg_gray2));
+            mSurfaceView.setVisibility(View.GONE);
+            // mSurfaceBgLayout.setBackgroundColor(getContext().getResources().getColor(R.color.bg_gray2));
+        }
+        if (mImgView != null)
+            mImgView.setVisibility(View.VISIBLE);
+
+        //启动录像
+        if (connectstate && !mShareUtil.getContinusTakePhotoState()) {
+
+            takephotoManager.StartRecording(mHostBean, getmDeviceNum());
+        }
+    }
+
+    /**
+     * @param : arg1-打开true,关闭false
+     * @return :
+     * @method : openCamear
+     * @Author : xiaoxiao
+     * @Describe : 打开或关闭相机
+     * @Date : 2018/5/14
+     */
+    public void openCamear(boolean arg1) {
+        if (mStartOrEndTakePicture != null)
+            mStartOrEndTakePicture.setChecked(arg1);
+
+    }
+
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        mSurfaceHolder = holder;
+        if (mMediaPlayer != null) {
+            mMediaPlayer.attachSurface(holder.getSurface(), this, width, height);
+        }
+        if (width > 0) {
+            mVideoHeight = height;
+            mVideoWidth = width;
+        }
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.detachSurface();
+        }
+    }
+
+    @Override
+    public void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) {
+        mVideoHeight = height;
+        mVideoWidth = width;
+        mVideoVisibleHeight = visible_height;
+        mVideoVisibleWidth = visible_width;
+        mSarNum = sar_num;
+        mSarDen = sar_den;
+        mHandler.removeMessages(HANDLER_SURFACE_SIZE);
+        mHandler.sendEmptyMessage(HANDLER_SURFACE_SIZE);
+    }
+
+    private static final int HANDLER_BUFFER_START = 1;
+    private static final int HANDLER_BUFFER_END = 2;
+    private static final int HANDLER_SURFACE_SIZE = 3;
+
+    private static final int SURFACE_BEST_FIT = 0;
+    private static final int SURFACE_FIT_HORIZONTAL = 1;
+    private static final int SURFACE_FIT_VERTICAL = 2;
+    private static final int SURFACE_FILL = 3;
+    private static final int SURFACE_16_9 = 4;
+    private static final int SURFACE_4_3 = 5;
+    private static final int SURFACE_ORIGINAL = 6;
+    private int mCurrentSize = SURFACE_BEST_FIT;
+
+    private Handler mVlcHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg == null || msg.getData() == null)
+                return;
+            int key = msg.getData().getInt("event");
+            Log.e("AAA", "key=="+key);
+            switch (key) {
+                case EventHandler.MediaPlayerPositionChanged:
+                    Log.e("AAA", "MediaPlayerPositionChanged");
+                    break;
+                case EventHandler.MediaPlayerPlaying:
+                    mHandler.removeMessages(HANDLER_BUFFER_END);
+                    mHandler.sendEmptyMessage(HANDLER_BUFFER_END);
+                    Log.e("AAA", "MediaPlayerPlaying");
+/*                    if(mShareUtil!=null&&mShareUtil.getConnectstate())
+                        updateCameraResources(((MainActivity) context).getResources().getDrawable(R.drawable.icon_page_video_a0), getResId());*/
+                    break;
+                case EventHandler.MediaPlayerEndReached:
+                    Log.e("AAA", "MediaPlayerEndReached");
+                    //播放完成
+                    break;
+                case EventHandler.MediaPlayerStopped:
+                    Log.e("AAA", "MediaPlayerStopped");
+                    break;
+                case EventHandler.MediaPlayerEncounteredError:
+                    Log.e("AAA", "MediaPlayerEncounteredError"+COMMAND_CAMERA_MEDIAPLAY_ERROR_COUNT);
+                    COMMAND_CAMERA_MEDIAPLAY_ERROR_COUNT ++;
+                    //预览失败
+                    if(COMMAND_CAMERA_MEDIAPLAY_ERROR_COUNT==3){
+                        Message msg1 = new Message();
+                        msg1.what = 0x11;
+                        msg1.arg1 = -1;
+                        mHandler.sendMessage(msg1);
+                        COMMAND_CAMERA_MEDIAPLAY_ERROR_COUNT = 0;
+                    }else{
+                        //重新尝试连接
+                        isShowVideo = false;
+                        //增加预览失败处理逻辑
+                        playVideo();
+                    }
+                    break;
+            }
+
+        }
+    };
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case HANDLER_BUFFER_START:
+                    showLoading();
+                    break;
+                case HANDLER_BUFFER_END:
+                    mSurfaceView.setBackgroundColor(getContext().getResources().getColor(com.navinfo.collect.library.R.color.transp));
+                    mImgView.setVisibility(View.GONE);
+                    //重置异常计数器
+                    COMMAND_CAMERA_MEDIAPLAY_ERROR_COUNT = 0;
+                    hideLoading();
+                    break;
+                case HANDLER_SURFACE_SIZE:
+                    changeSurfaceSize();
+                    break;
+                case 0x55:
+                    int drawable = R.drawable.pop_camera_img;
+                    try {
+                        if (TakePhotoManager.getInstance().getCameraVedioClent(getmDeviceNum()).GetMode() == SensorWorkingMode.CAMEAR_PHOTO_CONTINUOUS_PHOTO)
+                            drawable = R.drawable.pop_camera_take_photo_img;
+                    } catch (Exception e) {
+
+                    }
+                    updateCameraBackgroundResources(drawable, getmDeviceNum());
+                    break;
+                case 0x11:
+                    if (msg.arg1 >= 0) {
+                        //Toast.makeText(getContext(),"预览成功",Toast.LENGTH_SHORT).show();
+                    } else {
+                        hideLoading();
+                        Toast.makeText(getContext(), "预览失败", Toast.LENGTH_SHORT).show();
+                    }
+                    break;
+                case 0x66:
+                    if(videoLoadingProDlg!=null&&videoLoadingProDlg.isShowing())
+                        videoLoadingProDlg.setText("成功获取时间,正在加载预留画面");
+                    //相机GPS信号差,请稍等片刻,或将相机移到开发地带。
+                    mGpsTv.setText("相机GPS信号差,请稍等片刻,或将相机移到开发地带。");
+                    mGpsTv.setVisibility(View.GONE);
+                    isCheckTime = true;
+                    //没有开始录像或者拍照时启动GPS获取,判断连接是否正常
+                    if (getmDeviceNum() == 1) {
+                        isStartThread = true;
+                    } else {
+                        isStartThread2 = true;
+                    }
+                    mStartOrEndTakePicture.setEnabled(true);
+                    //开启预览模式
+                    playVideo();
+                    Log.e("checkTime", "校验成功");
+                    break;
+                case 0x77:
+                    hideLoading();
+                    Log.e("checkTime", "校验失败");
+                    mGpsTv.setVisibility(View.VISIBLE);
+                    mGpsTv.setText("请在设置中确保PAD/时区与相机/时区保持一致或重新连接相机。");
+                    BaseToast.makeText(context, "请在设置中确保PAD/时区与相机/时区保持一致。", Toast.LENGTH_SHORT).show();
+                    break;
+
+            }
+        }
+    };
+
+    /**
+     * @param :
+     * @return :
+     * @method : showLoading
+     * @Author : xiaoxiao
+     * @Describe : 显示等待对话框
+     * @Date : 2018/5/14
+     */
+    private void showLoading() {
+        try {
+
+            if (videoLoadingProDlg == null)
+                videoLoadingProDlg = new LoadingDialog(getContext());
+
+
+            if (!videoLoadingProDlg.isShowing()) {
+                videoLoadingProDlg.setText("正在获取中...");
+                videoLoadingProDlg.setOnCancelListener(null);
+                videoLoadingProDlg.show();
+            }
+
+        } catch (Exception e) {
+
+        }
+    }
+
+    /**
+     * @param :
+     * @return :
+     * @method : hideLoading
+     * @Author : xiaoxiao
+     * @Describe : 隐藏等待对话框
+     * @Date : 2018/5/14
+     */
+    public void hideLoading() {
+        try {
+            if (videoLoadingProDlg != null) {
+                videoLoadingProDlg.dismiss();
+                videoLoadingProDlg = null;
+            }
+        } catch (Exception e) {
+
+        }
+    }
+
+    /**
+     * @param :
+     * @return :
+     * @method : startGPSStatus
+     * @Author : xiaoxiao
+     * @Describe :启动gps
+     * @Date : 2018/5/14
+     */
+    public void startGPSStatus() {
+
+        //重新校验时间
+        isCheckTime = false;
+
+        if (getmDeviceNum() == 1) {
+
+            if (!isStartThread) {
+                isStartThread = true;
+                mUIUpdateRecoverProgress.run();
+            }
+        } else if (getmDeviceNum() == 2) {
+
+            if (!isStartThread2) {
+                isStartThread2 = true;
+                //((MainActivity) context).mUIUpdateRecoverProgress.run();
+            }
+        }
+    }
+
+    public Runnable mUIUpdateRecoverProgress = new Runnable() {
+
+        @Override
+        public void run() {
+            //都获信号取后不在监听
+            if (!isStartThread)
+                return;
+
+            if (isStartThread && mShareUtil.getConnectstate() && NetUtils.getInstance().isExistWifi(false) && !TextUtils.isEmpty(mShareUtil.getTakeCameraIP()) && mShareUtil.getContinusTakePhotoState()) {
+
+                long subTime = System.currentTimeMillis() - mPreTime;
+
+                //修改为绝对值,防止时间错误
+                if (Math.abs(subTime) > 3000 && TakePhotoManager.getInstance() != null) {
+                    mPreTime = System.currentTimeMillis();
+                    TakePhotoManager.getInstance().getCameraVedioClent(1).setmTag(1);
+                    TakePhotoManager.getInstance().getCameraVedioClent(1).GetGpsStatus();
+                }
+            }
+
+            mHandler.postDelayed(mUIUpdateRecoverProgress, 1000);
+
+        }
+    };
+
+    /**
+     * @param :
+     * @return :
+     * @method : changeSurfaceSize
+     * @Author : xiaoxiao
+     * @Describe : 改变视频屏幕显示尺寸
+     * @Date : 2018/5/14
+     */
+    private void changeSurfaceSize() {
+
+        WindowManager wm = (WindowManager) context
+                .getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+
+        int dw = display.getWidth();
+        int dh = display.getHeight();
+
+        // calculate aspect ratio
+        double ar = (double) mVideoWidth / (double) mVideoHeight;
+        // calculate display aspect ratio
+        double dar = (double) dw / (double) dh;
+
+        switch (mCurrentSize) {
+            case SURFACE_BEST_FIT:
+                if (dar < ar)
+                    dh = (int) (dw / ar);
+                else
+                    dw = (int) (dh * ar);
+                break;
+            case SURFACE_FIT_HORIZONTAL:
+                dh = (int) (dw / ar);
+                break;
+            case SURFACE_FIT_VERTICAL:
+                dw = (int) (dh * ar);
+                break;
+            case SURFACE_FILL:
+                break;
+            case SURFACE_16_9:
+                ar = 16.0 / 9.0;
+                if (dar < ar)
+                    dh = (int) (dw / ar);
+                else
+                    dw = (int) (dh * ar);
+                break;
+            case SURFACE_4_3:
+                ar = 4.0 / 3.0;
+                if (dar < ar)
+                    dh = (int) (dw / ar);
+                else
+                    dw = (int) (dh * ar);
+                break;
+            case SURFACE_ORIGINAL:
+                dh = mVideoHeight;
+                dw = mVideoWidth;
+                break;
+        }
+
+        mSurfaceHolder.setFixedSize(mVideoWidth, mVideoHeight);
+
+        Log.e("qj", mVideoWidth + "===");
+
+        mSurfaceView.invalidate();
+    }
+
+    public HostBean getmHostBean() {
+        return mHostBean;
+    }
+
+    //连接
+    private void connection(HostBean hostBean) {
+        if (hostBean != null) {
+            SensorParams params = new SensorParams();
+
+            params.put("ip", hostBean.ipAddress.toString());
+
+            Log.e("AAA", "ip" + hostBean.ipAddress);
+
+            mHostBean = hostBean;
+
+            mShareUtil.setTakeCameraIP(SystemConstant.USER_ID, hostBean.ipAddress.toString());
+
+            mShareUtil.setTakeCameraMac(SystemConstant.USER_ID, hostBean.hardwareAddress.toString());
+
+            takephotoManager.connect(getmDeviceNum(), hostBean, params);
+        }
+    }
+
+    private int getResId() {
+
+        if (getmDeviceNum() == 2)
+            return R.id.main_activity_camera2;
+
+        return R.id.main_activity_camera;
+    }
+
+    public ShareUtil getmShareUtil() {
+        return mShareUtil;
+    }
+
+    //停止录像或拍照
+    private void stopVideoOrPicture() {
+        updateCameraResources(0, getmDeviceNum());
+
+        if (isShowVideo()) {
+
+            stopVideo();
+
+        } else {
+
+            takephotoManager.StartRecording(mHostBean, getmDeviceNum());
+
+            isStartThread = true;
+
+        }
+    }
+
+    //获取编号
+    public int getmDeviceNum() {
+        return mDeviceNum;
+    }
+
+    //设置编号
+    public void setmDeviceNum(int mDeviceNum) {
+        this.mDeviceNum = mDeviceNum;
+    }
+
+    //启动或关闭拍照模式
+    public void initmTakePhotoOrRecord(boolean isCheck) {
+        if (mTakePhotoOrRecord != null && mTakePhotoOrRecord.isChecked() != isCheck) {
+            mTakePhotoOrRecord.setChecked(isCheck);
+            mTakePhotoOrRecord.setText(isCheck ? "录像" : "拍照");
+            isCancel = true;
+
+            if (!isCheck)
+                setmImgViewImageDrawable(1);
+            else
+                setmImgViewImageDrawable(0);
+        }
+    }
+
+    private void setmImgViewImageDrawable(int type) {
+        Drawable drawable = getContext().getResources().getDrawable(R.mipmap.icon_camera_img);
+        if (type == 1)
+            drawable = getContext().getResources().getDrawable(R.mipmap.icon_camera_take_photo_img);
+
+        if (mImgView != null)
+            mImgView.setImageDrawable(drawable);
+    }
+}
diff --git a/app/src/main/java/com/navinfo/omqs/ui/dialog/DataSource.java b/app/src/main/java/com/navinfo/omqs/ui/dialog/DataSource.java
new file mode 100644
index 00000000..d4b9e841
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/dialog/DataSource.java
@@ -0,0 +1,11 @@
+package com.navinfo.omqs.ui.dialog;
+/**
+ * @ClassName:     DataSource.java
+ * @author         zcs
+ * @version        V1.0  
+ * @Date           2015年9月17日 下午1:20:08 
+ * @Description:   Dialog关闭时调用
+ */
+public abstract class DataSource {
+	public abstract void Data(String str,Object obg);
+}
diff --git a/app/src/main/java/com/navinfo/omqs/ui/dialog/FirstDialog.java b/app/src/main/java/com/navinfo/omqs/ui/dialog/FirstDialog.java
new file mode 100644
index 00000000..385f37be
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/dialog/FirstDialog.java
@@ -0,0 +1,510 @@
+package com.navinfo.omqs.ui.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.navinfo.omqs.R;
+
+/**
+ * @author zcs
+ * @version V1.0
+ * @ClassName: FirstDialog.java
+ * @Date 2015年11月18日 下午5:25:27
+ * @Description: 弹出默认的dialog
+ */
+public class FirstDialog extends MyDialog {
+
+    private CharSequence mPositiveButtonText;
+    private OnClickListener mPositiveButtonListener;
+    private CharSequence mNegativeButtonText;
+    private OnClickListener mNegativeButtonListener;
+    private CharSequence mMiddleButtonText;
+    private OnClickListener mMiddleButtonListener;
+    private Object tag;
+
+    public FirstDialog(Context context) {
+
+        super(context);
+        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+        View rootView = LayoutInflater.from(context).inflate(R.layout.dialog_default, null);
+        setContentView(rootView/*, layoutParams*/);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void request(Object obj) {
+
+    }
+
+
+
+    /**
+     * 设置标题文字
+     */
+    @Override
+    public void setTitle(CharSequence string) {
+        findViewById(R.id.ll_title).setVisibility(View.VISIBLE);
+        TextView tv = (TextView) findViewById(R.id.tv_title);
+        tv.setText(TextUtils.isEmpty(string) ? "" : string);
+    }
+
+    /**
+     * 设置标题颜色
+     */
+    public void setTitleColor(int color) {
+        ((TextView) findViewById(R.id.tv_title)).setTextColor(color);
+    }
+
+    /**
+     * 设置标题2文字
+     */
+    public void setTitle2(CharSequence string) {
+        findViewById(R.id.tv_title2).setVisibility(View.VISIBLE);
+        TextView tv = (TextView) findViewById(R.id.tv_title2);
+        tv.setText(TextUtils.isEmpty(string) ? "" : string);
+    }
+
+    public void setTitle2Color(int color) {
+        ((TextView) findViewById(R.id.tv_title2)).setTextColor(color);
+    }
+
+    /**
+     * 设置标题下分割线显隐
+     */
+    public void setTitleDividerVisible(int visible) {
+        findViewById(R.id.title_divider).setVisibility(visible);
+    }
+
+    /**
+     * 设置标题下分割线显隐
+     */
+    public void setTitleDividerVisible2(int visible) {
+        findViewById(R.id.title_divider2).setVisibility(visible);
+    }
+
+    public void setBottomDividerVisible(int visible) {
+        findViewById(R.id.v_divice).setVisibility(visible);
+
+    }
+
+    /**
+     * 确认按钮
+     *
+     * @param string
+     */
+    public void setConfirm(CharSequence string) {
+        mPositiveButtonText = string;
+        TextView btn = (TextView) findViewById(R.id.btn_fm_confirm);
+        showBottomView();
+        btn.setText(TextUtils.isEmpty(string) ? "确定" : string);
+    }
+
+    public void setConfirmEnable(boolean enable) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_confirm);
+        btn.setEnabled(enable);
+    }
+
+
+    public void setConfirmVisibility(int visibility) {
+        findViewById(R.id.btn_fm_confirm).setVisibility(visibility);
+    }
+
+    /**
+     * 确认按钮
+     *
+     * @param colors
+     */
+    public void setConfirmTxtColor(int colors) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_confirm);
+        btn.setTextColor(colors);
+    }
+
+    /**
+     * 确认按钮字体大小
+     *
+     * @param size
+     */
+    public void setConfirmSize(float size) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_confirm);
+        btn.setTextSize(size);
+    }
+
+    /**
+     * 取消按钮
+     *
+     * @param string
+     */
+    public void setCancel(CharSequence string) {
+        mNegativeButtonText = string;
+        TextView btn = (TextView) findViewById(R.id.btn_fm_cancel);
+        btn.setText(TextUtils.isEmpty(string) ? "取消" : string);
+        showBottomView();
+        btn.setVisibility(View.VISIBLE);
+    }
+
+    /**
+     * 取消按钮字体颜色
+     *
+     * @param color
+     */
+    public void setCancelTxtColor(int color) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_cancel);
+        btn.setTextColor(color);
+    }
+
+    /**
+     * 取消按钮是否可点
+     *
+     * @param bl
+     */
+    public void setCancelIsCanClick(Boolean bl) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_cancel);
+        btn.setEnabled(bl);
+    }
+
+    /**
+     * 取消按钮字体大小
+     *
+     * @param size
+     */
+    public void setCancelSize(float size) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_cancel);
+        btn.setTextSize(size);
+    }
+
+    /**
+     * 中间按钮
+     *
+     * @param string
+     */
+    public void setMiddle(CharSequence string) {
+        mNegativeButtonText = string;
+        TextView btn = (TextView) findViewById(R.id.btn_fm_middle);
+        btn.setText(TextUtils.isEmpty(string) ? "中间" : string);
+        showBottomView();
+        btn.setVisibility(View.VISIBLE);
+    }
+
+    /**
+     * 中间按钮字体颜色
+     *
+     * @param color
+     */
+    public void setMiddleTxtColor(int color) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_middle);
+        btn.setTextColor(color);
+    }
+
+    /**
+     * 中间按钮是否可点
+     *
+     * @param bl
+     */
+    public void setMiddleIsCanClick(Boolean bl) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_middle);
+        btn.setEnabled(bl);
+    }
+
+    /**
+     * 中间按钮字体大小
+     *
+     * @param size
+     */
+    public void setMiddleSize(float size) {
+        TextView btn = (TextView) findViewById(R.id.btn_fm_middle);
+        btn.setTextSize(size);
+    }
+
+    /**
+     * 设置中间提示信息
+     *
+     * @param string
+     */
+    public void setContentTxt(CharSequence string) {
+        TextView tv = (TextView) findViewById(R.id.tv_content);
+        tv.setText(TextUtils.isEmpty(string) ? "" : string);
+    }
+
+    /**
+     * 设置中间提示信息是否可长按复制
+     *
+     * @param isSelectable
+     */
+    public void setTextIsSelectable(boolean isSelectable) {
+        TextView tv = (TextView) findViewById(R.id.tv_content);
+        tv.setTextIsSelectable(isSelectable);
+    }
+
+    /**
+     * 设置点击事件
+     *
+     * @param click
+     */
+    public void setContentClickListener(View.OnClickListener click) {
+        findViewById(R.id.tv_content).setOnClickListener(click);
+    }
+
+
+    /**
+     * 设置中间显隐
+     *
+     * @param visable
+     */
+    public void setContentTxtVisable(int visable) {
+        TextView tv = (TextView) findViewById(R.id.tv_content);
+        tv.setVisibility(visable);
+    }
+
+    /**
+     * 设置中间提示信息
+     *
+     * @param string
+     */
+    public void setMessage(CharSequence string) {
+        setContentTxt(string);
+    }
+
+    /**
+     * 设置中间提示颜色
+     *
+     * @param color
+     */
+    public void setMessageColor(int color) {
+        TextView tv = (TextView) findViewById(R.id.tv_content);
+        tv.setTextColor(color);
+    }
+
+    /**
+     * 设置中间提示文字
+     *
+     * @param txtId
+     */
+    public void setMessage(int txtId) {
+        String txt = context.getResources().getString(txtId);
+        TextView tv = (TextView) findViewById(R.id.tv_content);
+        tv.setText(txt);
+    }
+
+    /**
+     * 设置中间显示的内容
+     */
+    public void setMiddleView(View view) {
+        RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl_content_view);
+        rl.removeAllViews();
+        if (view != null)
+            rl.addView(view);
+    }
+
+    public void setMiddleViewMatch(View view) {
+        RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl_content_view);
+        rl.removeAllViews();
+        if (view != null)
+            rl.addView(view, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+    }
+
+    public void removeMideView() {
+        RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl_content_view);
+        rl.removeAllViews();
+    }
+
+    /**
+     * 设置中间显示的内容
+     */
+    public View setMiddleView(int id) {
+        RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl_content_view);
+        rl.removeAllViews();
+        View inflate = View.inflate(getContext(), id, rl);
+        return rl.getChildAt(0);
+    }
+
+    /**
+     * 确定按钮 点击事件
+     *
+     * @param click
+     */
+    public Dialog setConfirmListener(OnClickListener click) {
+        return setPositiveButton(mPositiveButtonText, click);
+    }
+
+    /**
+     * 取消按钮 点击事件
+     *
+     * @param click
+     */
+    public Dialog setCancelListener(OnClickListener click) {
+        return setNegativeButton(mNegativeButtonText, click);
+    }
+
+    /**
+     * 取消按钮 点击事件
+     *
+     * @param click
+     */
+    public Dialog setMiddleListener(OnClickListener click) {
+        return setMiddleButton(mMiddleButtonText, click);
+    }
+
+    /**
+     * 中间按钮 是否可点
+     *
+     * @param bl
+     */
+    public void setMiddleButtonIsCanClick(Boolean bl) {
+        TextView btn_fm_confirm = (TextView) findViewById(R.id.btn_fm_middle);
+        btn_fm_confirm.setEnabled(bl);
+    }
+
+    public Dialog setMiddleButton(CharSequence text, OnClickListener listener) {
+        mMiddleButtonText = text;
+        mMiddleButtonListener = listener;
+        setMiddle(text);
+        findViewById(R.id.middle_view).setVisibility(View.VISIBLE);
+        TextView btn_fm_middle = (TextView) findViewById(R.id.btn_fm_middle);
+        btn_fm_middle.setVisibility(View.VISIBLE);
+        btn_fm_middle.setOnClickListener(new View.OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                if (mMiddleButtonListener != null) {
+                    mMiddleButtonListener.onClick(FirstDialog.this, 3);
+                } else {
+                    dismiss();
+                }
+            }
+        });
+        return this;
+    }
+
+    public Dialog setMiddleButton(int txtId, final OnClickListener listener) {
+        String text = context.getResources().getString(txtId);
+        return setMiddleButton(text, listener);
+    }
+
+    /**
+     * 确认按钮 是否可点
+     *
+     * @param bl
+     */
+    public void setPositiveButtonIsCanClick(Boolean bl) {
+        TextView btn_fm_confirm = (TextView) findViewById(R.id.btn_fm_confirm);
+        btn_fm_confirm.setEnabled(bl);
+    }
+
+    public Dialog setPositiveButton(CharSequence text, OnClickListener listener) {
+        mPositiveButtonText = text;
+        mPositiveButtonListener = listener;
+        setConfirm(text);
+        findViewById(R.id.btn_fm_confirm).setOnClickListener(new View.OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                if (mPositiveButtonListener != null) {
+                    mPositiveButtonListener.onClick(FirstDialog.this, 2);
+                } else {
+                    dismiss();
+                }
+            }
+        });
+        //如果设置了确定或取消按钮,则不允许点击其他区域隐藏对话框
+        this.setCancelable(false);
+        return this;
+    }
+
+    public Dialog setPositiveButton(int txtId, final OnClickListener listener) {
+        String text = context.getResources().getString(txtId);
+        return setPositiveButton(text, listener);
+    }
+
+    public Dialog setNegativeButton(CharSequence text, OnClickListener listener) {
+        mNegativeButtonText = text;
+        mNegativeButtonListener = listener;
+        setCancel(text);
+        findViewById(R.id.btn_fm_cancel).setOnClickListener(new View.OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                if (mNegativeButtonListener != null) {
+                    mNegativeButtonListener.onClick(FirstDialog.this, 1);
+                } else {
+                    dismiss();
+                }
+            }
+        });
+        //如果设置了确定或取消按钮,则不允许点击其他区域隐藏对话框
+        this.setCancelable(false);
+        return this;
+    }
+
+    public Dialog setNegativeButton(int txtId, final OnClickListener listener) {
+        String text = context.getResources().getString(txtId);
+        return setNegativeButton(text, listener);
+    }
+
+    public interface OnClickListener {
+        /**
+         * This method will be invoked when a button in the dialog is clicked.
+         *
+         * @param dialog The dialog that received the click.
+         * @param which  The button that was clicked (e.g.
+         *               {@link DialogInterface#BUTTON1}) or the position
+         *               of the item clicked.
+         */
+        /* TODO: Change to use BUTTON_POSITIVE after API council */
+        public void onClick(Dialog dialog, int which);
+    }
+
+    private void showBottomView() {
+        findViewById(R.id.v_divice).setVisibility(View.VISIBLE);
+        findViewById(R.id.ll_bottom_btn).setVisibility(View.VISIBLE);
+        //如果设置了确定或取消按钮,则不允许点击其他区域隐藏对话框
+        this.setCancelable(false);
+    }
+
+
+    public void setNegativeView(int View) {
+        findViewById(R.id.btn_fm_cancel).setVisibility(View);
+        findViewById(R.id.view_dialog).setVisibility(View);
+    }
+
+    public void setCancelVisibility(int isVisibility) {
+        findViewById(R.id.btn_fm_cancel).setVisibility(isVisibility);
+    }
+
+    public void setBottomLayoutVisibility(int isVisibility) {
+        findViewById(R.id.ll_bottom_layout).setVisibility(isVisibility);
+    }
+
+    public Object getTag() {
+        return tag;
+    }
+
+    public void setTag(Object tag) {
+        this.tag = tag;
+    }
+
+    public void setNegativeButtonEnable(boolean enable) {
+        findViewById(R.id.btn_fm_cancel).setEnabled(enable);
+    }
+
+    /**
+     * 设置北京资源
+     */
+    public void setBackgroundColor(int res) {
+        LinearLayout rl = (LinearLayout) findViewById(R.id.ll_dialog);
+        if(rl!=null)
+            rl.setBackgroundColor(res);
+    }
+}
diff --git a/app/src/main/java/com/navinfo/omqs/ui/dialog/IDialog.java b/app/src/main/java/com/navinfo/omqs/ui/dialog/IDialog.java
new file mode 100644
index 00000000..ac1f581b
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/dialog/IDialog.java
@@ -0,0 +1,34 @@
+package com.navinfo.omqs.ui.dialog;
+/**
+ * @ClassName:     Dialog.java
+ * @author         zcs
+ * @version        V1.0  
+ * @param <T>
+ * @Date           2023年4月14日 上午10:15:44
+ * @Description:   所有弹出框的父类 
+ */
+public interface IDialog {
+
+	//void result(T t);
+	//public <T> void result(T t);
+	//public <T> void showData(T t);
+	/**
+	 * 给弹出框赋值
+	 * @param str
+	 * @param obj
+	 */
+	public void setData(String str,Object obj);
+	
+	/**
+	 * 给Diaolog传递的数据,显示时调用
+	 * @param obj
+	 */
+	public void request(Object obj);
+	
+	/**
+	 * 获得数据
+	 * @return
+	 */
+	public Object getData();
+
+}
diff --git a/app/src/main/java/com/navinfo/omqs/ui/dialog/LoadingDialog.java b/app/src/main/java/com/navinfo/omqs/ui/dialog/LoadingDialog.java
new file mode 100644
index 00000000..93affcb7
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/dialog/LoadingDialog.java
@@ -0,0 +1,83 @@
+package com.navinfo.omqs.ui.dialog;
+
+import android.content.Context;
+import android.graphics.drawable.AnimationDrawable;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+import com.navinfo.omqs.R;
+
+/**
+ * @author zcs
+ * @version V1.0
+ * @ClassName: LoadingDialog.java
+ * @Date 2015年9月17日 下午1:34:39
+ * @Description: 弹出等待框
+ */
+public class LoadingDialog extends MyDialog {
+
+    private CharSequence text;
+
+    private View.OnClickListener textListener;
+
+    private TextView tv_msg;
+
+    public LoadingDialog(Context context) {
+
+        super(context);
+
+        // requestWindowFeature(Window.FEATURE_NO_TITLE);//不显示标题
+    }
+
+    @Override
+    public void request(Object obj) {
+
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+
+        View customFrame = View.inflate(context, R.layout.dialog_loading_custom_frame_layout, null);
+
+        ((AnimationDrawable) customFrame.findViewById(R.id.customFrameLoadImg).getBackground()).start();
+
+        tv_msg = (TextView) customFrame.findViewById(R.id.customFrameMsg);
+
+        tv_msg.setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE);
+
+        tv_msg.setText(TextUtils.isEmpty(text) ? "" : text);
+
+        tv_msg.setOnClickListener(textListener);
+
+        setContentView(customFrame);
+    }
+
+    /**
+     * 设置等待提示文字
+     *
+     * @param text
+     */
+    public void setText(CharSequence text) {
+
+        this.text = text;
+        if (tv_msg!=null){
+            tv_msg.setVisibility(TextUtils.isEmpty(this.text) ? View.GONE : View.VISIBLE);
+            tv_msg.setText(TextUtils.isEmpty(this.text) ? "" : this.text);
+        }
+    }
+
+    /**
+     * 设置文本点击事件
+     *
+     * @param listener
+     */
+    public void setTextClickListener(View.OnClickListener listener){
+
+        this.textListener = listener;
+
+        if (tv_msg!=null){
+            tv_msg.setOnClickListener(listener);
+        }
+    }
+}
diff --git a/app/src/main/java/com/navinfo/omqs/ui/dialog/MyDialog.java b/app/src/main/java/com/navinfo/omqs/ui/dialog/MyDialog.java
new file mode 100644
index 00000000..b9413f22
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/dialog/MyDialog.java
@@ -0,0 +1,92 @@
+package com.navinfo.omqs.ui.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.view.Window;
+
+/**
+ * @param <T>
+ * @param <T>
+ * @author qj
+ * @version V1.0
+ * @ClassName: MyDialog.java
+ * @Date 2023年4月14日 上午10:18:52
+ * @Description: 所有提示框的父类(在onCreate设置布局)
+ */
+public abstract class MyDialog extends Dialog implements IDialog {
+
+    protected Context context;
+
+    private Object obj;
+
+    private DataSource dataSource;
+
+    private String str;
+
+    public MyDialog(Context context) {
+        super(context);
+        this.context = context;
+        requestWindowFeature(Window.FEATURE_NO_TITLE);//不显示标题
+        getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+    }
+
+    @Override
+    public void dismiss() {
+
+        if (dataSource != null) {
+
+            dataSource.Data(str, obj);
+
+        }
+
+        super.dismiss();
+    }
+
+    public void setWidthHeight(int width, int height) {
+        getWindow().setLayout(width, height);
+    }
+
+    @Override
+    public void show() {
+
+        request(obj);
+
+        super.show();
+    }
+
+    @Override
+    public void setData(String str, Object obj) {
+
+        this.str = str;
+
+        this.obj = obj;
+
+    }
+
+    @Override
+    public Object getData() {
+
+        return obj;
+
+    }
+
+    public void getResponse(DataSource dataSource) {
+
+        this.dataSource = dataSource;
+
+    }
+
+    /**
+     * 设置背景色
+     *
+     * @param drawable
+     */
+    public void setBackground(Drawable drawable) {
+
+        getWindow().setBackgroundDrawable(drawable);
+
+    }
+}
diff --git a/app/src/main/java/com/navinfo/omqs/ui/manager/TakePhotoManager.java b/app/src/main/java/com/navinfo/omqs/ui/manager/TakePhotoManager.java
new file mode 100644
index 00000000..dce99378
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/manager/TakePhotoManager.java
@@ -0,0 +1,578 @@
+package com.navinfo.omqs.ui.manager;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.volley.VolleyError;
+import com.navinfo.collect.library.garminvirbxe.CameraEventListener;
+import com.navinfo.collect.library.garminvirbxe.CameraGarminVirbXE;
+import com.navinfo.collect.library.garminvirbxe.HostBean;
+import com.navinfo.collect.library.garminvirbxe.SensorParams;
+import com.navinfo.collect.library.sensor.ISensor.enmConnectionStatus;
+import com.navinfo.collect.library.sensor.ISensor.enmSensorModel;
+import com.navinfo.collect.library.sensor.ISensor.SensorWorkingMode;
+import com.navinfo.collect.library.sensor.ISensor.enmSensorType;
+import com.navinfo.collect.library.sensor.ISensor.enmSignalQuality;
+import com.navinfo.collect.library.sensor.SensorManager;
+import com.navinfo.omqs.system.SystemConstant;
+import com.navinfo.omqs.util.ShareUtil;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author qj
+ * @version V1.0
+ * @Date 2023/4/14.
+ * @Description: (外设相机控制类)
+ */
+public class TakePhotoManager {
+
+    /**
+     * 拍照控制类集合
+     */
+    private List<CameraGarminVirbXE> mSensorInstanceList;
+
+    /**
+     * 拍照过程回调监听
+     */
+    /**
+     * 拍照管理类
+     */
+    private static volatile TakePhotoManager mInstance;
+    //外设相机连接状态
+    private HashMap<String, enmConnectionStatus> mConnectionStatusHashMap;
+    //上下文
+    private Context mCon;
+
+    /**
+     * 装拍照过程回调数组
+     */
+    private final List<CameraEventListener> mOnCameraEventListeners = new ArrayList<CameraEventListener>();
+
+    public static TakePhotoManager getInstance() {
+        if (mInstance == null) {
+            synchronized (TakePhotoManager.class) {
+                if (mInstance == null) {
+                    mInstance = new TakePhotoManager();
+                }
+            }
+        }
+        return mInstance;
+    }
+
+    public void init(Context context, int cameraCount) {
+
+        mCon = context;
+
+        if (cameraCount == 0)
+            cameraCount = 1;
+
+        mSensorInstanceList = new ArrayList<CameraGarminVirbXE>();
+
+        mConnectionStatusHashMap = new HashMap<String, enmConnectionStatus>();
+
+        CameraEventListener cameraEevent = new CameraEventListener() {
+            @Override
+            public void OnSnapPictureResponse(HostBean hostBean, Bitmap bitmap, String picName, int tag) {
+                Log.i("info", "bitmap:" + bitmap);
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnSnapPictureResponse(hostBean, bitmap, picName, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void requestError(HostBean hostBean, com.android.volley.VolleyError e, CameraGarminVirbXE.enmCommandType commandType, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.requestError(hostBean, e, commandType, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnStartRecordResponse(HostBean hostBean, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnStartRecordResponse(hostBean, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnStopRecordResponse(HostBean hostBean, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnStopRecordResponse(hostBean, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnStatusResponse(HostBean hostBean, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnStatusResponse(hostBean, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnSearchResponse(int tag, ArrayList<HostBean> scanIpList) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnSearchResponse(tag, scanIpList);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnConnectStatusChanged(HostBean hostBean, enmConnectionStatus connectStatus, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnConnectStatusChanged(hostBean, connectStatus, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnGetGpsStatusResponse(HostBean hostBean, boolean status, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnGetGpsStatusResponse(hostBean, status, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnConnectionStatusChanged(HostBean hostBean, enmConnectionStatus cs, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnConnectionStatusChanged(hostBean, cs, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnContinuousPhototTimeLapseRateResponse(HostBean hostBean, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnContinuousPhototTimeLapseRateResponse(hostBean, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnContinuousPhototTimeLapseRateStartResponse(HostBean hostBean, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnContinuousPhototTimeLapseRateStartResponse(hostBean, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnContinuousPhototTimeLapseRateStopResponse(HostBean hostBean, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnContinuousPhototTimeLapseRateStopResponse(hostBean, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnContinuousPhototSingle(HostBean hostBean, String url, String name, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnContinuousPhototSingle(hostBean, url, name, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnGetMediaList(HostBean hostBean, String json, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnGetMediaList(hostBean, json, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnSensorEvent() {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnSensorEvent();
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnConnectionStatusChanged(enmConnectionStatus cs) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnConnectionStatusChanged(cs);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnGetDeviceInfo(HostBean hostBean, String devicesId, int tag) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnGetDeviceInfo(hostBean, devicesId, tag);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void OnSignalQualityChanged(enmSignalQuality sq) {
+                if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                    for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                        if (weakRef != null) {
+                            weakRef.OnSignalQualityChanged(sq);
+                        }
+                    }
+                }
+            }
+        };
+
+        for (int i = 0; i < cameraCount; i++) {
+
+            CameraGarminVirbXE clent = (CameraGarminVirbXE) SensorManager.getInstance().CreateSensor(context, enmSensorType.SENSOR_CAMEAR, enmSensorModel.CAMERA_GARMIN_VIRB_XE);
+            clent.setmTag(i + 1);
+            clent.RegisterSensorEvent(cameraEevent);
+            mSensorInstanceList.add(clent);
+        }
+
+    }
+
+    //连接网络
+    public boolean connect(int indexClent, HostBean hostBean, SensorParams params) {
+        if (hostBean != null) {
+            CameraGarminVirbXE cameraGarminVirbXE = getCameraVedioClent(indexClent);
+            if (cameraGarminVirbXE != null) {
+                cameraGarminVirbXE.Connect(hostBean, params);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public enmConnectionStatus getConnectionStatus(HostBean hostBean) {
+
+        if (hostBean != null && mConnectionStatusHashMap != null && mConnectionStatusHashMap.containsKey(hostBean.hardwareAddress)) {
+            return mConnectionStatusHashMap.get(hostBean.hardwareAddress);
+        }
+
+
+        return enmConnectionStatus.DISCONNECTTED;
+    }
+
+    public enmConnectionStatus getConnectionStatus() {
+
+        if (mSensorInstanceList != null && mConnectionStatusHashMap != null) {
+            enmConnectionStatus mEnmConnectionStatus = enmConnectionStatus.DISCONNECTTED;
+            for (CameraGarminVirbXE cameraGarminVirbXE : mSensorInstanceList) {
+                mEnmConnectionStatus = cameraGarminVirbXE.GetConnectionStatus();
+                if (mEnmConnectionStatus == enmConnectionStatus.CONNECTTED)
+                    return enmConnectionStatus.CONNECTTED;
+
+            }
+        }
+
+
+        return enmConnectionStatus.DISCONNECTTED;
+    }
+
+    //设置相机模式
+    public void setCameraMode(int indexClent, SensorWorkingMode mode) {
+        if (indexClent > 0 && mSensorInstanceList!=null && indexClent <= mSensorInstanceList.size()) {
+            getCameraVedioClent(indexClent).SetMode(mode);
+        }
+    }
+
+    //获取当前相机模式
+    public SensorWorkingMode getCameraMode(int indexClent) {
+        if (mSensorInstanceList != null && indexClent > 0 && indexClent <= mSensorInstanceList.size()) {
+            return getCameraVedioClent(indexClent).GetMode();
+        }
+
+        return null;
+    }
+
+    public String mediaList(int indexClent, String path) {
+        if (mSensorInstanceList != null && indexClent > 0 && indexClent <= mSensorInstanceList.size()) {
+            getCameraVedioClent(indexClent).mediaList(path);
+        }
+
+        return null;
+    }
+
+
+    //搜索网络
+    public void SearchNet(HostBean hostBean, int indexClent, boolean isReadCache) {
+        if (mSensorInstanceList != null && mSensorInstanceList.size() > 0 && indexClent > 0 && indexClent <= mSensorInstanceList.size()) {
+            mSensorInstanceList.get(indexClent - 1).Search(isReadCache);
+            return;
+        }
+    }
+
+    //连续拍照
+    public void StartRecording(HostBean hostBean, int indexCamera) {
+        if (mSensorInstanceList != null && indexCamera > 0 && indexCamera <= mSensorInstanceList.size()) {
+            getCameraVedioClent(indexCamera).StartRecording();
+        }
+    }
+
+
+    public void getGpsStatus() {
+        if (mSensorInstanceList != null && mSensorInstanceList.size() > 0) {
+            for (CameraGarminVirbXE cameraGarminVirbXE : mSensorInstanceList) {
+                cameraGarminVirbXE.GetGpsStatus();
+            }
+        }
+
+    }
+
+    //获取GPS状态
+    public void getGpsStatus(HostBean hostBean, int index) {
+        if (hostBean != null) {
+            CameraGarminVirbXE cameraGarminVirbXE = findCameraGarminVirbXE(hostBean, index);
+            if (cameraGarminVirbXE != null) {
+                cameraGarminVirbXE.GetGpsStatus();
+            }
+        }
+    }
+
+    public void startCameraVedio(HostBean hostBean, int indexClent) {
+        if (hostBean != null) {
+
+            StopContinuousTakePhoto(hostBean, indexClent);
+
+            setCameraMode(indexClent, SensorWorkingMode.CAMERA_VEDIO_TIMELAPSE);
+
+            ShareUtil.getCameraMode(mCon).setContinusTakePhotoState(SystemConstant.USER_ID, false);
+
+            StartRecording(hostBean, indexClent);
+
+        }
+
+    }
+
+    //抓拍
+    public void SnapShot(HostBean hostBean, int index) {
+        if (hostBean != null) {
+            CameraGarminVirbXE cameraGarminVirbXE = findCameraGarminVirbXE(hostBean, index);
+            if (cameraGarminVirbXE != null) {
+                cameraGarminVirbXE.snapPicture(SystemConstant.getUuid(true));
+            }
+        }
+    }
+
+    public Long getGoogleTime() {
+        if (mSensorInstanceList != null && mSensorInstanceList.size() > 0) {
+            for (CameraGarminVirbXE cameraGarminVirbXE : mSensorInstanceList) {
+                if (cameraGarminVirbXE.getGoogleGpsTime() > 0) {
+                    return cameraGarminVirbXE.getGoogleGpsTime();
+                }
+            }
+        }
+
+        return 0l;
+    }
+
+    //停止时间线程,减少电量消耗
+    public void stopTimeThread() {
+        if (mSensorInstanceList != null && mSensorInstanceList.size() > 0) {
+            for (CameraGarminVirbXE cameraGarminVirbXE : mSensorInstanceList) {
+                cameraGarminVirbXE.stopTimeThread();
+            }
+        }
+    }
+
+    //设置拍照路径
+    public void setSavePath(HostBean hostBean, String path, int index) {
+        if (path == null || path.equals("")) {
+            return;
+
+        }
+        if (hostBean != null) {
+            CameraGarminVirbXE cameraGarminVirbXE = findCameraGarminVirbXE(hostBean, index);
+            if (cameraGarminVirbXE != null) {
+                File file = new File(path);
+                if (file.exists() && file.isDirectory()) {
+                    cameraGarminVirbXE.SetCameraPictureSavaPath(path);
+                }
+            }
+        }
+    }
+
+    //停止搜索
+    public void StopSearchNet(HostBean hostBean, int indexClent) {
+        if (hostBean != null) {
+            CameraGarminVirbXE cameraGarminVirbXE = findCameraGarminVirbXE(hostBean, indexClent);
+            if (cameraGarminVirbXE != null) {
+                cameraGarminVirbXE.StopSearch();
+            }
+        }
+    }
+
+    //停止连拍
+    public void StopContinuousTakePhoto(HostBean hostBean, int indexCamera) {
+        if (mSensorInstanceList != null && indexCamera > 0 && indexCamera <= mSensorInstanceList.size()) {
+            getCameraVedioClent(indexCamera).StopRecording();
+        }
+
+    }
+
+    //停止所有相机
+    public void StopContinuousTakePhotoAll() {
+        if (mSensorInstanceList != null) {
+            for (CameraGarminVirbXE cameraGarminVirbXE : mSensorInstanceList) {
+                cameraGarminVirbXE.StopRecording();
+            }
+        }
+
+    }
+
+    //查找对应控制类
+    private CameraGarminVirbXE findCameraGarminVirbXE(HostBean hostBean, int index) {
+
+        if (mSensorInstanceList != null && mSensorInstanceList.size() > 0) {
+
+            for (CameraGarminVirbXE cameraGarminVirbXE : mSensorInstanceList) {
+                if (cameraGarminVirbXE.getmHostBean() != null && hostBean != null && !TextUtils.isEmpty(cameraGarminVirbXE.getmHostBean().hardwareAddress)
+                        && !TextUtils.isEmpty(hostBean.hardwareAddress) && cameraGarminVirbXE.getmHostBean().hardwareAddress.equalsIgnoreCase(hostBean.hardwareAddress) && cameraGarminVirbXE.getmTag() == index) {
+                    return cameraGarminVirbXE;
+                }
+            }
+
+            return mSensorInstanceList.get(0);
+        }
+
+        return null;
+    }
+
+
+    public void setOnCameraEventChangeListener(CameraEventListener listener) {
+        synchronized (mOnCameraEventListeners) {
+            if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                for (CameraEventListener weakRef : mOnCameraEventListeners) {
+                    if (weakRef != null
+                            && weakRef == listener) {
+                        return;
+                    }
+                }
+            }
+            mOnCameraEventListeners.add(listener);
+        }
+    }
+
+    public void removeCameraEventListener(HostBean hostBean, CameraEventListener listener) {
+        synchronized (mOnCameraEventListeners) {
+            CameraEventListener weakRef;
+            if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                for (int idx = 0; idx < mOnCameraEventListeners.size(); idx++) {
+                    if ((weakRef = mOnCameraEventListeners.get(idx)) != null) {
+                        if (weakRef == listener) {
+                            mOnCameraEventListeners.remove(idx);
+                            return;
+                        }
+                    } else {
+                        mOnCameraEventListeners.remove(idx);
+                        idx--;
+                    }
+                }
+            }
+        }
+    }
+
+    public void removeCameraEventListenerAll(CameraEventListener listener) {
+        synchronized (mOnCameraEventListeners) {
+            CameraEventListener weakRef;
+            if (mOnCameraEventListeners != null && mOnCameraEventListeners.size() > 0) {
+                for (int idx = 0; idx < mOnCameraEventListeners.size(); idx++) {
+                    if ((weakRef = mOnCameraEventListeners.get(idx)) != null) {
+                        if (weakRef == listener) {
+                            mOnCameraEventListeners.remove(idx);
+                            return;
+                        }
+                    } else {
+                        mOnCameraEventListeners.remove(idx);
+                        idx--;
+                    }
+                }
+            }
+        }
+    }
+
+    //根据拍照模式获取控制类
+    public CameraGarminVirbXE getCameraVedioClent(SensorWorkingMode mode) {
+
+        if (mode == null)
+            return null;
+
+        if (mSensorInstanceList != null && mSensorInstanceList.size() > 0) {
+            for (CameraGarminVirbXE cameraGarminVirbXE : mSensorInstanceList) {
+                if (cameraGarminVirbXE.GetMode() != null && cameraGarminVirbXE.GetMode() == mode) {
+                    return cameraGarminVirbXE;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public CameraGarminVirbXE getCameraVedioClent(int indexClent) {
+
+        if (indexClent <= 0)
+            return null;
+
+        if (mSensorInstanceList != null && mSensorInstanceList.size() > 0 && indexClent <= mSensorInstanceList.size()) {
+            return mSensorInstanceList.get(indexClent - 1);
+        }
+
+        return null;
+    }
+}
diff --git a/app/src/main/java/com/navinfo/omqs/ui/other/BaseToast.java b/app/src/main/java/com/navinfo/omqs/ui/other/BaseToast.java
new file mode 100644
index 00000000..2914de36
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/other/BaseToast.java
@@ -0,0 +1,77 @@
+package com.navinfo.omqs.ui.other;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
+import com.navinfo.omqs.R;
+
+/**
+ * 在屏幕中间出现toast提示
+ */
+public class BaseToast extends Toast{
+	final Context mContext;
+	
+	private static int height;
+	static Toast result;
+	public BaseToast(Context context) {
+		super(context);
+		mContext = context;
+		DisplayMetrics dm = new DisplayMetrics();
+		// 获取屏幕信息
+		((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
+
+		height = dm.heightPixels;
+	}
+
+	/**
+	 * 屏幕中间显示toast
+	 * @param context
+	 * @param text 显示内容
+	 * @param duration 显示时长
+	 * @return
+	 */
+	public static Toast makeText(Context context, CharSequence text, int duration) {
+		try{
+			DisplayMetrics dm = new DisplayMetrics();
+			((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
+			height = dm.heightPixels;
+			result =result==null? new Toast(context):result;
+			LayoutInflater inflate = (LayoutInflater) context
+					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+			View v = inflate.inflate(R.layout.transient_notification, null);
+			TextView tv = (TextView) v.findViewById(android.R.id.message);
+			tv.setText(text);
+			result.setView(v);
+			if(duration<Toast.LENGTH_SHORT)
+				duration = Toast.LENGTH_SHORT;
+			result.setDuration(duration);
+			result.setGravity(Gravity.CENTER, 0, height/6);
+		}catch (Exception e){
+		}
+
+		return result;
+	}
+
+	/**
+	 * 屏幕中心显示toast
+	 * @param context
+	 * @param resId 文字资源id
+	 * @param duration 显示时长
+	 * @return
+	 * @throws Resources.NotFoundException
+	 */
+	public static Toast makeText(Context context, int resId, int duration)
+			throws Resources.NotFoundException {
+		return makeText(context, context.getResources().getText(resId),
+				duration);
+	}
+
+}
+
diff --git a/app/src/main/java/com/navinfo/omqs/util/FileUtils.java b/app/src/main/java/com/navinfo/omqs/util/FileUtils.java
new file mode 100644
index 00000000..d7194e70
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/util/FileUtils.java
@@ -0,0 +1,616 @@
+package com.navinfo.omqs.util;
+
+import android.content.Context;
+import android.media.ExifInterface;
+import android.text.TextUtils;
+import android.util.Log;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author qj
+ * @version V1.0
+ * @ClassName: FileUtils
+ * @Date 2023/4/17
+ * @Description: ${文件类)
+ */
+public class FileUtils {
+    //类标识
+    private static final String TAG = "FileUtils";
+    // 本类输出的日志文件名称
+    private static String TrackFILEName = "Track.txt";
+    // 本类输出的日志文件名称
+    private static String AdasTrackFILEName = "AdasTrack.txt";
+    //日志文件格式
+    private static SimpleDateFormat logfile = new SimpleDateFormat("yyyy-MM-dd");
+    //文件集合
+    private static List<File> filelist = new ArrayList<File>();
+
+
+    /**
+     * 复制文件到sd卡
+     *
+     * @param context  上下文
+     * @param fileDir  文件目录
+     * @param filePath 文件路径
+     * @param files    文件集合
+     */
+    public static void copyFileToSdcard(Context context, String fileDir,
+                                        String filePath, Field[] files) {
+
+        for (Field r : files) {
+            try {
+                int id = context.getResources().getIdentifier(r.getName(),
+                        "raw", context.getPackageName());
+                Log.i(TAG, new File(filePath).length() + "=====文件长度===="
+                        + filePath);
+                if (!new File(fileDir).exists()) {
+                    new File(fileDir).mkdirs();
+                }
+
+                // new File(path).delete();
+                if (new File(filePath).exists())
+                    new File(filePath).delete();
+                new File(filePath).createNewFile();
+                BufferedOutputStream bufEcrivain = new BufferedOutputStream(
+                        (new FileOutputStream(new File(filePath))));
+                BufferedInputStream VideoReader = new BufferedInputStream(
+                        context.getResources().openRawResource(id));
+                byte[] buff = new byte[20 * 1024];
+                int len;
+                while ((len = VideoReader.read(buff)) > 0) {
+                    bufEcrivain.write(buff, 0, len);
+                }
+                bufEcrivain.flush();
+                bufEcrivain.close();
+                VideoReader.close();
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+    }
+
+    /**
+     * 复制单个文件
+     *
+     * @param oldPath String 原文件路径 如:c:/fqf.txt
+     * @param newPath String 复制后路径 如:f:/fqf.txt
+     * @return boolean
+     */
+    public static boolean copyFile(String oldPath, String newPath) {
+        try {
+            int bytesum = 0;
+            int byteread = 0;
+            File oldfile = new File(oldPath);
+            if (oldfile.exists()) { // 文件存在时
+                InputStream inStream = new FileInputStream(oldPath); // 读入原文件
+                FileOutputStream fs = new FileOutputStream(newPath);
+                byte[] buffer = new byte[1444];
+                while ((byteread = inStream.read(buffer)) != -1) {
+
+                    bytesum += byteread; // 字节数 文件大小
+                    System.out.println(bytesum);
+                    fs.write(buffer, 0, byteread);
+
+                }
+                inStream.close();
+                return true;
+            }
+
+        } catch (Exception e) {
+
+            System.out.println("复制单个文件操作出错");
+            e.printStackTrace();
+
+        }
+        return false;
+
+    }
+
+
+    /**
+     * 实时轨迹信息写入文件
+     *
+     * @param info      信息
+     * @param isNewLine 是否换行写入
+     */
+    public static void writeRealTimeTrackToFile(String filePath, String info, boolean isNewLine) {
+
+
+        if (new File(filePath).exists() == false) {
+            new File(filePath).mkdirs();
+        }
+
+        File file = new File(filePath, "monitor_track.txt");
+
+        FileWriter filerWriter = null;
+
+        BufferedWriter bufWriter = null;
+
+        try {
+            if (!file.exists())
+                file.createNewFile();
+
+            //文件流
+            filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
+
+            //字符缓冲输出流
+            bufWriter = new BufferedWriter(filerWriter);
+
+            bufWriter.write(info);
+
+            if (isNewLine)
+                bufWriter.newLine();
+
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }finally {
+            try{
+                if(bufWriter!=null)
+                    bufWriter.close();
+
+                if(filerWriter!=null)
+                    filerWriter.close();
+            }catch (Exception e){
+
+            }
+
+        }
+    }
+
+
+    /**
+     * 轨迹信息写入文件
+     *
+     * @param info      信息
+     * @param isNewLine 是否换行写入
+     */
+    public static void writeTrackToFile(String filePath, String info, boolean isNewLine) {
+        Date nowtime = new Date();
+
+        String needWriteFiel = logfile.format(nowtime);
+
+        if (TextUtils.isEmpty(filePath))
+            return;
+
+        if (new File(filePath).exists() == false) {
+            new File(filePath).mkdirs();
+        }
+        File file = new File(filePath, needWriteFiel + TrackFILEName);
+        FileWriter filerWriter = null;
+        BufferedWriter bufWriter = null;
+        try {
+            if (!file.exists())
+                file.createNewFile();
+
+            //文件流
+            filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
+
+            //字符缓冲输出流
+            bufWriter = new BufferedWriter(filerWriter);
+
+            bufWriter.write(info);
+
+            if (isNewLine)
+                bufWriter.newLine();
+
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }finally {
+
+            try{
+                if(bufWriter!=null)
+                    bufWriter.close();
+
+                if(filerWriter!=null)
+                    filerWriter.close();
+            }catch (Exception e){
+
+            }
+
+        }
+    }
+
+    /**
+     * 实时轨迹偏差信息写入文件
+     *
+     * @param info      信息
+     * @param isNewLine 是否换行写入
+     */
+    public static void writeTrackLogToFile(String filePath, String info, boolean isNewLine) {
+
+
+        if (new File(filePath).exists() == false) {
+            new File(filePath).mkdirs();
+        }
+        File file = new File(filePath, "TrackLog.txt");
+        FileWriter filerWriter = null;
+        BufferedWriter bufWriter = null;
+        try {
+            if (!file.exists())
+                file.createNewFile();
+
+            //文件流
+            filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
+
+            //字符缓冲输出流
+            bufWriter = new BufferedWriter(filerWriter);
+
+            bufWriter.write(info);
+
+            if (isNewLine)
+                bufWriter.newLine();
+
+
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }finally {
+            try{
+                if(bufWriter!=null)
+                    bufWriter.close();
+
+                if(filerWriter!=null)
+                    filerWriter.close();
+            }catch (Exception e){
+
+            }
+        }
+    }
+
+
+    /**
+     * 逐行写入
+     *
+     * @param info      信息
+     */
+    public static void writeLine(String filePath,String fileName, String info) {
+
+        if (TextUtils.isEmpty(filePath))
+            return;
+
+        if (new File(filePath).exists() == false) {
+            new File(filePath).mkdirs();
+        }
+        File file = new File(filePath + fileName);
+        FileWriter filerWriter = null;
+        BufferedWriter bufWriter = null;
+        try {
+            if (!file.exists())
+                file.createNewFile();
+
+            //文件流
+            filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
+
+            //字符缓冲输出流
+            bufWriter = new BufferedWriter(filerWriter);
+
+            bufWriter.write(info);
+
+            bufWriter.newLine();
+
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }finally {
+            try{
+                if(bufWriter!=null)
+                    bufWriter.close();
+
+                if(filerWriter!=null)
+                    filerWriter.close();
+            }catch (Exception e){
+
+            }
+        }
+    }
+
+    /**
+     * Adas轨迹信息写入文件
+     *
+     * @param info      信息
+     * @param isNewLine 是否换行写入
+     */
+    public static void writeAdasTrackToFile(String filePath, String info, boolean isNewLine) {
+
+        Date nowtime = new Date();
+
+        String needWriteFiel = logfile.format(nowtime);
+
+        if (TextUtils.isEmpty(filePath))
+            return;
+
+        if (new File(filePath).exists() == false) {
+            new File(filePath).mkdirs();
+        }
+
+        File file = new File(filePath, needWriteFiel + AdasTrackFILEName);
+        FileWriter filerWriter = null;
+        BufferedWriter bufWriter = null;
+        try {
+            if (!file.exists())
+                file.createNewFile();
+
+            //文件流
+            filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
+
+            //字符缓冲输出流
+            bufWriter = new BufferedWriter(filerWriter);
+
+            bufWriter.write(info);
+
+            if (isNewLine)
+                bufWriter.newLine();
+
+
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }finally {
+            try{
+                if(bufWriter!=null)
+                    bufWriter.close();
+
+                if(filerWriter!=null)
+                    filerWriter.close();
+            }catch (Exception e){
+
+            }
+        }
+    }
+
+    /**
+     * 获取文件绝对路径
+     *
+     * @return list
+     * 文件绝对路径集合
+     */
+    public static List<File> getFileList(String strPath, String[] suffix) {
+        File dir = new File(strPath);
+        File[] files = dir.listFiles(); // 该文件目录下文件全部放入数组
+
+        if (files != null) {
+            for (int i = 0; i < files.length; i++) {
+                String fileName = files[i].getName();
+                if (files[i].isDirectory()) { // 判断是文件还是文件夹
+                    getFileList(files[i].getAbsolutePath(), suffix); // 获取文件绝对路径
+                } else {
+                    if (suffix != null && suffix.length > 0) {
+                        for (String str : suffix) {
+                            if (fileName.endsWith(str)) { // 判断文件名是否以
+                                String strFileName = files[i].getAbsolutePath();
+                                System.out.println("---" + strFileName);
+                                filelist.add(files[i]);
+                            }
+                        }
+                    }
+                }
+            }
+
+        }
+        return filelist;
+    }
+
+    /**
+     * 清理缓存文件
+     */
+    public static void clearCacheFile() {
+        filelist.clear();
+    }
+
+    /**
+     * 获取文件目录大小
+     *
+     * @param file
+     */
+    public static double getDirSize(File file) {
+        //判断文件是否存在
+        if (file.exists()) {
+            //如果是目录则递归计算其内容的总大小
+            if (file.isDirectory()) {
+                File[] children = file.listFiles();
+                double size = 0;
+                for (File f : children)
+                    size += getDirSize(f);
+                return size;
+            } else {//如果是文件则直接返回其大小,以“兆”为单位
+                double size = (double) file.length() / 1024 / 1024;
+                return size;
+            }
+        } else {
+            System.out.println("文件或者文件夹不存在,请检查路径是否正确!");
+            return 0.0;
+        }
+    }
+
+    public static byte[] readFileByBytes(String url) throws IOException {
+        File file = new File(url);
+        if (file.exists() && !file.mkdir()) {
+            long fileSize = file.length();
+            if (fileSize > Integer.MAX_VALUE) {
+//                System.out.println("file too big...");
+                return null;
+            }
+
+            FileInputStream fi = new FileInputStream(file);
+            byte[] buffer = new byte[(int) fileSize];
+            int offset = 0;
+            int numRead = 0;
+            while (offset < buffer.length
+                    && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
+                offset += numRead;
+            }
+            // 确保所有数据均被读取
+            if (offset != buffer.length) {
+                throw new IOException("Could not completely read file "
+                        + file.getName());
+            }
+            fi.close();
+            return buffer;
+        }
+        return null;
+    }
+
+
+    //把从服务器获得图片的输入流InputStream写到本地磁盘
+    public static void saveImageToDisk(String url, String savePath) {
+
+        InputStream inputStream = getInputStream(url);
+        if(inputStream==null)
+            return;
+
+        byte[] data = new byte[1024];
+        int len = 0;
+        FileOutputStream fileOutputStream = null;
+        try {
+            fileOutputStream = new FileOutputStream(savePath);
+            while ((len = inputStream.read(data)) != -1) {
+                fileOutputStream.write(data, 0, len);
+
+            }
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } finally {
+
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+            if (fileOutputStream != null) {
+                try {
+                    fileOutputStream.close();
+                } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+
+        }
+
+    }
+
+    // 从服务器获得一个输入流(本例是指从服务器获得一个image输入流)
+    public static InputStream getInputStream(String urlPath) {
+        InputStream inputStream = null;
+        HttpURLConnection httpURLConnection = null;
+
+        try {
+            URL url = new URL(urlPath);
+            httpURLConnection = (HttpURLConnection) url.openConnection();
+            // 设置网络连接超时时间
+            httpURLConnection.setConnectTimeout(3000);
+            // 设置应用程序要从网络连接读取数据
+            httpURLConnection.setDoInput(true);
+
+            httpURLConnection.setRequestMethod("GET");
+            int responseCode = httpURLConnection.getResponseCode();
+            if (responseCode == 200) {
+                // 从服务器返回一个输入流
+                inputStream = httpURLConnection.getInputStream();
+
+            }
+
+        } catch (MalformedURLException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+        return inputStream;
+
+    }
+
+    public static String getExifTime(String jpegFile) {
+        try {
+
+            ExifInterface exif = new ExifInterface(jpegFile);
+
+            String time = exif.getAttribute(ExifInterface.TAG_DATETIME);
+
+            return time;
+
+
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    /**
+     * 轨迹信息写入文件
+     *
+     * @param info      信息
+     * @param isNewLine 是否换行写入
+     */
+    public static void writeToFile(String filePath, String info, boolean isNewLine) {
+
+        if (TextUtils.isEmpty(filePath))
+            return;
+
+        File file = new File(filePath);
+        FileWriter filerWriter = null;
+        BufferedWriter bufWriter = null;
+        try {
+            if (!file.exists())
+                file.createNewFile();
+
+            //文件流
+            filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
+
+            //字符缓冲输出流
+            bufWriter = new BufferedWriter(filerWriter);
+
+            bufWriter.write(info);
+
+            if (isNewLine)
+                bufWriter.newLine();
+
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }finally {
+            try{
+                if(bufWriter!=null)
+                    bufWriter.close();
+
+                if(filerWriter!=null)
+                    filerWriter.close();
+            }catch (Exception e){
+
+            }
+        }
+    }
+}
+
+
+
+
+
diff --git a/app/src/main/java/com/navinfo/omqs/util/NetUtils.java b/app/src/main/java/com/navinfo/omqs/util/NetUtils.java
new file mode 100644
index 00000000..a692c114
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/util/NetUtils.java
@@ -0,0 +1,78 @@
+package com.navinfo.omqs.util;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+/**
+ * @ClassName:     NetUtils.java
+ * @author         qj
+ * @version        V1.0
+ * @Date           2016年12月17日 下午1:56:02
+ * @Description:   网络类
+ */
+public class NetUtils {
+	//单例对象
+	private static volatile NetUtils mInstance;
+	//上下文
+	private Context mCon;
+
+	public static NetUtils getInstance() {
+
+		if (mInstance == null) {
+			synchronized (NetUtils.class) {
+				if (mInstance == null) {
+					mInstance = new NetUtils();
+				}
+			}
+		}
+		return mInstance;
+	}
+
+	/**
+	 * 初始化
+	 * @param  context
+	 * 			上下文
+	 */
+	public void init(Context context){
+		
+		this.mCon = context;
+		
+
+	}
+
+	/**
+	 * 是否wifi
+	 * @return true 是 false 否
+	 */
+	public boolean isExistWifi(boolean isNeedMobile){
+
+		//获取系统服务
+		ConnectivityManager manager = (ConnectivityManager)mCon.getSystemService(Context.CONNECTIVITY_SERVICE);
+		try{
+			//获取状态
+			final NetworkInfo.State wifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
+
+			if(wifi == NetworkInfo.State.CONNECTED||wifi==NetworkInfo.State.CONNECTING){
+				return true;
+			}
+		}catch (Exception e){
+		}
+
+
+		if(isNeedMobile){
+			try{
+				//获取状态
+				final NetworkInfo mobileNetwork = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+
+				if(mobileNetwork!=null&&mobileNetwork.getState()!=null&& (mobileNetwork.getState()== NetworkInfo.State.CONNECTED||mobileNetwork.getState()==NetworkInfo.State.CONNECTING)){
+					return true;
+				}
+			}catch (Exception e){
+			}
+
+		}
+
+		return false;
+	}
+}
diff --git a/app/src/main/java/com/navinfo/omqs/util/ShareUtil.java b/app/src/main/java/com/navinfo/omqs/util/ShareUtil.java
new file mode 100644
index 00000000..54e2511e
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/util/ShareUtil.java
@@ -0,0 +1,373 @@
+package com.navinfo.omqs.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import com.navinfo.omqs.system.SystemConstant;
+
+/**
+ * @ClassName:     ShareUtil.java
+ * @author         qj
+ * @version        V1.0
+ * @Date           2016年12月17日 下午1:56:02
+ * @Description:  相机数据存储
+ */
+public class ShareUtil {
+	//系统数据存储对象
+	private static SharedPreferences mSharePre=null;
+	//安卓编辑器
+	private static Editor editor;
+	//拍照状态标识
+   	private final static String CONTINUS_TAKE_PHOTO_STATE = "continue_take_photo_state";
+   	//外设相机按钮状态标识
+	private final static String SELECT_TAKE_PHOTO_OR_RECORD = "select_take_photo_or_record";
+	//外设相机种别标识
+	private final static String SELECT_CAMERA_KIND = "select_take_kind";
+	//外设相机连接标识
+	private final static String CAMERA_CONNECT_STATE = "camera_connect_state";
+	//外设相机工作模式
+	private final static String TAKE_CAMERA_MODE = "take_camera_mode";
+	//连接相机ip
+	private final static String TAKE_CAMERA_IP = "take_camera_ip";
+	//连接相机Mac
+	private final static String TAKE_CAMERA_MAC = "take_camera_mac";
+	//外设相机编号,应对多个相机连接使用,识别存储某一个设备连接状态等信息
+	private int mDeviceNum = 1;
+	//上下文
+	private Context mContext;
+
+	private ShareUtil() {
+	}
+
+	public ShareUtil(Context context, int deviceNum) {
+		mContext  = context;
+		mDeviceNum = deviceNum;
+	}
+
+	/**
+	 * method : getSelectCameraKind
+	 * Author : qj
+	 * Describe : 获取相机类型
+	 * param :  context 上下文
+	 * return true 相机 false视频
+	 * Date : 2018/4/23
+	 */
+	public boolean getSelectCameraKind(){
+		if(mContext==null)
+			return false;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
+		}
+		return mSharePre.getBoolean(mDeviceNum+SystemConstant.USER_ID+SELECT_CAMERA_KIND, false);
+	}
+
+	/**
+	 * method : setSelectCameraKind
+	 * Author : qj
+	 * Describe : 设置相机类型
+	 * param :  context 上下文
+	 * param : userid用户id
+	 * param : true 内置相机 false 外置相机
+	 * Date : 2018/4/23
+	 */
+	public void setSelectCameraKind(String userId,Boolean bll){
+		if(mContext==null)
+			return ;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
+		}
+
+		editor=mSharePre.edit();
+
+		 editor.putBoolean(mDeviceNum+userId+SELECT_CAMERA_KIND,bll).commit();
+	
+	}
+
+	/**
+	 * method : getSelectTakePhotoOrRecord
+	 * Author : qj
+	 * Describe : 获取相机使用类型
+	 * param :  context 上下文
+	 * param : true 相机拍照 false 录像视频
+	 * Date : 2018/4/23
+	 */
+	public boolean getSelectTakePhotoOrRecord(){
+		if(mContext==null)
+			return true;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_TAKEPHOTO_OR_RECORD, Context.MODE_PRIVATE);
+		}
+
+		return mSharePre.getBoolean(mDeviceNum+SystemConstant.USER_ID+SELECT_TAKE_PHOTO_OR_RECORD, mDeviceNum==1?true:false);
+
+	}
+
+	/**
+	 * method : setSelectTakePhotoOrRecord
+	 * Author : qj
+	 * Describe : 设置相机使用类型
+	 * param :  context 上下文
+	 * param : userid 用户id
+	 * param : true 相机拍照 false 录像视频
+	 * Date : 2018/4/23
+	 */
+	public void setSelectTakePhotoOrRecord(String userId,Boolean bll){
+		if(mContext==null)
+			return ;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_TAKEPHOTO_OR_RECORD, Context.MODE_PRIVATE);
+		}
+		editor=mSharePre.edit();
+
+		 editor.putBoolean(mDeviceNum+userId+SELECT_TAKE_PHOTO_OR_RECORD,bll).commit();
+	
+	}
+
+	/**
+	 * method : getContinusTakePhotoState
+	 * Author : qj
+	 * Describe : 获取相机工作状态
+	 * param :  context 上下文
+	 * Date : 2018/4/23
+	 */
+	public boolean getContinusTakePhotoState(){
+		if(mContext==null)
+			return true;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
+		}
+		return mSharePre.getBoolean(mDeviceNum+SystemConstant.USER_ID+CONTINUS_TAKE_PHOTO_STATE, true);
+
+	}
+
+	/**
+	 * method : setContinusTakePhotoState
+	 * Author : qj
+	 * Describe : 设置相机工作状态
+	 * param :  context 上下文
+	 * param : userid 用户id
+	 * param : true 停止 false 否
+	 * Date : 2018/4/23
+	 */
+	public void setContinusTakePhotoState(String userId,Boolean bll){
+		if(mContext==null)
+			return ;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
+		}
+		editor=mSharePre.edit();
+
+		 editor.putBoolean(mDeviceNum+userId+CONTINUS_TAKE_PHOTO_STATE,bll).commit();
+	}
+
+	/**
+	 * method : getConnectstate
+	 * Author : qj
+	 * Describe : 获取相机连接状态
+	 * param :  context 上下文
+	 * Date : 2018/4/23
+	 */
+	public boolean getConnectstate(){
+		if(mContext==null)
+			return false;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.CAMERA_CONNECT_STATE, Context.MODE_PRIVATE);
+		}
+		return mSharePre.getBoolean(mDeviceNum+SystemConstant.USER_ID+CAMERA_CONNECT_STATE, false);
+	}
+
+	/**
+	 * method : setConnectstate
+	 * Author : qj
+	 * Describe : 设置相机连接状态
+	 * param :  context 上下文
+	 * param : userid 用户id
+	 * param : true 连接 false 否
+	 * Date : 2018/4/23
+	 */
+	public void setConnectstate(String userId,Boolean bll){
+		if(mContext==null)
+			return ;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.CAMERA_CONNECT_STATE, Context.MODE_PRIVATE);
+		}
+		editor=mSharePre.edit();
+
+		editor.putBoolean(mDeviceNum+userId+CAMERA_CONNECT_STATE,bll).commit();
+	}
+
+	/**
+	 * method : getTakeCameraMode
+	 * Author : qj
+	 * Describe : 获取相机模式
+	 * param :  context 上下文
+	 * Date : 2018/4/23
+	 */
+	public int getTakeCameraMode(){
+		if(mContext==null)
+			return 0;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_MODE, Context.MODE_PRIVATE);
+		}
+
+		return mSharePre.getInt(mDeviceNum+SystemConstant.USER_ID+TAKE_CAMERA_MODE, mDeviceNum==1?0:1);
+
+	}
+
+	/**
+	 * method : setTakeCameraMode
+	 * Author : qj
+	 * Describe : 设置相机模式
+	 * param :  context 上下文
+	 * param : userid 用户id
+	 * param : int 0 视频 1 拍照
+	 * Date : 2018/4/23
+	 */
+	public void setTakeCameraMode(String userId,int mode){
+		if(mContext==null)
+			return ;
+
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_MODE, Context.MODE_PRIVATE);
+		}
+		editor=mSharePre.edit();
+
+		editor.putInt(mDeviceNum+userId+TAKE_CAMERA_MODE,mode).commit();
+	}
+
+	/**
+	 * method : getTakeCameraIP
+	 * Author : qj
+	 * Describe : 获取相机ip
+	 * param :  context 上下文
+	 * Date : 2018/4/23
+	 */
+	public  String getTakeCameraIP(){
+		if(mContext==null)
+			return "";
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_IP, Context.MODE_PRIVATE);
+		}
+		String ip=mSharePre.getString(mDeviceNum+SystemConstant.USER_ID+TAKE_CAMERA_IP, "");
+		return ip;
+	}
+
+	/**
+	 * method : setTakeCameraIP
+	 * Author : qj
+	 * Describe : 设置相机ip
+	 * param :  context 上下文
+	 * param : userid 用户id
+	 * param : ip 连接地址
+	 * Date : 2018/4/23
+	 */
+	public void setTakeCameraIP(String userId,String ip){
+		if(mContext==null)
+			return ;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_IP, Context.MODE_PRIVATE);
+		}
+
+		editor=mSharePre.edit();
+
+		editor.putString(mDeviceNum+userId+TAKE_CAMERA_IP,ip).commit();
+	}
+
+	/**
+	 * method : getTakeCameraMac
+	 * Author : qj
+	 * param : mac 硬件信息
+	 * param :  context 上下文
+	 * Date : 2018/4/23
+	 */
+	public  String getTakeCameraMac(){
+		if(mContext==null)
+			return "";
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_MAC, Context.MODE_PRIVATE);
+		}
+		String mac=mSharePre.getString(mDeviceNum+SystemConstant.USER_ID+TAKE_CAMERA_MAC, "");
+		return mac;
+	}
+
+	/**
+	 * method : setTakeCameraMac
+	 * Author : qj
+	 * Describe : 设置相机mac
+	 * param :  context 上下文
+	 * param : userid 用户id
+	 * param : mac 硬件信息
+	 * Date : 2018/4/23
+	 */
+	public void setTakeCameraMac(String userId,String mac){
+		if(mContext==null)
+			return ;
+
+		if(mSharePre==null){
+			mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_MAC, Context.MODE_PRIVATE);
+		}
+
+		editor=mSharePre.edit();
+
+		editor.putString(mDeviceNum+userId+TAKE_CAMERA_MAC,mac).commit();
+	}
+
+	/**
+	 * method : getConnectstateMac
+	 * Author : qj
+	 * param : mac 硬件信息
+	 * Date : 2018/4/23
+	 */
+	public static String getConnectstateMac(Context context){
+		if(context==null)
+			return "";
+
+		ShareUtil shareUtil = new ShareUtil(context,1);
+
+		if(shareUtil.getConnectstate())
+			return shareUtil.getTakeCameraMac();
+
+		shareUtil = new ShareUtil(context,2);
+
+		if(shareUtil.getConnectstate())
+			return shareUtil.getTakeCameraMac();
+
+		return "";
+	}
+
+	/**
+	 * method : getConnectstateMac
+	 * Author : qj
+	 * param : mac 硬件信息
+	 * Date : 2018/4/23
+	 */
+	public static ShareUtil getCameraMode(Context context){
+		if(context==null)
+			return null;
+
+		ShareUtil shareUtil = new ShareUtil(context,1);
+
+		if(shareUtil.getConnectstate()/*&&shareUtil.getTakeCameraMode()==0不需要判断相机类型*/)
+			return shareUtil;
+
+		shareUtil = new ShareUtil(context,2);
+
+		if(shareUtil.getConnectstate()/*&&shareUtil.getTakeCameraMode()==0不需要判断相机类型*/)
+			return shareUtil;
+
+		return null;
+	}
+}
diff --git a/app/src/main/res/color/btn_select_color.xml b/app/src/main/res/color/btn_select_color.xml
new file mode 100644
index 00000000..9c69fb58
--- /dev/null
+++ b/app/src/main/res/color/btn_select_color.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="#9F9F9F"/>
+    <item android:state_checked="true" android:color="@color/white"></item>
+    <item android:state_selected="true" android:color="@color/white"></item>
+    <item android:state_pressed="true" android:color="@color/white"></item>
+    <item android:color="#9F9F9F"></item>
+</selector>
diff --git a/app/src/main/res/color/common_dialog_cancel_text_selector.xml b/app/src/main/res/color/common_dialog_cancel_text_selector.xml
new file mode 100644
index 00000000..2b918209
--- /dev/null
+++ b/app/src/main/res/color/common_dialog_cancel_text_selector.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"  android:color="@color/red"/>
+    <item android:state_enabled="false" android:color="@color/text_hint_gray"/>
+</selector>
diff --git a/app/src/main/res/color/common_dialog_confirm_text_selector.xml b/app/src/main/res/color/common_dialog_confirm_text_selector.xml
new file mode 100644
index 00000000..7d3143dd
--- /dev/null
+++ b/app/src/main/res/color/common_dialog_confirm_text_selector.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+     <item android:state_enabled="true"  android:color="@color/blue"/>
+     <item android:state_enabled="false" android:color="@color/text_hint_gray"/>
+</selector>
diff --git a/app/src/main/res/color/common_dialog_middle_text_selector.xml b/app/src/main/res/color/common_dialog_middle_text_selector.xml
new file mode 100644
index 00000000..59fdfd14
--- /dev/null
+++ b/app/src/main/res/color/common_dialog_middle_text_selector.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"  android:color="@color/orange"/>
+     <item android:state_enabled="false" android:color="@color/text_hint_gray"/>
+</selector>
diff --git a/app/src/main/res/color/selector_default_text_color_white_enable_gray.xml b/app/src/main/res/color/selector_default_text_color_white_enable_gray.xml
new file mode 100644
index 00000000..18707d36
--- /dev/null
+++ b/app/src/main/res/color/selector_default_text_color_white_enable_gray.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"  android:color="@color/line_gray" />
+    <item android:color="@color/white" />
+
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_bg_default.xml b/app/src/main/res/drawable/btn_bg_default.xml
new file mode 100644
index 00000000..bb1aa4b3
--- /dev/null
+++ b/app/src/main/res/drawable/btn_bg_default.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+   <item android:state_enabled="false" android:drawable="@color/white"></item>
+    <item android:state_checked="true" android:drawable="@drawable/icon_btn_bg_gray_press"></item>
+    <item android:state_selected="true" android:drawable="@drawable/icon_btn_bg_gray_press"></item>
+    <item android:state_pressed="true" android:drawable="@drawable/icon_btn_bg_gray_press"></item>
+    <item  android:drawable="@drawable/icon_btn_bg_white_nor"></item>
+
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_connect_bg_enabled.xml b/app/src/main/res/drawable/btn_connect_bg_enabled.xml
new file mode 100644
index 00000000..edd37fc7
--- /dev/null
+++ b/app/src/main/res/drawable/btn_connect_bg_enabled.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+            <solid android:color="@color/blue" />
+
+            <corners android:radius="@dimen/five" />
+</shape>
diff --git a/app/src/main/res/drawable/btn_red_disconnect_bg.xml b/app/src/main/res/drawable/btn_red_disconnect_bg.xml
new file mode 100644
index 00000000..46cc1931
--- /dev/null
+++ b/app/src/main/res/drawable/btn_red_disconnect_bg.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <solid android:color="#fe1a1a" />
+
+    <corners android:radius="@dimen/five" />
+
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/chk_icon_camera_open_close_xml.xml b/app/src/main/res/drawable/chk_icon_camera_open_close_xml.xml
new file mode 100644
index 00000000..1119bd24
--- /dev/null
+++ b/app/src/main/res/drawable/chk_icon_camera_open_close_xml.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:drawable="@mipmap/icon_camera_on">
+    </item>
+    <item android:state_selected="true" android:drawable="@mipmap/icon_camera_on">
+    </item>
+    <item android:drawable="@mipmap/icon_camera_off">
+    </item>
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/chk_icon_camera_record_or_takephoto_xml.xml b/app/src/main/res/drawable/chk_icon_camera_record_or_takephoto_xml.xml
new file mode 100644
index 00000000..7c7a5a79
--- /dev/null
+++ b/app/src/main/res/drawable/chk_icon_camera_record_or_takephoto_xml.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:drawable="@mipmap/record_select">
+    </item>
+    <item android:state_selected="true" android:drawable="@mipmap/record_select">
+    </item>
+    <item android:drawable="@mipmap/takephoto_select">
+    </item>
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/chk_icon_camera_start_stop_xml.xml b/app/src/main/res/drawable/chk_icon_camera_start_stop_xml.xml
new file mode 100644
index 00000000..ca55bb7e
--- /dev/null
+++ b/app/src/main/res/drawable/chk_icon_camera_start_stop_xml.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_enabled="true" android:drawable="@mipmap/icon_camera_start">
+    </item>
+    <item android:state_selected="true" android:state_enabled="true" android:drawable="@mipmap/icon_camera_start">
+    </item>
+    <item android:state_enabled="false" android:drawable="@mipmap/icon_camera_start_disable">
+    </item>
+    <item android:drawable="@mipmap/icon_camera_end">
+    </item>
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/dialog_bg.xml b/app/src/main/res/drawable/dialog_bg.xml
new file mode 100644
index 00000000..c08ea5cd
--- /dev/null
+++ b/app/src/main/res/drawable/dialog_bg.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+
+    <corners
+        android:bottomLeftRadius="@dimen/five"
+        android:bottomRightRadius="@dimen/five"
+        android:topLeftRadius="@dimen/five"
+        android:topRightRadius="@dimen/five" />
+
+    <solid android:color="@color/white" />
+<!--     <solid android:color="@color/fm_kit_white" /> -->
+
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/dialog_bg_cancel.xml b/app/src/main/res/drawable/dialog_bg_cancel.xml
new file mode 100644
index 00000000..f46b1ed1
--- /dev/null
+++ b/app/src/main/res/drawable/dialog_bg_cancel.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    >
+     <item android:state_enabled="false">
+	    <shape android:shape="rectangle" >
+		    <corners android:bottomLeftRadius="@dimen/five" />
+		    <solid android:color="@color/line_gray" />
+	    </shape>
+    </item>
+    <item android:state_pressed="true">
+	    <shape android:shape="rectangle" >
+		    <corners android:bottomLeftRadius="@dimen/five" />
+		    <solid android:color="#f1f1f1" />
+	    </shape>
+    </item>
+<!-- 		    <solid android:color="@color/fm_card_default_bg_color" /> -->
+    <item >
+		<shape android:shape="rectangle" >
+		    <corners android:bottomLeftRadius="@dimen/five" />
+		    <solid android:color="@android:color/white" />
+	    </shape>
+    </item>
+</selector>
diff --git a/app/src/main/res/drawable/dialog_bg_ok.xml b/app/src/main/res/drawable/dialog_bg_ok.xml
new file mode 100644
index 00000000..5dee094d
--- /dev/null
+++ b/app/src/main/res/drawable/dialog_bg_ok.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    >
+      <item android:state_enabled="false">
+		<shape android:shape="rectangle" >
+		    <corners   android:bottomRightRadius="@dimen/five" />
+		    <solid android:color="#e1e1e1" />
+	    </shape>
+    </item>
+    <item android:state_pressed="true">
+		<shape android:shape="rectangle" >
+		    <corners   android:bottomRightRadius="@dimen/five" />
+		    <solid android:color="#f1f1f1" />
+	    </shape>
+    </item>
+<!-- 		    <solid android:color="@color/fm_card_default_bg_color" /> -->
+    <item >
+		<shape android:shape="rectangle" >
+		    <corners android:bottomRightRadius="@dimen/five" />
+		    <solid android:color="@android:color/white" />
+	    </shape>
+    </item>
+</selector>
diff --git a/app/src/main/res/drawable/drawable_bg_blue_bg_4_radius.xml b/app/src/main/res/drawable/drawable_bg_blue_bg_4_radius.xml
new file mode 100644
index 00000000..cf3c0fea
--- /dev/null
+++ b/app/src/main/res/drawable/drawable_bg_blue_bg_4_radius.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+    <solid android:color="@color/blue" />
+    <corners
+        android:bottomLeftRadius="5dp"
+        android:bottomRightRadius="5dp"
+        android:topLeftRadius="5dp"
+        android:topRightRadius="5dp" />
+    <padding
+        android:bottom="1dp"
+        android:left="1dp"
+        android:right="1dp"
+        android:top="1dp"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/icon_btn_bg_gray_press.9.png b/app/src/main/res/drawable/icon_btn_bg_gray_press.9.png
new file mode 100644
index 00000000..f11d6107
Binary files /dev/null and b/app/src/main/res/drawable/icon_btn_bg_gray_press.9.png differ
diff --git a/app/src/main/res/drawable/icon_btn_bg_white_nor.9.png b/app/src/main/res/drawable/icon_btn_bg_white_nor.9.png
new file mode 100644
index 00000000..8f66eabd
Binary files /dev/null and b/app/src/main/res/drawable/icon_btn_bg_white_nor.9.png differ
diff --git a/app/src/main/res/drawable/icon_camera_close_xml.xml b/app/src/main/res/drawable/icon_camera_close_xml.xml
new file mode 100644
index 00000000..6bbcc538
--- /dev/null
+++ b/app/src/main/res/drawable/icon_camera_close_xml.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@mipmap/icon_camera_close_press" android:state_focused="true"></item>
+    <item android:drawable="@mipmap/icon_camera_close_press" android:state_pressed="true"></item>
+    <item android:drawable="@mipmap/icon_camera_close_press" android:state_selected="true"></item>
+    <item android:drawable="@mipmap/icon_camera_close_press" android:state_checked="true"></item>
+    <item android:drawable="@mipmap/icon_camera_close_normal"></item>
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/loading_anim.xml b/app/src/main/res/drawable/loading_anim.xml
new file mode 100644
index 00000000..c80cc1ef
--- /dev/null
+++ b/app/src/main/res/drawable/loading_anim.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="false" >
+
+    <item
+        android:drawable="@mipmap/loading_01"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_02"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_03"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_04"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_05"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_06"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_07"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_08"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_09"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_10"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_11"
+        android:duration="60"/>
+    <item
+        android:drawable="@mipmap/loading_12"
+        android:duration="60"/>
+
+</animation-list>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/pop_camera_img.xml b/app/src/main/res/drawable/pop_camera_img.xml
new file mode 100644
index 00000000..fb7e8b10
--- /dev/null
+++ b/app/src/main/res/drawable/pop_camera_img.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
+      <item android:drawable="@mipmap/icon_page_video_a3" android:duration="1000" />
+   <item android:drawable="@mipmap/icon_page_video_a0" android:duration="1000" />
+   <item android:drawable="@mipmap/icon_page_video_a3" android:duration="1000" />
+   <item android:drawable="@mipmap/icon_page_video_a0" android:duration="1000" />
+</animation-list>
diff --git a/app/src/main/res/drawable/pop_camera_take_photo_img.xml b/app/src/main/res/drawable/pop_camera_take_photo_img.xml
new file mode 100644
index 00000000..5acd8ef8
--- /dev/null
+++ b/app/src/main/res/drawable/pop_camera_take_photo_img.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
+      <item android:drawable="@mipmap/icon_page_take_photo_a3" android:duration="1000" />
+   <item android:drawable="@mipmap/icon_page_take_photo_a3" android:duration="1000" />
+   <item android:drawable="@mipmap/icon_page_take_photo_a3" android:duration="1000" />
+   <item android:drawable="@mipmap/icon_page_take_photo_a0" android:duration="1000" />
+</animation-list>
diff --git a/app/src/main/res/drawable/progress_bg.xml b/app/src/main/res/drawable/progress_bg.xml
index 244083fc..45d0d3d6 100644
--- a/app/src/main/res/drawable/progress_bg.xml
+++ b/app/src/main/res/drawable/progress_bg.xml
@@ -14,7 +14,7 @@
         <clip android:clipOrientation="horizontal">
             <shape>
                 <corners android:radius="4dp" />
-                <solid android:color="@color/default_blue" />
+                <solid android:color="@color/blue" />
             </shape>
         </clip>
     </item>
diff --git a/app/src/main/res/drawable/selector_bg_blue_gray_bg_4_radius.xml b/app/src/main/res/drawable/selector_bg_blue_gray_bg_4_radius.xml
new file mode 100644
index 00000000..63b99406
--- /dev/null
+++ b/app/src/main/res/drawable/selector_bg_blue_gray_bg_4_radius.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:drawable="@drawable/shade_btn_gray_bg_4_radius_hd"></item>
+    <item android:state_checked="true" android:drawable="@drawable/drawable_bg_blue_bg_4_radius"/>
+    <item android:state_pressed="true" android:drawable="@drawable/drawable_bg_blue_bg_4_radius"/>
+    <item android:state_selected="true" android:drawable="@drawable/drawable_bg_blue_bg_4_radius"></item>
+    <item android:drawable="@drawable/drawable_bg_blue_bg_4_radius"/>
+
+</selector>
diff --git a/app/src/main/res/drawable/selector_default_text_color_white_enable_gray.xml b/app/src/main/res/drawable/selector_default_text_color_white_enable_gray.xml
new file mode 100644
index 00000000..18707d36
--- /dev/null
+++ b/app/src/main/res/drawable/selector_default_text_color_white_enable_gray.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"  android:color="@color/line_gray" />
+    <item android:color="@color/white" />
+
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shade_btn_gray_bg_4_radius_hd.xml b/app/src/main/res/drawable/shade_btn_gray_bg_4_radius_hd.xml
new file mode 100644
index 00000000..0a579e50
--- /dev/null
+++ b/app/src/main/res/drawable/shade_btn_gray_bg_4_radius_hd.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+    <solid android:color="@color/gray_121" />
+    <corners
+        android:bottomLeftRadius="5dp"
+        android:bottomRightRadius="5dp"
+        android:topLeftRadius="5dp"
+        android:topRightRadius="5dp" />
+    <padding
+        android:bottom="1dp"
+        android:left="1dp"
+        android:right="1dp"
+        android:top="1dp"/>
+</shape>
diff --git a/app/src/main/res/drawable/transient_toast_bg.xml b/app/src/main/res/drawable/transient_toast_bg.xml
new file mode 100644
index 00000000..9f1f934f
--- /dev/null
+++ b/app/src/main/res/drawable/transient_toast_bg.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+    <corners android:topLeftRadius="3dp" android:topRightRadius="3dp" android:bottomLeftRadius="3dp" android:bottomRightRadius="3dp"></corners>
+    <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp"/>
+	<solid android:color="#AA535353"></solid>
+</shape>
diff --git a/app/src/main/res/layout/connect_out_camera.xml b/app/src/main/res/layout/connect_out_camera.xml
new file mode 100644
index 00000000..8c0f6134
--- /dev/null
+++ b/app/src/main/res/layout/connect_out_camera.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:scrollbars="vertical">
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal">
+
+        <ImageView
+            android:id="@+id/cancel_dialog"
+            android:layout_width="40dp"
+            android:layout_height="10dp"
+            android:visibility="invisible"
+            android:src="@drawable/icon_camera_close_xml" />
+
+        <LinearLayout
+            android:id="@+id/layer_connectCamera_operate"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/fl_layout"
+            android:background="@color/white"
+            android:gravity="center_vertical"
+            android:orientation="vertical"
+            android:paddingBottom="15dp"
+            android:paddingLeft="10dp"
+            android:paddingRight="10dp"
+            android:paddingTop="15dp">
+
+            <RelativeLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="20dp"
+                android:orientation="horizontal"
+                android:visibility="gone">
+
+                <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentLeft="true"
+                    android:layout_centerVertical="true"
+                    android:text="默认外设相机拍照"
+                    android:textColor="@android:color/black"
+                    android:textSize="15sp" />
+
+                <CheckBox
+                    android:id="@+id/select_camera"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentRight="true"
+                    android:layout_centerVertical="true"
+                    android:button="@drawable/chk_icon_camera_open_close_xml" />
+            </RelativeLayout>
+
+            <TextView
+                android:id="@+id/gps_status_hint"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_marginBottom="1dp"
+                android:ellipsize="marquee"
+                android:focusable="true"
+                android:focusableInTouchMode="true"
+                android:gravity="center"
+                android:marqueeRepeatLimit="marquee_forever"
+                android:padding="@dimen/ten"
+                android:textColor="@color/red"
+                android:scrollHorizontally="true"
+                android:visibility="gone"
+                android:singleLine="true"
+                android:text="相机GPS信号差,请稍等片刻,或将相机移到开发地带。"
+                android:textSize="@dimen/card_title_font_2size" />
+
+            <TextView
+                android:id="@+id/one_bt_connect"
+                style="@style/fm_btn_default_blue_white"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="1dp"
+                android:padding="@dimen/ten"
+                android:text="一键连接"
+                android:textSize="@dimen/card_title_font_2size" />
+        </LinearLayout>
+
+        <FrameLayout
+            android:id="@+id/fl_layout"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/camear_dialog_hight"
+            android:layout_below="@+id/cancel_dialog"
+            android:background="@color/bg_gray2">
+
+
+            <CheckBox
+                android:id="@+id/startorendtakepicture"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="bottom|center_horizontal"
+                android:button="@drawable/chk_icon_camera_start_stop_xml"
+                android:checked="true"
+                android:enabled="false" />
+
+
+            <CheckBox
+                android:id="@+id/takephoto_or_record"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="right|bottom"
+                android:layout_margin="10dp"
+                android:button="@drawable/chk_icon_camera_record_or_takephoto_xml"
+                android:checked="true"
+                android:paddingLeft="@dimen/five"
+                android:text="录像"
+                android:textColor="@color/white" />
+
+            <ImageView
+                android:id="@+id/video_defalut"
+                android:layout_width="148.5dp"
+                android:layout_height="@dimen/camear_dialog_iv_hight"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginTop="@dimen/camear_dialog_iv_margin_top"
+                android:src="@mipmap/icon_camera_img" />
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="40dp"
+                android:layout_gravity="bottom"
+                android:background="@color/bg_dark"
+                android:orientation="horizontal">
+
+                <ImageView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_marginLeft="@dimen/five"
+                    android:src="@mipmap/icon_camera_time" />
+
+                <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:layout_marginLeft="@dimen/five"
+                    android:text="00:00:00"
+                    android:textColor="@color/white"
+                    android:textSize="15sp" />
+
+            </LinearLayout>
+
+            <SurfaceView
+                android:id="@+id/video"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_centerInParent="true"
+                android:background="@color/bg_gray2"
+                android:fitsSystemWindows="true"
+                android:visibility="gone" />
+        </FrameLayout>
+
+    </RelativeLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_default.xml b/app/src/main/res/layout/dialog_default.xml
new file mode 100644
index 00000000..eeaacc37
--- /dev/null
+++ b/app/src/main/res/layout/dialog_default.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:id="@+id/ll_dialog"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:background="@drawable/dialog_bg"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/ll_title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentTop="true"
+            android:gravity="center"
+            android:orientation="vertical"
+            android:visibility="gone">
+
+            <TextView
+                android:id="@+id/tv_title"
+                style="@style/content_font_default"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@android:color/transparent"
+                android:paddingBottom="@dimen/three"
+                android:paddingLeft="@dimen/eight"
+                android:paddingRight="@dimen/eight"
+                android:paddingTop="@dimen/eight"
+                android:text="title"
+                android:textColor="@color/black"
+                android:textSize="@dimen/card_title_font_2size" />
+
+            <View
+                android:id="@+id/title_divider"
+                android:layout_width="match_parent"
+                android:layout_height="0.6dp"
+                android:layout_marginBottom="@dimen/five"
+                android:layout_marginTop="@dimen/five"
+                android:background="@color/line_gray" />
+
+            <TextView
+                android:id="@+id/tv_title2"
+                style="@style/content_font_default"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@android:color/transparent"
+                android:paddingBottom="@dimen/eight"
+                android:text="title"
+                android:textColor="@color/black"
+                android:textSize="@dimen/card_title_font_3size"
+                android:visibility="gone" />
+
+            <View
+                android:id="@+id/title_divider2"
+                android:layout_width="match_parent"
+                android:layout_height="0.6dp"
+                android:background="@color/line_gray"
+                android:visibility="gone" />
+        </LinearLayout>
+
+        <RelativeLayout
+            android:id="@+id/rl_content_view"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center">
+
+            <TextView
+                android:id="@+id/tv_content"
+                style="@style/content_font_default"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:background="@android:color/transparent"
+                android:gravity="center"
+                android:paddingBottom="@dimen/twenty_two"
+                android:paddingLeft="@dimen/twelve"
+                android:paddingRight="@dimen/twelve"
+                android:paddingTop="@dimen/twenty"
+                android:text="提示内容"
+                android:textColor="@color/black"
+                android:textSize="@dimen/card_title_font_3size" />
+        </RelativeLayout>
+
+
+        <LinearLayout
+            android:id="@+id/ll_bottom_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:gravity="center"
+            android:orientation="vertical">
+
+            <View
+                android:id="@+id/v_divice"
+                android:layout_width="match_parent"
+                android:layout_height="0.6dp"
+                android:background="@color/line_gray"
+                android:visibility="visible" />
+
+            <LinearLayout
+                android:id="@+id/ll_bottom_btn"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:visibility="gone">
+
+                <TextView
+                    android:id="@+id/btn_fm_cancel"
+                    style="@style/btn_default_style"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:background="@drawable/dialog_bg_cancel"
+                    android:gravity="center"
+                    android:padding="@dimen/twelve"
+                    android:text="取消"
+                    android:textColor="@color/common_dialog_cancel_text_selector" />
+
+                <View
+                    android:id="@+id/middle_view"
+                    android:layout_width="0.6dp"
+                    android:layout_height="match_parent"
+                    android:background="@drawable/dialog_bg_cancel"
+                    android:visibility="gone" />
+
+                <TextView
+                    android:id="@+id/btn_fm_middle"
+                    style="@style/btn_default_style"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:background="@drawable/dialog_bg_ok"
+                    android:gravity="center"
+                    android:padding="@dimen/twelve"
+                    android:text="中间"
+                    android:textColor="@color/common_dialog_middle_text_selector"
+                    android:visibility="gone" />
+
+                <View
+                    android:id="@+id/view_dialog"
+                    android:layout_width="0.6dp"
+                    android:layout_height="match_parent"
+                    android:background="@color/line_gray" />
+
+                <TextView
+                    android:id="@+id/btn_fm_confirm"
+                    style="@style/btn_default_style"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:background="@drawable/dialog_bg_ok"
+                    android:gravity="center"
+                    android:padding="@dimen/twelve"
+                    android:text="确定"
+                    android:textColor="@color/common_dialog_confirm_text_selector" />
+            </LinearLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+</RelativeLayout>
diff --git a/app/src/main/res/layout/dialog_loading_custom_frame_layout.xml b/app/src/main/res/layout/dialog_loading_custom_frame_layout.xml
new file mode 100644
index 00000000..9508e30c
--- /dev/null
+++ b/app/src/main/res/layout/dialog_loading_custom_frame_layout.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/parentPanel"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:background="@color/white"
+    android:orientation="horizontal" >
+
+    <ImageView
+        android:id="@+id/customFrameLoadImg"
+        android:layout_width="60dp"
+        android:layout_height="60dp"
+        android:background="@drawable/loading_anim" />
+
+    <TextView
+        android:id="@+id/customFrameMsg"
+        android:layout_width="wrap_content"
+        android:textColor="@color/black"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="10dp"
+        android:singleLine="true"
+        android:textSize="14sp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_offline_map.xml b/app/src/main/res/layout/fragment_offline_map.xml
index 03bf1190..e1212d77 100644
--- a/app/src/main/res/layout/fragment_offline_map.xml
+++ b/app/src/main/res/layout/fragment_offline_map.xml
@@ -11,7 +11,7 @@
         android:id="@+id/offline_map_tab_layout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="@color/default_blue"
+        android:background="@color/blue"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintTop_toTopOf="parent">
 
diff --git a/app/src/main/res/layout/fragment_offline_map_state_list.xml b/app/src/main/res/layout/fragment_offline_map_state_list.xml
index 5de6383b..feaefe01 100644
--- a/app/src/main/res/layout/fragment_offline_map_state_list.xml
+++ b/app/src/main/res/layout/fragment_offline_map_state_list.xml
@@ -4,7 +4,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@color/default_red"
+    android:background="@color/red"
     tools:context=".ui.fragment.offlinemap.OfflineMapStateListFragment">
 
     <TextView
diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml
index 0a7f8b09..f245a323 100644
--- a/app/src/main/res/layout/map_view.xml
+++ b/app/src/main/res/layout/map_view.xml
@@ -34,6 +34,29 @@
             app:layout_constraintLeft_toLeftOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
 
+        <ImageButton
+            android:id="@+id/main_activity_camera"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginLeft="160dp"
+            android:layout_marginTop="20dp"
+            android:onClick="@{()->mainActivity.openCamera()}"
+            android:src="@mipmap/icon_page_video_a1"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <ImageButton
+            android:id="@+id/main_activity_camera2"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:visibility="gone"
+            android:layout_marginLeft="20dp"
+            android:layout_marginTop="20dp"
+            android:onClick="@{()->mainActivity.openCamera()}"
+            android:src="@drawable/baseline_person_24"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
         <ImageButton
             android:id="@+id/main_activity_location"
             android:layout_width="48dp"
diff --git a/app/src/main/res/layout/personal_center_head.xml b/app/src/main/res/layout/personal_center_head.xml
index 30935119..7b3e03f6 100644
--- a/app/src/main/res/layout/personal_center_head.xml
+++ b/app/src/main/res/layout/personal_center_head.xml
@@ -3,7 +3,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="@dimen/nav_header_height"
-    android:background="@color/default_blue"
+    android:background="@color/blue"
     android:gravity="bottom"
     android:orientation="vertical"
     android:paddingLeft="@dimen/activity_horizontal_margin"
diff --git a/app/src/main/res/layout/transient_notification.xml b/app/src/main/res/layout/transient_notification.xml
new file mode 100644
index 00000000..6c495d72
--- /dev/null
+++ b/app/src/main/res/layout/transient_notification.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/layout/transient_notification.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/transient_toast_bg"
+    android:orientation="vertical" >
+    <TextView
+        android:textSize="@dimen/card_title_font_2size"
+        android:id="@android:id/message"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:shadowColor="#BB000000"
+        android:shadowRadius="2.75"
+        android:textAppearance="@android:style/TextAppearance.Small"
+        android:textColor="@android:color/background_light" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/loading_01.png b/app/src/main/res/mipmap-hdpi/loading_01.png
new file mode 100644
index 00000000..1c190a99
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_01.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_02.png b/app/src/main/res/mipmap-hdpi/loading_02.png
new file mode 100644
index 00000000..bc930f2d
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_02.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_03.png b/app/src/main/res/mipmap-hdpi/loading_03.png
new file mode 100644
index 00000000..e461335e
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_03.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_04.png b/app/src/main/res/mipmap-hdpi/loading_04.png
new file mode 100644
index 00000000..071af1ed
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_04.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_05.png b/app/src/main/res/mipmap-hdpi/loading_05.png
new file mode 100644
index 00000000..43ba85ff
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_05.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_06.png b/app/src/main/res/mipmap-hdpi/loading_06.png
new file mode 100644
index 00000000..67c6faa1
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_06.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_07.png b/app/src/main/res/mipmap-hdpi/loading_07.png
new file mode 100644
index 00000000..797c5d8a
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_07.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_08.png b/app/src/main/res/mipmap-hdpi/loading_08.png
new file mode 100644
index 00000000..bbeecf25
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_08.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_09.png b/app/src/main/res/mipmap-hdpi/loading_09.png
new file mode 100644
index 00000000..397c08da
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_09.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_10.png b/app/src/main/res/mipmap-hdpi/loading_10.png
new file mode 100644
index 00000000..2c4c58b2
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_10.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_11.png b/app/src/main/res/mipmap-hdpi/loading_11.png
new file mode 100644
index 00000000..587c1df6
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_11.png differ
diff --git a/app/src/main/res/mipmap-hdpi/loading_12.png b/app/src/main/res/mipmap-hdpi/loading_12.png
new file mode 100644
index 00000000..162ffd46
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/loading_12.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_close_normal.png b/app/src/main/res/mipmap-xhdpi/icon_camera_close_normal.png
new file mode 100644
index 00000000..8290ed44
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_close_normal.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_close_press.png b/app/src/main/res/mipmap-xhdpi/icon_camera_close_press.png
new file mode 100644
index 00000000..59f00328
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_close_press.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_end.png b/app/src/main/res/mipmap-xhdpi/icon_camera_end.png
new file mode 100644
index 00000000..09e2ead9
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_end.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_img.png b/app/src/main/res/mipmap-xhdpi/icon_camera_img.png
new file mode 100644
index 00000000..f43569ec
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_img.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_off.png b/app/src/main/res/mipmap-xhdpi/icon_camera_off.png
new file mode 100644
index 00000000..c184fa69
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_off.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_on.png b/app/src/main/res/mipmap-xhdpi/icon_camera_on.png
new file mode 100644
index 00000000..77c08ef2
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_on.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_start.png b/app/src/main/res/mipmap-xhdpi/icon_camera_start.png
new file mode 100644
index 00000000..f3cb8821
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_start.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_start_disable.png b/app/src/main/res/mipmap-xhdpi/icon_camera_start_disable.png
new file mode 100644
index 00000000..e66018ef
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_start_disable.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_take_photo_img.png b/app/src/main/res/mipmap-xhdpi/icon_camera_take_photo_img.png
new file mode 100644
index 00000000..ec88d2af
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_take_photo_img.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_camera_time.png b/app/src/main/res/mipmap-xhdpi/icon_camera_time.png
new file mode 100644
index 00000000..94777f50
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_camera_time.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a0.png b/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a0.png
new file mode 100644
index 00000000..8916ca0d
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a0.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a1.png b/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a1.png
new file mode 100644
index 00000000..b9b30d8a
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a1.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a2.png b/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a2.png
new file mode 100644
index 00000000..ca4a4e80
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a2.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a3.png b/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a3.png
new file mode 100644
index 00000000..d513a9d9
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_page_take_photo_a3.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_page_video_a0.png b/app/src/main/res/mipmap-xhdpi/icon_page_video_a0.png
new file mode 100644
index 00000000..975bafaa
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_page_video_a0.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_page_video_a1.png b/app/src/main/res/mipmap-xhdpi/icon_page_video_a1.png
new file mode 100644
index 00000000..221c49a7
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_page_video_a1.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_page_video_a2.png b/app/src/main/res/mipmap-xhdpi/icon_page_video_a2.png
new file mode 100644
index 00000000..17858f57
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_page_video_a2.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_page_video_a3.png b/app/src/main/res/mipmap-xhdpi/icon_page_video_a3.png
new file mode 100644
index 00000000..fdf21227
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_page_video_a3.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/record_select.png b/app/src/main/res/mipmap-xhdpi/record_select.png
new file mode 100644
index 00000000..d265c7bb
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/record_select.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/takephoto_select.png b/app/src/main/res/mipmap-xhdpi/takephoto_select.png
new file mode 100644
index 00000000..f7d72ed0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/takephoto_select.png differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 3a08ff82..6e54318f 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -2,8 +2,21 @@
 <resources>
     <color name="black">#FF000000</color>
     <color name="white">#FFFFFFFF</color>
+    <color name="red">#FF0000</color>
+    <color name="transp">#00000000</color>
+    <color name="orange">#ff8d36</color>
+    <color name="blue" comment="应用主要色调">#1abbfe</color>
+    <color name="line_gray" comment="轻度灰色,一般用于下划线,不可点击按钮的边框">#dadade</color>
     <color name="cv_gray_153">#999999</color>
     <color name="cvm_red">#FF3B30</color>
     <color name="cv_bg_color">#553C3F41</color>
     <color name="btn_blue_solid">#108ee9</color>
+    <color name="background_light">#ffffffff</color>
+    <!-- 一键连接对话框背景色 -->
+    <color name="bg_gray2">#d1d1d1</color>
+    <!-- 一键连接时间显示区域背景色 -->
+    <color name="bg_dark">#999999</color>
+    <color name="gray_121">#797979</color>
+    <color name="gray_59">#595959</color>
+    <color name="text_hint_gray" comment="输入框内默认字体颜色,输入框边框颜色">#c1c1c1</color>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 094d4c98..480ce172 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -9,4 +9,28 @@
     <dimen name="default_font_size" comment="默认字体大小,style中父最顶层">15dp</dimen>
     <dimen name="card_title_font_2size">13sp</dimen>
     <dimen name="card_title_font_3size">10sp</dimen>
+    <dimen name="one">1dp</dimen>
+    <dimen name="two">2dp</dimen>
+    <dimen name="three">3dp</dimen>
+    <dimen name="four">4dp</dimen>
+    <dimen name="five">5dp</dimen>
+    <dimen name="six">6dp</dimen>
+    <dimen name="eight">8dp</dimen>
+    <dimen name="nine">9dp</dimen>
+    <dimen name="ten">10dp</dimen>
+    <dimen name="twelve">12dp</dimen>
+    <dimen name="twefour">14dp</dimen>
+    <dimen name="fifteen">15dp</dimen>
+    <dimen name="sixteen">16dp</dimen>
+    <dimen name="eighteen">18dp</dimen>
+    <dimen name="twenty">20dp</dimen>
+    <dimen name="twenty_two">22dp</dimen>
+    <dimen name="twenty_four">24dp</dimen>
+    <!-- 相机设置iv距离上方间距-->
+    <dimen name="camear_dialog_iv_margin_top" comment="相机设置窗体高度">25dp</dimen>
+    <!-- 相机设置窗体高度-->
+    <dimen name="camear_dialog_hight" comment="相机设置窗体高度">150dp</dimen>
+    <!-- 相机设置窗体IV高度-->
+    <dimen name="camear_dialog_iv_hight" comment="相机设置窗体高度">75dp</dimen>
+    <dimen name="head_img_width">48dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index ea96791b..4c69500a 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -6,7 +6,7 @@
         <item name="android:clickable">true</item>
         <item name="android:focusable">true</item>
         <item name="android:layout_alignParentTop">true</item>
-        <item name="android:background">@color/default_blue</item>
+        <item name="android:background">@color/blue</item>
         <item name="android:paddingBottom">6dp</item>
         <item name="android:paddingLeft">14dp</item>
         <item name="android:paddingRight">14dp</item>
@@ -54,4 +54,33 @@
         <item name="android:textColor">@color/btn_blue_white</item>
         <item name="android:textSize">15sp</item>
     </style>
+
+    <!-- 默认按钮样式 -->
+    <style name="btn_default_style" parent="content_font_default">
+        <item name="android:textColor">@color/btn_select_color</item>
+        <item name="android:background">@drawable/btn_bg_default</item>
+        <item name="android:clickable">true</item>
+        <item name="android:focusable">true</item>
+        <item name="android:gravity">center</item>
+        <item name="android:paddingBottom">1dp</item>
+    </style>
+
+    <style name="fm_btn_default_blue_white" parent="@android:style/Widget.Button">
+        <item name="android:background">@drawable/selector_bg_blue_gray_bg_4_radius</item>
+        <item name="android:textColor">@color/selector_default_text_color_white_enable_gray</item>
+        <item name="android:padding">@dimen/five</item>
+    </style>
+
+    <style name="MyDialog" parent="Theme.AppCompat.DialogWhenLarge">
+        <item name="android:windowFrame">@null</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:windowContentOverlay">@null</item>
+    </style>
+
+    <!-- 连续拍照对话框 -->
+    <style name="MyCustomDialog" parent="@style/MyDialog">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowNoTitle">true</item>
+    </style>
 </resources>
diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml
new file mode 100644
index 00000000..70cd516f
--- /dev/null
+++ b/app/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="MissingDefaultResource">
+    <base-config cleartextTrafficPermitted="true" />
+</network-security-config>
\ No newline at end of file
diff --git a/collect-library/build.gradle b/collect-library/build.gradle
index b56d5058..2b609930 100644
--- a/collect-library/build.gradle
+++ b/collect-library/build.gradle
@@ -10,41 +10,17 @@ ext.vtmVersion = "0.18.0"
 ext.realm_version = '10.10.1'
 ext.appcompatVersion = "1.3.0"
 ext.materialVersion = "1.5.0"
-ext.kotlin_version = '1.7.0'
+ext.kotlin_version = '1.8.0'
 
 android {
     compileSdk 30
 
-    defaultConfig {
-        minSdk 23
-        targetSdk 30
-        versionCode 1
-        versionName "1.0"
-
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        consumerProguardFiles "consumer-rules.pro"
-
-        // 指定room.schemaLocation生成的文件路径
-        javaCompileOptions {
-            annotationProcessorOptions {
-                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
-            }
-        }
-        ndk {
-            abiFilters "armeabi", "armeabi-v7a"
-        }
-    }
-
     buildTypes {
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
 
     sourceSets {
         main {
@@ -55,8 +31,7 @@ android {
 
 
 dependencies {
-    compileOnly fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
-    api files('libs/BaiduLBS_AndroidSDK_Lib.aar')
+    api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
     implementation "androidx.appcompat:appcompat:$appcompatVersion"
     implementation "com.google.android.material:material:$materialVersion"
     testImplementation 'junit:junit:4.13.2'
diff --git a/collect-library/libs/BaiduLBS_Android.jar b/collect-library/libs/BaiduLBS_Android.jar
new file mode 100644
index 00000000..07327d76
Binary files /dev/null and b/collect-library/libs/BaiduLBS_Android.jar differ
diff --git a/collect-library/libs/BaiduLBS_AndroidSDK_Lib.aar b/collect-library/libs/BaiduLBS_AndroidSDK_Lib.aar
deleted file mode 100644
index 18d4fe80..00000000
Binary files a/collect-library/libs/BaiduLBS_AndroidSDK_Lib.aar and /dev/null differ
diff --git a/collect-library/libs/armeabi-v7a/libAsr2Code.so b/collect-library/libs/armeabi-v7a/libAsr2Code.so
new file mode 100644
index 00000000..fa01878c
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libAsr2Code.so differ
diff --git a/collect-library/libs/armeabi-v7a/libBugly.so b/collect-library/libs/armeabi-v7a/libBugly.so
new file mode 100644
index 00000000..2dc98ed3
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libBugly.so differ
diff --git a/collect-library/libs/armeabi-v7a/libDecode.so b/collect-library/libs/armeabi-v7a/libDecode.so
new file mode 100644
index 00000000..8efb1d5f
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libDecode.so differ
diff --git a/collect-library/libs/armeabi-v7a/libNuanceVocalizer.so b/collect-library/libs/armeabi-v7a/libNuanceVocalizer.so
new file mode 100644
index 00000000..2791e318
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libNuanceVocalizer.so differ
diff --git a/collect-library/libs/armeabi-v7a/libSetWakeupJni.so b/collect-library/libs/armeabi-v7a/libSetWakeupJni.so
new file mode 100644
index 00000000..93811097
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libSetWakeupJni.so differ
diff --git a/collect-library/libs/armeabi-v7a/libejTTS.so b/collect-library/libs/armeabi-v7a/libejTTS.so
new file mode 100644
index 00000000..9575bccc
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libejTTS.so differ
diff --git a/collect-library/libs/armeabi-v7a/libgnustl_shared.so b/collect-library/libs/armeabi-v7a/libgnustl_shared.so
new file mode 100644
index 00000000..96c22a25
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libgnustl_shared.so differ
diff --git a/collect-library/libs/armeabi-v7a/libindoor.so b/collect-library/libs/armeabi-v7a/libindoor.so
new file mode 100644
index 00000000..e14d583d
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libindoor.so differ
diff --git a/collect-library/libs/armeabi-v7a/libiomx-gingerbread.so b/collect-library/libs/armeabi-v7a/libiomx-gingerbread.so
new file mode 100644
index 00000000..6665608d
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libiomx-gingerbread.so differ
diff --git a/collect-library/libs/armeabi-v7a/libiomx-hc.so b/collect-library/libs/armeabi-v7a/libiomx-hc.so
new file mode 100644
index 00000000..77f02566
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libiomx-hc.so differ
diff --git a/collect-library/libs/armeabi-v7a/libiomx-ics.so b/collect-library/libs/armeabi-v7a/libiomx-ics.so
new file mode 100644
index 00000000..8b534a94
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libiomx-ics.so differ
diff --git a/collect-library/libs/armeabi-v7a/liblocSDK8b.so b/collect-library/libs/armeabi-v7a/liblocSDK8b.so
new file mode 100644
index 00000000..c14b9199
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/liblocSDK8b.so differ
diff --git a/collect-library/libs/armeabi-v7a/libsimpleconfiglib.so b/collect-library/libs/armeabi-v7a/libsimpleconfiglib.so
new file mode 100644
index 00000000..ac2258c6
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libsimpleconfiglib.so differ
diff --git a/collect-library/libs/armeabi-v7a/libtiny_magic.so b/collect-library/libs/armeabi-v7a/libtiny_magic.so
new file mode 100644
index 00000000..d9e77292
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libtiny_magic.so differ
diff --git a/collect-library/libs/armeabi-v7a/libvlcjni.so b/collect-library/libs/armeabi-v7a/libvlcjni.so
new file mode 100644
index 00000000..37d9ae53
Binary files /dev/null and b/collect-library/libs/armeabi-v7a/libvlcjni.so differ
diff --git a/collect-library/libs/armeabi/libAsr2Code.so b/collect-library/libs/armeabi/libAsr2Code.so
new file mode 100644
index 00000000..fa01878c
Binary files /dev/null and b/collect-library/libs/armeabi/libAsr2Code.so differ
diff --git a/collect-library/libs/armeabi/libBugly.so b/collect-library/libs/armeabi/libBugly.so
new file mode 100644
index 00000000..2dc98ed3
Binary files /dev/null and b/collect-library/libs/armeabi/libBugly.so differ
diff --git a/collect-library/libs/armeabi/libDecode.so b/collect-library/libs/armeabi/libDecode.so
new file mode 100644
index 00000000..8efb1d5f
Binary files /dev/null and b/collect-library/libs/armeabi/libDecode.so differ
diff --git a/collect-library/libs/armeabi/libNuanceVocalizer.so b/collect-library/libs/armeabi/libNuanceVocalizer.so
new file mode 100644
index 00000000..2791e318
Binary files /dev/null and b/collect-library/libs/armeabi/libNuanceVocalizer.so differ
diff --git a/collect-library/libs/armeabi/libSetWakeupJni.so b/collect-library/libs/armeabi/libSetWakeupJni.so
new file mode 100644
index 00000000..93811097
Binary files /dev/null and b/collect-library/libs/armeabi/libSetWakeupJni.so differ
diff --git a/collect-library/libs/armeabi/libejTTS.so b/collect-library/libs/armeabi/libejTTS.so
new file mode 100644
index 00000000..9575bccc
Binary files /dev/null and b/collect-library/libs/armeabi/libejTTS.so differ
diff --git a/collect-library/libs/armeabi/libgnustl_shared.so b/collect-library/libs/armeabi/libgnustl_shared.so
new file mode 100644
index 00000000..5cf6d20f
Binary files /dev/null and b/collect-library/libs/armeabi/libgnustl_shared.so differ
diff --git a/collect-library/libs/armeabi/libiomx-gingerbread.so b/collect-library/libs/armeabi/libiomx-gingerbread.so
new file mode 100644
index 00000000..6665608d
Binary files /dev/null and b/collect-library/libs/armeabi/libiomx-gingerbread.so differ
diff --git a/collect-library/libs/armeabi/libiomx-hc.so b/collect-library/libs/armeabi/libiomx-hc.so
new file mode 100644
index 00000000..77f02566
Binary files /dev/null and b/collect-library/libs/armeabi/libiomx-hc.so differ
diff --git a/collect-library/libs/armeabi/libiomx-ics.so b/collect-library/libs/armeabi/libiomx-ics.so
new file mode 100644
index 00000000..8b534a94
Binary files /dev/null and b/collect-library/libs/armeabi/libiomx-ics.so differ
diff --git a/collect-library/libs/armeabi/libsimpleconfiglib.so b/collect-library/libs/armeabi/libsimpleconfiglib.so
new file mode 100644
index 00000000..71a782db
Binary files /dev/null and b/collect-library/libs/armeabi/libsimpleconfiglib.so differ
diff --git a/collect-library/libs/armeabi/libtiny_magic.so b/collect-library/libs/armeabi/libtiny_magic.so
new file mode 100644
index 00000000..d41e0a4c
Binary files /dev/null and b/collect-library/libs/armeabi/libtiny_magic.so differ
diff --git a/collect-library/libs/armeabi/libvlcjni.so b/collect-library/libs/armeabi/libvlcjni.so
new file mode 100644
index 00000000..37d9ae53
Binary files /dev/null and b/collect-library/libs/armeabi/libvlcjni.so differ
diff --git a/collect-library/src/main/AndroidManifest.xml b/collect-library/src/main/AndroidManifest.xml
index 5f8fe9fa..476a70ac 100644
--- a/collect-library/src/main/AndroidManifest.xml
+++ b/collect-library/src/main/AndroidManifest.xml
@@ -14,8 +14,7 @@
         android:value="IxQi4mZGTlfv6Z9M2GRdqn4KKRbOATUU" />
     <application
         android:allowBackup="true"
-        android:networkSecurityConfig="@xml/network_security_config"
-        >
+        android:networkSecurityConfig="@xml/network_security_config">
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/NavinfoPbfData.java b/collect-library/src/main/java/com/navinfo/collect/library/data/NavinfoPbfData.java
index 6461d04c..31766754 100644
--- a/collect-library/src/main/java/com/navinfo/collect/library/data/NavinfoPbfData.java
+++ b/collect-library/src/main/java/com/navinfo/collect/library/data/NavinfoPbfData.java
@@ -4,7 +4,6 @@ import com.google.protobuf.Descriptors;
 import com.google.protobuf.GeneratedMessageV3;
 import com.navinfo.collect.library.data.entity.GeometryFeatureEntity;
 import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Resultdata;
-
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.CoordinateXYM;
 import org.locationtech.jts.geom.CoordinateXYZM;
diff --git a/collect-library/src/main/java/com/navinfo/collect/library/garminvirbxe/CameraEventListener.java b/collect-library/src/main/java/com/navinfo/collect/library/garminvirbxe/CameraEventListener.java
index 585c4075..bf59c5eb 100644
--- a/collect-library/src/main/java/com/navinfo/collect/library/garminvirbxe/CameraEventListener.java
+++ b/collect-library/src/main/java/com/navinfo/collect/library/garminvirbxe/CameraEventListener.java
@@ -16,48 +16,43 @@ import com.navinfo.collect.library.sensor.ISensor.enmConnectionStatus;
 public interface CameraEventListener extends SensorEventListener{
     /**
      *拍照成功
-     * 
+     *
      * @return
      */
     public void OnSnapPictureResponse(HostBean hostBean, Bitmap bitmap, String picName, int tag);
 
     /** 错误 */
     public void requestError(HostBean hostBean, VolleyError e, CameraGarminVirbXE.enmCommandType commandType, int tag);
-    
+
     /**
      * 开始自动拍照回调
      */
     public void OnStartRecordResponse(HostBean hostBean, int tag);
-    
+
     /**
      * 停止自动拍照回调
      */
     public void OnStopRecordResponse(HostBean hostBean, int tag);
-    
+
     /**
      * 停止自动拍照回调
      */
     public void OnStatusResponse(HostBean hostBean, int tag);
-    
+
     /**
      * 局域网搜索相机完成回调
      * @param tag
      * @param scanIpList
      */
     public void OnSearchResponse(int tag,ArrayList<HostBean> scanIpList);
-    
+
     /**
      * 状态发生改变时候回调
      * @param connectStatus
      */
     public void OnConnectStatusChanged(HostBean hostBean, enmConnectionStatus connectStatus, int tag);
-    
-    /**
-     * 返回设备id
-     * @param devicesId
-     */
-    public void OnGetDeviceInfo(HostBean hostBean, String devicesId, int tag);
-    
+
+
     /**
      * 返回是否有gps信息
      * @param status
@@ -97,4 +92,11 @@ public interface CameraEventListener extends SensorEventListener{
      *
      */
     public void OnGetMediaList(HostBean hostBean, String json, int tag);
+
+    /**
+     * 返回设备id
+     * @param devicesId
+     */
+    public void OnGetDeviceInfo(HostBean hostBean,String devicesId,int tag);
 }
+
diff --git a/collect-library/src/main/java/com/navinfo/collect/library/sensor/SensorManager.java b/collect-library/src/main/java/com/navinfo/collect/library/sensor/SensorManager.java
new file mode 100644
index 00000000..d734fdc9
--- /dev/null
+++ b/collect-library/src/main/java/com/navinfo/collect/library/sensor/SensorManager.java
@@ -0,0 +1,60 @@
+package com.navinfo.collect.library.sensor;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import com.navinfo.collect.library.garminvirbxe.CameraGarminVirbXE;
+import com.navinfo.collect.library.garminvirbxe.SensorParams;
+import com.navinfo.collect.library.sensor.ISensor.enmSensorModel;
+import com.navinfo.collect.library.sensor.ISensor.enmSensorType;
+import org.json.JSONObject;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SensorManager {
+
+    private static volatile SensorManager mInstance;
+
+    private Context mContext;
+
+    private long diffTime = 0;
+
+    Handler mainHandler = new Handler(Looper.getMainLooper());
+
+    public static SensorManager getInstance() {
+        if (mInstance == null) {
+            synchronized (SensorManager.class) {
+                if (mInstance == null) {
+                    mInstance = new SensorManager();
+                }
+            }
+        }
+        return mInstance;
+    }
+
+    public void init(Context context) {
+        mContext = context;
+        diffTime = context.getSharedPreferences("nowTime", Context.MODE_PRIVATE).getLong("THE_DIFFERENCE_VALUE", 0);
+    }
+
+    public static ISensor CreateSensor(Context mContext, enmSensorType type, enmSensorModel model) {
+
+        ISensor pSensorInstance = null;
+
+        if (type == enmSensorType.SENSOR_CAMEAR) { // Garmin 相机
+            if (model == enmSensorModel.CAMERA_GARMIN_VIRB_XE) {
+                pSensorInstance = new CameraGarminVirbXE(mContext);
+            } else {
+                pSensorInstance = new Camera(mContext);
+            }
+        }
+
+        return pSensorInstance;
+    }
+
+    public void setDiffTime(long diffValue) {
+        this.diffTime = diffValue;
+    }
+
+}
diff --git a/collect-library/src/main/java/com/navinfo/collect/library/system/VLCApplication.java b/collect-library/src/main/java/com/navinfo/collect/library/system/VLCApplication.java
new file mode 100644
index 00000000..250ab896
--- /dev/null
+++ b/collect-library/src/main/java/com/navinfo/collect/library/system/VLCApplication.java
@@ -0,0 +1,100 @@
+/*****************************************************************************
+ * VLCApplication.java
+ *****************************************************************************
+ * Copyright © 2010-2013 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+package com.navinfo.collect.library.system;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import java.util.Locale;
+
+public class VLCApplication extends Application {
+    public final static String TAG = "VLC/VLCApplication";
+    private static VLCApplication instance;
+
+    public final static String SLEEP_INTENT = "org.videolan.vlc.SleepIntent";
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        // Are we using advanced debugging - locale?
+        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
+        String p = pref.getString("set_locale", "");
+        if (p != null && !p.equals("")) {
+            Locale locale;
+            // workaround due to region code
+            if(p.equals("zh-TW")) {
+                locale = Locale.TRADITIONAL_CHINESE;
+            } else if(p.startsWith("zh")) {
+                locale = Locale.CHINA;
+            } else if(p.equals("pt-BR")) {
+                locale = new Locale("pt", "BR");
+            } else if(p.equals("bn-IN") || p.startsWith("bn")) {
+                locale = new Locale("bn", "IN");
+            } else {
+                /**
+                 * Avoid a crash of
+                 * java.lang.AssertionError: couldn't initialize LocaleData for locale
+                 * if the user enters nonsensical region codes.
+                 */
+                if(p.contains("-"))
+                    p = p.substring(0, p.indexOf('-'));
+                locale = new Locale(p);
+            }
+            Locale.setDefault(locale);
+            Configuration config = new Configuration();
+            config.locale = locale;
+            getBaseContext().getResources().updateConfiguration(config,
+                    getBaseContext().getResources().getDisplayMetrics());
+        }
+
+        instance = this;
+    }
+
+    /**
+     * Called when the overall system is running low on memory
+     */
+    @Override
+    public void onLowMemory() {
+        super.onLowMemory();
+        Log.w(TAG, "System is running low on memory");
+    }
+
+    /**
+     * @return the main context of the Application
+     */
+    public static Context getAppContext()
+    {
+        return instance;
+    }
+
+    /**
+     * @return the main resources from the Application
+     */
+    public static Resources getAppResources()
+    {
+        if(instance == null) return null;
+        return instance.getResources();
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/libvlc/Aout.java b/collect-library/src/main/java/org/videolan/libvlc/Aout.java
new file mode 100644
index 00000000..971f6494
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/libvlc/Aout.java
@@ -0,0 +1,74 @@
+/*****************************************************************************
+ * Aout.java
+ *****************************************************************************
+ * Copyright © 2011-2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.libvlc;
+
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.util.Log;
+
+public class Aout {
+    /**
+     * Java side of the audio output module for Android.
+     * Uses an AudioTrack to play decoded audio buffers.
+     *
+     * TODO Use MODE_STATIC instead of MODE_STREAM with a MemoryFile (ashmem)
+     */
+
+    public Aout() {
+    }
+
+    private AudioTrack mAudioTrack;
+    private static final String TAG = "LibVLC/aout";
+
+    public void init(int sampleRateInHz, int channels, int samples) {
+        Log.d(TAG, sampleRateInHz + ", " + channels + ", " + samples + "=>" + channels * samples);
+        int minBufferSize = AudioTrack.getMinBufferSize(sampleRateInHz,
+                                                        AudioFormat.CHANNEL_OUT_STEREO,
+                                                        AudioFormat.ENCODING_PCM_16BIT);
+        mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
+                                     sampleRateInHz,
+                                     AudioFormat.CHANNEL_OUT_STEREO,
+                                     AudioFormat.ENCODING_PCM_16BIT,
+                                     Math.max(minBufferSize, channels * samples * 2),
+                                     AudioTrack.MODE_STREAM);
+    }
+
+    public void release() {
+        if (mAudioTrack != null) {
+            mAudioTrack.release();
+        }
+        mAudioTrack = null;
+    }
+
+    public void playBuffer(byte[] audioData, int bufferSize) {
+        if (mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED)
+            return;
+        if (mAudioTrack.write(audioData, 0, bufferSize) != bufferSize) {
+            Log.w(TAG, "Could not write all the samples to the audio device");
+        }
+        mAudioTrack.play();
+    }
+
+    public void pause() {
+        mAudioTrack.pause();
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/libvlc/EventHandler.java b/collect-library/src/main/java/org/videolan/libvlc/EventHandler.java
new file mode 100644
index 00000000..e012b4bc
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/libvlc/EventHandler.java
@@ -0,0 +1,123 @@
+/*****************************************************************************
+ * EventHandler.java
+ *****************************************************************************
+ * Copyright © 2011-2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.libvlc;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+
+import java.util.ArrayList;
+
+public class EventHandler {
+
+    /*
+     * Be sure to subscribe to events you need in the JNI too.
+     */
+
+    public static final int MediaMetaChanged                = 0;
+    //public static final int MediaSubItemAdded               = 1;
+    //public static final int MediaDurationChanged            = 2;
+    //public static final int MediaParsedChanged              = 3;
+    //public static final int MediaFreed                      = 4;
+    //public static final int MediaStateChanged               = 5;
+
+    //public static final int MediaPlayerMediaChanged         = 0x100;
+    //public static final int MediaPlayerNothingSpecial       = 0x101;
+    //public static final int MediaPlayerOpening              = 0x102;
+    //public static final int MediaPlayerBuffering            = 0x103;
+    public static final int MediaPlayerPlaying                = 0x104;
+    public static final int MediaPlayerPaused                 = 0x105;
+    public static final int MediaPlayerStopped                = 0x106;
+    //public static final int MediaPlayerForward              = 0x107;
+    //public static final int MediaPlayerBackward             = 0x108;
+    public static final int MediaPlayerEndReached             = 0x109;
+    public static final int MediaPlayerEncounteredError       = 0x10a;
+    //public static final int MediaPlayerTimeChanged          = 0x10b;
+    public static final int MediaPlayerPositionChanged        = 0x10c;
+    //public static final int MediaPlayerSeekableChanged      = 0x10d;
+    //public static final int MediaPlayerPausableChanged      = 0x10e;
+    //public static final int MediaPlayerTitleChanged         = 0x10f;
+    //public static final int MediaPlayerSnapshotTaken        = 0x110;
+    //public static final int MediaPlayerLengthChanged        = 0x111;
+    public static final int MediaPlayerVout                   = 0x112;
+
+    public static final int MediaListItemAdded                = 0x200;
+    //public static final int MediaListWillAddItem            = 0x201;
+    public static final int MediaListItemDeleted              = 0x202;
+    //public static final int MediaListWillDeleteItem         = 0x203;
+
+    //public static final int MediaListViewItemAdded          = 0x300;
+    //public static final int MediaListViewWillAddItem        = 0x301;
+    //public static final int MediaListViewItemDeleted        = 0x302;
+    //public static final int MediaListViewWillDeleteItem     = 0x303;
+
+    //public static final int MediaListPlayerPlayed           = 0x400;
+    //public static final int MediaListPlayerNextItemSet      = 0x401;
+    //public static final int MediaListPlayerStopped          = 0x402;
+
+    //public static final int MediaDiscovererStarted          = 0x500;
+    //public static final int MediaDiscovererEnded            = 0x501;
+
+    //public static final int VlmMediaAdded                   = 0x600;
+    //public static final int VlmMediaRemoved                 = 0x601;
+    //public static final int VlmMediaChanged                 = 0x602;
+    //public static final int VlmMediaInstanceStarted         = 0x603;
+    //public static final int VlmMediaInstanceStopped         = 0x604;
+    //public static final int VlmMediaInstanceStatusInit      = 0x605;
+    //public static final int VlmMediaInstanceStatusOpening   = 0x606;
+    //public static final int VlmMediaInstanceStatusPlaying   = 0x607;
+    //public static final int VlmMediaInstanceStatusPause     = 0x608;
+    //public static final int VlmMediaInstanceStatusEnd       = 0x609;
+    //public static final int VlmMediaInstanceStatusError     = 0x60a;
+
+    private ArrayList<Handler> mEventHandler;
+    private static EventHandler mInstance;
+
+    EventHandler() {
+        mEventHandler = new ArrayList<Handler>();
+    }
+
+    public static EventHandler getInstance() {
+        if (mInstance == null) {
+            mInstance = new EventHandler();
+        }
+        return mInstance;
+    }
+
+    public void addHandler(Handler handler) {
+        if (!mEventHandler.contains(handler))
+            mEventHandler.add(handler);
+    }
+
+    public void removeHandler(Handler handler) {
+        mEventHandler.remove(handler);
+    }
+
+    /** This method is called by a native thread **/
+    public void callback(int event, Bundle b) {
+        b.putInt("event", event);
+        for (int i = 0; i < mEventHandler.size(); i++) {
+            Message msg = Message.obtain();
+            msg.setData(b);
+            mEventHandler.get(i).sendMessage(msg);
+        }
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/libvlc/IVideoPlayer.java b/collect-library/src/main/java/org/videolan/libvlc/IVideoPlayer.java
new file mode 100644
index 00000000..c714b5b3
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/libvlc/IVideoPlayer.java
@@ -0,0 +1,34 @@
+/*****************************************************************************
+ * IVideoPlayer.java
+ *****************************************************************************
+ * Copyright © 2010-2013 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.libvlc;
+
+public interface IVideoPlayer {
+    /**
+     * This method is called by native vout to request a surface resize when frame size doesn't match surface size.
+     * @param width Frame width
+     * @param height Frame height
+     * @param visible_width Visible frame width
+     * @param visible_height Visible frame height
+     * @param sar_num Surface aspect ratio numerator
+     * @param sar_den Surface aspect ratio denominator
+     */
+    void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
+}
diff --git a/collect-library/src/main/java/org/videolan/libvlc/LibVLC.java b/collect-library/src/main/java/org/videolan/libvlc/LibVLC.java
new file mode 100644
index 00000000..fb941165
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/libvlc/LibVLC.java
@@ -0,0 +1,653 @@
+/*****************************************************************************
+ * LibVLC.java
+ *****************************************************************************
+ * Copyright © 2010-2013 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.libvlc;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+public class LibVLC {
+    private static final String TAG = "VLC/LibVLC";
+    public static final int AOUT_AUDIOTRACK_JAVA = 0;
+    public static final int AOUT_AUDIOTRACK = 1;
+    public static final int AOUT_OPENSLES = 2;
+
+    private static LibVLC sInstance;
+
+    /** libVLC instance C pointer */
+    private long mLibVlcInstance = 0; // Read-only, reserved for JNI
+    /** libvlc_media_player pointer and index */
+    private int mInternalMediaPlayerIndex = 0; // Read-only, reserved for JNI
+    private long mInternalMediaPlayerInstance = 0; // Read-only, reserved for JNI
+
+    private MediaList mMediaList; // Pointer to media list being followed
+    private MediaList mPrimaryList; // Primary/default media list; see getPrimaryMediaList()
+
+    /** Buffer for VLC messages */
+    private StringBuffer mDebugLogBuffer;
+    private boolean mIsBufferingLog = false;
+
+    private Aout mAout;
+
+    /** Keep screen bright */
+    //private WakeLock mWakeLock;
+
+    /** Settings */
+    private boolean iomx = false;
+    private String subtitlesEncoding = "";
+    private int aout = LibVlcUtil.isGingerbreadOrLater() ? AOUT_OPENSLES : AOUT_AUDIOTRACK_JAVA;
+    private boolean timeStretching = false;
+    private int deblocking = -1;
+    private String chroma = "";
+    private boolean verboseMode = true;
+    private float[] equalizer = null;
+    private boolean frameSkip = false;
+    private int networkCaching = 0;
+
+    /** Check in libVLC already initialized otherwise crash */
+    private boolean mIsInitialized = false;
+    public native void attachSurface(Surface surface, IVideoPlayer player, int width, int height);
+
+    public native void detachSurface();
+
+    /* Load library before object instantiation */
+    static {
+        try {
+            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
+                System.loadLibrary("iomx-gingerbread");
+            else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2)
+                System.loadLibrary("iomx-hc");
+            else
+                System.loadLibrary("iomx-ics");
+        } catch (Throwable t) {
+            Log.w(TAG, "Unable to load the iomx library: " + t);
+        }
+        try {
+            System.loadLibrary("vlcjni");
+        } catch (UnsatisfiedLinkError ule) {
+            Log.e(TAG, "Can't load vlcjni library: " + ule);
+            /// FIXME Alert user
+            System.exit(1);
+        } catch (SecurityException se) {
+            Log.e(TAG, "Encountered a security issue when loading vlcjni library: " + se);
+            /// FIXME Alert user
+            System.exit(1);
+        }
+    }
+
+    /**
+     * Singleton constructor of libVLC Without surface and vout to create the
+     * thumbnail and get information e.g. on the MediaLibraryActivity
+     *
+     * @return libVLC instance
+     * @throws LibVlcException
+     */
+    public static LibVLC getInstance() throws LibVlcException {
+        synchronized (LibVLC.class) {
+            if (sInstance == null) {
+                /* First call */
+                sInstance = new LibVLC();
+            }
+        }
+
+        return sInstance;
+    }
+
+    /**
+     * Return an existing instance of libVLC Call it when it is NOT important
+     * that this fails
+     *
+     * @return libVLC instance OR null
+     */
+    public static LibVLC getExistingInstance() {
+        synchronized (LibVLC.class) {
+            return sInstance;
+        }
+    }
+
+    /**
+     * Constructor
+     * It is private because this class is a singleton.
+     */
+    private LibVLC() {
+        mAout = new Aout();
+    }
+
+    /**
+     * Destructor:
+     * It is bad practice to rely on them, so please don't forget to call
+     * destroy() before exiting.
+     */
+    @Override
+    public void finalize() {
+        if (mLibVlcInstance != 0) {
+            Log.d(TAG, "LibVLC is was destroyed yet before finalize()");
+            destroy();
+        }
+    }
+
+    /**
+     * Get the media list that LibVLC is following right now.
+     *
+     * @return The media list object being followed
+     */
+    public MediaList getMediaList() {
+        return mMediaList;
+    }
+
+    /**
+     * Set the media list for LibVLC to follow.
+     *
+     * @param mediaList The media list object to follow
+     */
+    public void setMediaList(MediaList mediaList) {
+        mMediaList = mediaList;
+    }
+
+    /**
+     * Sets LibVLC to follow the default media list (see below)
+     */
+    public void setMediaList() {
+        mMediaList = mPrimaryList;
+    }
+
+    /**
+     * Gets the primary media list, or the "currently playing" list.
+     * Not to be confused with the media list pointer from above, which
+     * refers the the MediaList object that libVLC is currently following.
+     * This list is just one out of many lists that it can be pointed towards.
+     *
+     * This list will be used for lists of songs that are not user-defined.
+     * For example: selecting a song from the Songs list, or from the list
+     * displayed after selecting an album.
+     *
+     * It is loaded as the default list.
+     *
+     * @return The primary media list
+     */
+    public MediaList getPrimaryMediaList() {
+        return mPrimaryList;
+    }
+
+    /**
+     * Give to LibVLC the surface to draw the video.
+     * @param f the surface to draw
+     */
+    public native void setSurface(Surface f);
+
+    public static synchronized void restart(Context context) {
+        if (sInstance != null) {
+            try {
+                sInstance.destroy();
+                sInstance.init(context);
+            } catch (LibVlcException lve) {
+                Log.e(TAG, "Unable to reinit libvlc: " + lve);
+            }
+        }
+    }
+
+    /**
+     * those get/is* are called from native code to get settings values.
+     */
+
+    public boolean useIOMX() {
+        return iomx;
+    }
+
+    public void setIomx(boolean iomx) {
+        this.iomx = iomx;
+    }
+
+    public String getSubtitlesEncoding() {
+        return subtitlesEncoding;
+    }
+
+    public void setSubtitlesEncoding(String subtitlesEncoding) {
+        this.subtitlesEncoding = subtitlesEncoding;
+    }
+
+    public int getAout() {
+        return aout;
+    }
+
+    public void setAout(int aout) {
+        if (aout < 0)
+            this.aout = LibVlcUtil.isGingerbreadOrLater() ? AOUT_OPENSLES : AOUT_AUDIOTRACK_JAVA;
+        else
+            this.aout = aout;
+    }
+
+    public boolean timeStretchingEnabled() {
+        return timeStretching;
+    }
+
+    public void setTimeStretching(boolean timeStretching) {
+        this.timeStretching = timeStretching;
+    }
+
+    public int getDeblocking() {
+        int ret = deblocking;
+        if(deblocking < 0) {
+            /**
+             * Set some reasonable deblocking defaults:
+             *
+             * Skip all (4) for armv6 and MIPS by default
+             * Skip non-ref (1) for all armv7 more than 1.2 Ghz and more than 2 cores
+             * Skip non-key (3) for all devices that don't meet anything above
+             */
+            LibVlcUtil.MachineSpecs m = LibVlcUtil.getMachineSpecs();
+            if( (m.hasArmV6 && !(m.hasArmV7)) || m.hasMips )
+                ret = 4;
+            else if(m.bogoMIPS > 1200 && m.processors > 2)
+                ret = 1;
+            else
+                ret = 3;
+        } else if(deblocking > 4) { // sanity check
+            ret = 3;
+        }
+        return ret;
+    }
+
+    public void setDeblocking(int deblocking) {
+        this.deblocking = deblocking;
+    }
+
+    public String getChroma() {
+        return chroma;
+    }
+
+    public void setChroma(String chroma) {
+        this.chroma = chroma.equals("YV12") && !LibVlcUtil.isGingerbreadOrLater() ? "" : chroma;
+    }
+
+    public boolean isVerboseMode() {
+        return verboseMode;
+    }
+
+    public void setVerboseMode(boolean verboseMode) {
+        this.verboseMode = verboseMode;
+    }
+
+    public float[] getEqualizer()
+    {
+        return equalizer;
+    }
+
+    public void setEqualizer(float[] equalizer)
+    {
+        this.equalizer = equalizer;
+        applyEqualizer();
+    }
+
+    private void applyEqualizer()
+    {
+        setNativeEqualizer(mInternalMediaPlayerInstance, this.equalizer);
+    }
+    private native int setNativeEqualizer(long mediaPlayer, float[] bands);
+
+    public boolean frameSkipEnabled() {
+        return frameSkip;
+    }
+
+    public void setFrameSkip(boolean frameskip) {
+        this.frameSkip = frameskip;
+    }
+
+    public int getNetworkCaching() {
+        return this.networkCaching;
+    }
+
+    public void setNetworkCaching(int networkcaching) {
+        this.networkCaching = networkcaching;
+    }
+
+    /**
+     * Initialize the libVLC class
+     */
+    public void init(Context context) throws LibVlcException {
+        Log.v(TAG, "Initializing LibVLC");
+        mDebugLogBuffer = new StringBuffer();
+        if (!mIsInitialized) {
+            if(!LibVlcUtil.hasCompatibleCPU(context)) {
+                Log.e(TAG, LibVlcUtil.getErrorMsg());
+                throw new LibVlcException();
+            }
+            nativeInit();
+            mMediaList = mPrimaryList = new MediaList(this);
+            setEventHandler(EventHandler.getInstance());
+            mIsInitialized = true;
+        }
+    }
+
+    /**
+     * Destroy this libVLC instance
+     * @note You must call it before exiting
+     */
+    public void destroy() {
+        Log.v(TAG, "Destroying LibVLC instance");
+        nativeDestroy();
+        detachEventHandler();
+        mIsInitialized = false;
+    }
+
+    /**
+     * Open the Java audio output.
+     * This function is called by the native code
+     */
+    public void initAout(int sampleRateInHz, int channels, int samples) {
+        Log.d(TAG, "Opening the java audio output");
+        mAout.init(sampleRateInHz, channels, samples);
+    }
+
+    /**
+     * Play an audio buffer taken from the native code
+     * This function is called by the native code
+     */
+    public void playAudio(byte[] audioData, int bufferSize) {
+        mAout.playBuffer(audioData, bufferSize);
+    }
+
+    /**
+     * Pause the Java audio output
+     * This function is called by the native code
+     */
+    public void pauseAout() {
+        Log.d(TAG, "Pausing the java audio output");
+        mAout.pause();
+    }
+
+    /**
+     * Close the Java audio output
+     * This function is called by the native code
+     */
+    public void closeAout() {
+        Log.d(TAG, "Closing the java audio output");
+        mAout.release();
+    }
+
+    public int readMedia(String mrl) {
+        return readMedia(mLibVlcInstance, mrl, false);
+    }
+
+    /**
+     * Read a media.
+     */
+    public int readMedia(String mrl, boolean novideo) {
+        Log.v(TAG, "Reading " + mrl);
+        return readMedia(mLibVlcInstance, mrl, novideo);
+    }
+
+    /**
+     * Play a media from the media list (playlist)
+     *
+     * @param position The index of the media
+     */
+    public void playIndex(int position) {
+        playIndex(mLibVlcInstance, position);
+    }
+
+    public TrackInfo[] readTracksInfo(String mrl) {
+        return readTracksInfo(mLibVlcInstance, mrl);
+    }
+
+    /**
+     * Get a media thumbnail.
+     */
+    public byte[] getThumbnail(String mrl, int i_width, int i_height) {
+        return getThumbnail(mLibVlcInstance, mrl, i_width, i_height);
+    }
+
+    /**
+     * Return true if there is a video track in the file
+     */
+    public boolean hasVideoTrack(String mrl) throws java.io.IOException {
+        return hasVideoTrack(mLibVlcInstance, mrl);
+    }
+
+    /**
+     * Sets the speed of playback (1 being normal speed, 2 being twice as fast)
+     *
+     * @param rate
+     */
+    public native void setRate(float rate);
+
+    /**
+     * Get the current playback speed
+     */
+    public native float getRate();
+
+    /**
+     * Initialize the libvlc C library
+     * @return a pointer to the libvlc instance
+     */
+    private native void nativeInit() throws LibVlcException;
+
+    /**
+     * Close the libvlc C library
+     * @note mLibVlcInstance should be 0 after a call to destroy()
+     */
+    private native void nativeDestroy();
+
+    /**
+     * Start buffering to the mDebugLogBuffer.
+     */
+    public native void startDebugBuffer();
+    public native void stopDebugBuffer();
+    public String getBufferContent() {
+        return mDebugLogBuffer.toString();
+    }
+
+    public void clearBuffer() {
+        mDebugLogBuffer.setLength(0);
+    }
+
+    public boolean isDebugBuffering() {
+        return mIsBufferingLog;
+    }
+
+    /**
+     * Read a media
+     * @param instance: the instance of libVLC
+     * @param mrl: the media mrl
+     * @param novideo: don't enable video decoding for this media
+     * @return the position in the playlist
+     */
+    private native int readMedia(long instance, String mrl, boolean novideo);
+
+    /**
+     * Play an index in the native media list (playlist)
+     */
+    private native void playIndex(long instance, int position);
+
+    /**
+     * Returns true if any media is playing
+     */
+    public native boolean isPlaying();
+
+    /**
+     * Returns true if any media is seekable
+     */
+    public native boolean isSeekable();
+
+    /**
+     * Plays any loaded media
+     */
+    public native void play();
+
+    /**
+     * Pauses any playing media
+     */
+    public native void pause();
+
+    /**
+     * Stops any playing media
+     */
+    public native void stop();
+
+    /**
+     * Play the previous media (if any) in the media list
+     */
+    public native void previous();
+
+    /**
+     * Play the next media (if any) in the media list
+     */
+    public native void next();
+
+    /**
+     * Gets volume as integer
+     */
+    public native int getVolume();
+
+    /**
+     * Sets volume as integer
+     * @param volume: Volume level passed as integer
+     */
+    public native int setVolume(int volume);
+
+    /**
+     * Gets the current movie time (in ms).
+     * @return the movie time (in ms), or -1 if there is no media.
+     */
+    public native long getTime();
+
+    /**
+     * Sets the movie time (in ms), if any media is being played.
+     * @param time: Time in ms.
+     * @return the movie time (in ms), or -1 if there is no media.
+     */
+    public native long setTime(long time);
+
+    /**
+     * Gets the movie position.
+     * @return the movie position, or -1 for any error.
+     */
+    public native float getPosition();
+
+    /**
+     * Sets the movie position.
+     * @param pos: movie position.
+     */
+    public native void setPosition(float pos);
+
+    /**
+     * Gets current movie's length in ms.
+     * @return the movie length (in ms), or -1 if there is no media.
+     */
+    public native long getLength();
+
+    /**
+     * Get the libVLC version
+     * @return the libVLC version string
+     */
+    public native String version();
+
+    /**
+     * Get the libVLC compiler
+     * @return the libVLC compiler string
+     */
+    public native String compiler();
+
+    /**
+     * Get the libVLC changeset
+     * @return the libVLC changeset string
+     */
+    public native String changeset();
+
+    /**
+     * Get a media thumbnail.
+     * @return a bytearray with the RGBA thumbnail data inside.
+     */
+    private native byte[] getThumbnail(long instance, String mrl, int i_width, int i_height);
+
+    /**
+     * Return true if there is a video track in the file
+     */
+    private native boolean hasVideoTrack(long instance, String mrl);
+
+    private native TrackInfo[] readTracksInfo(long instance, String mrl);
+
+    public native TrackInfo[] readTracksInfoPosition(MediaList mediaList, int position);
+
+    public native int getAudioTracksCount();
+
+    public native Map<Integer,String> getAudioTrackDescription();
+
+    public native int getAudioTrack();
+
+    public native int setAudioTrack(int index);
+
+    public native int getVideoTracksCount();
+
+    public native int addSubtitleTrack(String path);
+
+    public native Map<Integer,String> getSpuTrackDescription();
+
+    public native int getSpuTrack();
+
+    public native int setSpuTrack(int index);
+
+    public native int getSpuTracksCount();
+
+    public static native String nativeToURI(String path);
+
+    public static String PathToURI(String path) {
+        if(path == null) {
+            throw new NullPointerException("Cannot convert null path!");
+        }
+        return LibVLC.nativeToURI(path);
+    }
+
+    public static native void nativeReadDirectory(String path, ArrayList<String> res);
+
+    public native static boolean nativeIsPathDirectory(String path);
+
+    /**
+     * Get the list of existing items in the media list (playlist)
+     */
+    public native void getMediaListItems(ArrayList<String> arl);
+
+     /**
+      * Expand and continue playing the current media.
+      *
+      * @return the index of the media was expanded, and -1 if no media was expanded
+      */
+    public int expandAndPlay() {
+        int r = mMediaList.expandMedia(mInternalMediaPlayerIndex);
+        if(r == 0)
+            this.playIndex(mInternalMediaPlayerIndex);
+        return r;
+    }
+
+    private native void setEventHandler(EventHandler eventHandler);
+
+    private native void detachEventHandler();
+
+    public native float[] getBands();
+
+    public native String[] getPresets();
+
+    public native float[] getPreset(int index);
+}
diff --git a/collect-library/src/main/java/org/videolan/libvlc/LibVlcException.java b/collect-library/src/main/java/org/videolan/libvlc/LibVlcException.java
new file mode 100644
index 00000000..f676f13a
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/libvlc/LibVlcException.java
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * LibVlcException.java
+ *****************************************************************************
+ * Copyright © 2011-2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/**
+ * LibVlcException: exceptions thrown by the native LibVLC interface
+ */
+package org.videolan.libvlc;
+
+/**
+ * @author jpeg
+ *
+ */
+public class LibVlcException extends Exception {
+    private static final long serialVersionUID = -1909522348226924189L;
+
+    /**
+     * Create an empty error
+     */
+    public LibVlcException() {
+        super();
+    }
+
+    /**
+     * @param detailMessage
+     */
+    public LibVlcException(String detailMessage) {
+        super(detailMessage);
+    }
+
+    /**
+     * @param throwable
+     */
+    public LibVlcException(Throwable throwable) {
+        super(throwable);
+    }
+
+    /**
+     * @param detailMessage
+     * @param throwable
+     */
+    public LibVlcException(String detailMessage, Throwable throwable) {
+        super(detailMessage, throwable);
+    }
+
+}
diff --git a/collect-library/src/main/java/org/videolan/libvlc/LibVlcUtil.java b/collect-library/src/main/java/org/videolan/libvlc/LibVlcUtil.java
new file mode 100644
index 00000000..87727c83
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/libvlc/LibVlcUtil.java
@@ -0,0 +1,421 @@
+/*****************************************************************************
+ * LibVlcUtil.java
+ *****************************************************************************
+ * Copyright © 2011-2013 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.libvlc;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Locale;
+
+public class LibVlcUtil {
+    public final static String TAG = "VLC/LibVLC/Util";
+
+    public static boolean isFroyoOrLater()
+    {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
+    }
+
+    public static boolean isGingerbreadOrLater()
+    {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
+    }
+
+    public static boolean isHoneycombOrLater()
+    {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
+    }
+
+    public static boolean isICSOrLater()
+    {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+    }
+
+    public static boolean isJellyBeanOrLater()
+    {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
+    }
+
+    private static String errorMsg = null;
+    private static boolean isCompatible = false;
+    public static String getErrorMsg() {
+        return errorMsg;
+    }
+
+    public static boolean hasCompatibleCPU(Context context)
+    {
+        // If already checked return cached result
+        if(errorMsg != null || isCompatible) return isCompatible;
+
+        ElfData elf = readLib(context.getApplicationInfo().dataDir + "/lib/libvlcjni.so");
+        if(elf == null) {
+            Log.e(TAG, "WARNING: Unable to read libvlcjni.so; cannot check device ABI!");
+            Log.e(TAG, "WARNING: Cannot guarantee correct ABI for this build (may crash)!");
+            return true;
+        }
+
+        String CPU_ABI = Build.CPU_ABI;
+        String CPU_ABI2 = "none";
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { // CPU_ABI2 since 2.2
+            try {
+                CPU_ABI2 = (String) Build.class.getDeclaredField("CPU_ABI2").get(null);
+            } catch (Exception e) { }
+        }
+
+        Log.i(TAG, "machine = " + (elf.e_machine == EM_ARM ? "arm" : elf.e_machine == EM_386 ? "x86" : "mips"));
+        Log.i(TAG, "arch = " + elf.att_arch);
+        Log.i(TAG, "fpu = " + elf.att_fpu);
+        boolean hasNeon = false, hasFpu = false, hasArmV6 = false,
+                hasArmV7 = false, hasMips = false, hasX86 = false;
+        float bogoMIPS = -1;
+        int processors = 0;
+
+        if(CPU_ABI.equals("x86")) {
+            hasX86 = true;
+        } else if(CPU_ABI.equals("armeabi-v7a") ||
+                  CPU_ABI2.equals("armeabi-v7a")) {
+            hasArmV7 = true;
+            hasArmV6 = true; /* Armv7 is backwards compatible to < v6 */
+        } else if(CPU_ABI.equals("armeabi") ||
+                  CPU_ABI2.equals("armeabi")) {
+            hasArmV6 = true;
+        }
+
+        try {
+            FileReader fileReader = new FileReader("/proc/cpuinfo");
+            BufferedReader br = new BufferedReader(fileReader);
+            String line;
+            while((line = br.readLine()) != null) {
+                if(!hasArmV7 && line.contains("ARMv7")) {
+                    hasArmV7 = true;
+                    hasArmV6 = true; /* Armv7 is backwards compatible to < v6 */
+                }
+                if(!hasArmV7 && !hasArmV6 && line.contains("ARMv6"))
+                    hasArmV6 = true;
+                // "clflush size" is a x86-specific cpuinfo tag.
+                // (see kernel sources arch/x86/kernel/cpu/proc.c)
+                if(line.contains("clflush size"))
+                    hasX86 = true;
+                // "microsecond timers" is specific to MIPS.
+                // see arch/mips/kernel/proc.c
+                if(line.contains("microsecond timers"))
+                    hasMips = true;
+                if(!hasNeon && line.contains("neon"))
+                    hasNeon = true;
+                if(!hasFpu && line.contains("vfp"))
+                    hasFpu = true;
+                if(line.startsWith("processor"))
+                    processors++;
+                if(bogoMIPS < 0 && line.toLowerCase(Locale.ENGLISH).contains("bogomips")) {
+                    String[] bogo_parts = line.split(":");
+                    try {
+                        bogoMIPS = Float.parseFloat(bogo_parts[1].trim());
+                    } catch(NumberFormatException e) {
+                        bogoMIPS = -1; // invalid bogomips
+                    }
+                }
+            }
+            fileReader.close();
+        } catch(IOException ex){
+            ex.printStackTrace();
+            errorMsg = "IOException whilst reading cpuinfo flags";
+            isCompatible = false;
+            return false;
+        }
+        if(processors == 0)
+            processors = 1; // possibly borked cpuinfo?
+
+        // Enforce proper architecture to prevent problems
+        if(elf.e_machine == EM_386 && !hasX86) {
+            errorMsg = "x86 build on non-x86 device";
+            isCompatible = false;
+            return false;
+        } else if(elf.e_machine == EM_ARM && hasX86) {
+            errorMsg = "ARM build on x86 device";
+            isCompatible = false;
+            return false;
+        }
+
+        if(elf.e_machine == EM_MIPS && !hasMips) {
+            errorMsg = "MIPS build on non-MIPS device";
+            isCompatible = false;
+            return false;
+        } else if(elf.e_machine == EM_ARM && hasMips) {
+            errorMsg = "ARM build on MIPS device";
+            isCompatible = false;
+            return false;
+        }
+
+        if(elf.e_machine == EM_ARM && elf.att_arch.startsWith("v7") && !hasArmV7) {
+            errorMsg = "ARMv7 build on non-ARMv7 device";
+            isCompatible = false;
+            return false;
+        }
+        if(elf.e_machine == EM_ARM) {
+            if(elf.att_arch.startsWith("v6") && !hasArmV6) {
+                errorMsg = "ARMv6 build on non-ARMv6 device";
+                isCompatible = false;
+                return false;
+            } else if(elf.att_fpu && !hasFpu) {
+                errorMsg = "FPU-enabled build on non-FPU device";
+                isCompatible = false;
+                return false;
+            }
+        }
+
+        errorMsg = null;
+        isCompatible = true;
+        // Store into MachineSpecs
+        machineSpecs = new MachineSpecs();
+        machineSpecs.hasArmV6 = hasArmV6;
+        machineSpecs.hasArmV7 = hasArmV7;
+        machineSpecs.hasFpu = hasFpu;
+        machineSpecs.hasMips = hasMips;
+        machineSpecs.hasNeon = hasNeon;
+        machineSpecs.hasX86 = hasX86;
+        machineSpecs.bogoMIPS = bogoMIPS;
+        machineSpecs.processors = processors;
+        return true;
+    }
+
+    public static MachineSpecs getMachineSpecs() {
+        return machineSpecs;
+    }
+    private static MachineSpecs machineSpecs = null;
+    public static class MachineSpecs {
+        public boolean hasNeon;
+        public boolean hasFpu;
+        public boolean hasArmV6;
+        public boolean hasArmV7;
+        public boolean hasMips;
+        public boolean hasX86;
+        public float bogoMIPS;
+        public int processors;
+    }
+
+    private static final int EM_386 = 3;
+    private static final int EM_MIPS = 8;
+    private static final int EM_ARM = 40;
+    private static final int ELF_HEADER_SIZE = 52;
+    private static final int SECTION_HEADER_SIZE = 40;
+    private static final int SHT_ARM_ATTRIBUTES = 0x70000003;
+    private static class ElfData {
+        ByteOrder order;
+        int e_machine;
+        int e_shoff;
+        int e_shnum;
+        int sh_offset;
+        int sh_size;
+        String att_arch;
+        boolean att_fpu;
+    }
+
+    /** '*' prefix means it's unsupported */
+    private static String[] CPU_archs = {"*Pre-v4", "*v4", "*v4T",
+                                         "v5T", "v5TE", "v5TEJ",
+                                         "v6", "v6KZ", "v6T2", "v6K", "v7",
+                                         "*v6-M", "*v6S-M", "*v7E-M", "*v8"};
+
+    private static ElfData readLib(String path) {
+        File file = new File(path);
+        if (!file.exists() || !file.canRead())
+            return null;
+
+        RandomAccessFile in = null;
+        try {
+            in = new RandomAccessFile(file, "r");
+
+            ElfData elf = new ElfData();
+            if (!readHeader(in, elf))
+                return null;
+
+            switch (elf.e_machine) {
+                case EM_386:
+                case EM_MIPS:
+                    return elf;
+                case EM_ARM:
+                    in.close();
+                    in = new RandomAccessFile(file, "r");
+                    if (!readSection(in, elf))
+                        return null;
+                    in.close();
+                    in = new RandomAccessFile(file, "r");
+                    if (!readArmAttributes(in, elf))
+                        return null;
+                    break;
+                default:
+                    return null;
+            }
+            return elf;
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (in != null)
+                    in.close();
+            } catch (IOException e) {
+            }
+        }
+        return null;
+    }
+
+    private static boolean readHeader(RandomAccessFile in, ElfData elf) throws IOException {
+        // http://www.sco.com/developers/gabi/1998-04-29/ch4.eheader.html
+        byte[] bytes = new byte[ELF_HEADER_SIZE];
+        in.readFully(bytes);
+        if (bytes[0] != 127 ||
+                bytes[1] != 'E' ||
+                bytes[2] != 'L' ||
+                bytes[3] != 'F' ||
+                bytes[4] != 1) { // ELFCLASS32, Only 32bit header is supported
+            return false;
+        }
+
+        elf.order = bytes[5] == 1
+                ? ByteOrder.LITTLE_ENDIAN // ELFDATA2LSB
+                : ByteOrder.BIG_ENDIAN;   // ELFDATA2MSB
+
+        // wrap bytes in a ByteBuffer to force endianess
+        ByteBuffer buffer = ByteBuffer.wrap(bytes);
+        buffer.order(elf.order);
+
+        elf.e_machine = buffer.getShort(18);    /* Architecture */
+        elf.e_shoff = buffer.getInt(32);        /* Section header table file offset */
+        elf.e_shnum = buffer.getShort(48);      /* Section header table entry count */
+        return true;
+    }
+
+    private static boolean readSection(RandomAccessFile in, ElfData elf) throws IOException {
+        byte[] bytes = new byte[SECTION_HEADER_SIZE];
+        in.seek(elf.e_shoff);
+
+        for (int i = 0; i < elf.e_shnum; ++i) {
+            in.readFully(bytes);
+
+            // wrap bytes in a ByteBuffer to force endianess
+            ByteBuffer buffer = ByteBuffer.wrap(bytes);
+            buffer.order(elf.order);
+
+            int sh_type = buffer.getInt(4); /* Section type */
+            if (sh_type != SHT_ARM_ATTRIBUTES)
+                continue;
+
+            elf.sh_offset = buffer.getInt(16);  /* Section file offset */
+            elf.sh_size = buffer.getInt(20);    /* Section size in bytes */
+            return true;
+        }
+
+        return false;
+    }
+
+    private static boolean readArmAttributes(RandomAccessFile in, ElfData elf) throws IOException {
+        byte[] bytes = new byte[elf.sh_size];
+        in.seek(elf.sh_offset);
+        in.readFully(bytes);
+
+        // wrap bytes in a ByteBuffer to force endianess
+        ByteBuffer buffer = ByteBuffer.wrap(bytes);
+        buffer.order(elf.order);
+
+        //http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf
+        //http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf
+        if (buffer.get() != 'A') // format-version
+            return false;
+
+        // sub-sections loop
+        while (buffer.remaining() > 0) {
+            int start_section = buffer.position();
+            int length = buffer.getInt();
+            String vendor = getString(buffer);
+            if (vendor.equals("aeabi")) {
+                // tags loop
+                while (buffer.position() < start_section + length) {
+                    int start = buffer.position();
+                    int tag = buffer.get();
+                    int size = buffer.getInt();
+                    // skip if not Tag_File, we don't care about others
+                    if (tag != 1) {
+                        buffer.position(start + size);
+                        continue;
+                    }
+
+                    // attributes loop
+                    while (buffer.position() < start + size) {
+                        tag = getUleb128(buffer);
+                        if (tag == 6) { // CPU_arch
+                            int arch = getUleb128(buffer);
+                            elf.att_arch = CPU_archs[arch];
+                        }
+                        else if (tag == 27) { // ABI_HardFP_use
+                            getUleb128(buffer);
+                            elf.att_fpu = true;
+                        }
+                        else {
+                            // string for 4=CPU_raw_name / 5=CPU_name / 32=compatibility
+                            // string for >32 && odd tags
+                            // uleb128 for other
+                            tag %= 128;
+                            if (tag == 4 || tag == 5 || tag == 32 || (tag > 32 && (tag & 1) != 0))
+                                getString(buffer);
+                            else
+                                getUleb128(buffer);
+                        }
+                    }
+                }
+                break;
+            }
+        }
+        return true;
+    }
+
+    private static String getString(ByteBuffer buffer) {
+        StringBuilder sb = new StringBuilder(buffer.limit());
+        while (buffer.remaining() > 0) {
+            char c = (char) buffer.get();
+            if (c == 0)
+                break;
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    private static int getUleb128(ByteBuffer buffer) {
+        int ret = 0;
+        int c;
+        do {
+            ret <<= 7;
+            c = buffer.get();
+            ret |= c & 0x7f;
+        } while((c & 0x80) > 0);
+
+        return ret;
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/libvlc/MediaList.java b/collect-library/src/main/java/org/videolan/libvlc/MediaList.java
new file mode 100644
index 00000000..4ac851cd
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/libvlc/MediaList.java
@@ -0,0 +1,124 @@
+/*****************************************************************************
+ * MediaList.java
+ *****************************************************************************
+ * Copyright © 2013 VLC authors and VideoLAN
+ * Copyright © 2013 Edward Wang
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+package org.videolan.libvlc;
+
+/**
+ * Java/JNI wrapper for the libvlc_media_list_t structure.
+ */
+public class MediaList {
+    private static final String TAG = "VLC/LibVLC/MediaList";
+
+    private long mMediaListInstance = 0; // Read-only, reserved for JNI
+    private long mEventHanderGlobalRef = 0; // Read-only, reserved for JNI
+    private LibVLC mLibVLC; // Used to create new objects that require a libvlc instance
+    private boolean destroyed = false;
+    private EventHandler mEventHandler;
+
+    public MediaList(LibVLC libVLC) {
+        mEventHandler = new EventHandler(); // used in init() below to fire events at the correct targets
+        mMediaListInstance = init(libVLC);
+        mLibVLC = libVLC;
+    }
+    private native long init(LibVLC libvlc_instance);
+
+    @Override
+    public void finalize() {
+        if(!destroyed) destroy();
+    }
+
+    /**
+     * Releases the media list.
+     *
+     * The object should be considered released after this and must not be used.
+     */
+    public void destroy() {
+        nativeDestroy();
+        mMediaListInstance = 0;
+        mEventHanderGlobalRef = 0;
+        mLibVLC = null;
+        destroyed = true;
+    }
+    private native void nativeDestroy();
+
+    public void add(String mrl) {
+        add(mLibVLC, mrl, false, false);
+    }
+    public void add(String mrl, boolean noVideo) {
+        add(mLibVLC, mrl, noVideo, false);
+    }
+    private native void add(LibVLC libvlc_instance, String mrl, boolean noVideo, boolean noOmx);
+
+    /**
+     * Clear the media list. (remove all media)
+     */
+    public native void clear();
+
+    /**
+     * This function checks the currently playing media for subitems at the given
+     * position, and if any exist, it will expand them at the same position
+     * and replace the current media.
+     *
+     * @param position The position to expand
+     * @return -1 if no subitems were found, 0 if subitems were expanded
+     */
+    public int expandMedia(int position) {
+        return expandMedia(mLibVLC, position);
+    }
+    private native int expandMedia(LibVLC libvlc_instance, int position);
+
+    public void loadPlaylist(String mrl) {
+        loadPlaylist(mLibVLC, mrl);
+    }
+    private native void loadPlaylist(LibVLC libvlc_instance, String mrl);
+
+    public void insert(int position, String mrl) {
+        insert(mLibVLC, position, mrl);
+    }
+    private native void insert(LibVLC libvlc_instance, int position, String mrl);
+
+    public native void remove(int position);
+
+    public native int size();
+
+    /**
+     * @param position The index of the media in the list
+     * @return null if not found
+     */
+    public native String getMRL(int position);
+
+    public EventHandler getEventHandler() {
+        return mEventHandler;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("LibVLC Media List: {");
+        for(int i = 0; i < size(); i++) {
+            sb.append(((Integer)i).toString());
+            sb.append(": ");
+            sb.append(getMRL(i));
+            sb.append(", ");
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/libvlc/TrackInfo.java b/collect-library/src/main/java/org/videolan/libvlc/TrackInfo.java
new file mode 100644
index 00000000..7cf23f03
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/libvlc/TrackInfo.java
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * TrackInfo.java
+ *****************************************************************************
+ * Copyright © 2010-2013 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.libvlc;
+
+public class TrackInfo {
+
+    public static final int TYPE_UNKNOWN = -1;
+    public static final int TYPE_AUDIO = 0;
+    public static final int TYPE_VIDEO = 1;
+    public static final int TYPE_TEXT = 2;
+    public static final int TYPE_META = 3;
+
+    public int Type;
+    public int Id;
+    public String Codec;
+    public String Language;
+
+    /* Video */
+    public int Height;
+    public int Width;
+    public float Framerate;
+
+    /* Audio */
+    public int Channels;
+    public int Samplerate;
+
+    /* MetaData */
+    public long Length;
+    public String Title;
+    public String Artist;
+    public String Album;
+    public String Genre;
+    public String ArtworkURL;
+}
diff --git a/collect-library/src/main/java/org/videolan/vlc/MurmurHash.java b/collect-library/src/main/java/org/videolan/vlc/MurmurHash.java
new file mode 100644
index 00000000..bae3723c
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/vlc/MurmurHash.java
@@ -0,0 +1,183 @@
+package org.videolan.vlc;
+
+/** Murmur hash 2.0.
+ *
+ * The murmur hash is a relative fast hash function from
+ * http://murmurhash.googlepages.com/ for platforms with efficient
+ * multiplication.
+ *
+ * This is a re-implementation of the original C code plus some
+ * additional features.
+ *
+ * Public domain.
+ *
+ * @author Viliam Holub
+ * @version 1.0.2
+ *
+ */
+public final class MurmurHash {
+
+    /** Generates 32 bit hash from byte array of the given length and
+     * seed.
+     *
+     * @param data byte array to hash
+     * @param length length of the array to hash
+     * @param seed initial seed value
+     * @return 32 bit hash of the given array
+     */
+    public static int hash32(final byte[] data, int length, int seed) {
+        // 'm' and 'r' are mixing constants generated offline.
+        // They're not really 'magic', they just happen to work well.
+        final int m = 0x5bd1e995;
+        final int r = 24;
+        // Initialize the hash to a random value
+        int h = seed ^ length;
+        int length4 = length / 4;
+
+        for (int i = 0; i < length4; i++) {
+            final int i4 = i * 4;
+            int k = (data[i4 + 0] & 0xff) + ((data[i4 + 1] & 0xff) << 8)
+                    + ((data[i4 + 2] & 0xff) << 16) + ((data[i4 + 3] & 0xff) << 24);
+            k *= m;
+            k ^= k >>> r;
+            k *= m;
+            h *= m;
+            h ^= k;
+        }
+
+        // Handle the last few bytes of the input array
+        switch (length % 4) {
+            case 3:
+                h ^= (data[(length & ~3) + 2] & 0xff) << 16;
+            case 2:
+                h ^= (data[(length & ~3) + 1] & 0xff) << 8;
+            case 1:
+                h ^= (data[length & ~3] & 0xff);
+                h *= m;
+        }
+
+        h ^= h >>> 13;
+        h *= m;
+        h ^= h >>> 15;
+
+        return h;
+    }
+
+    /** Generates 32 bit hash from byte array with default seed value.
+     *
+     * @param data byte array to hash
+     * @param length length of the array to hash
+     * @return 32 bit hash of the given array
+     */
+    public static int hash32(final byte[] data, int length) {
+        return hash32(data, length, 0x9747b28c);
+    }
+
+    /** Generates 32 bit hash from a string.
+     *
+     * @param text string to hash
+     * @return 32 bit hash of the given string
+     */
+    public static int hash32(final String text) {
+        final byte[] bytes = text.getBytes();
+        return hash32(bytes, bytes.length);
+    }
+
+    /** Generates 32 bit hash from a substring.
+     *
+     * @param text string to hash
+     * @param from starting index
+     * @param length length of the substring to hash
+     * @return 32 bit hash of the given string
+     */
+    public static int hash32(final String text, int from, int length) {
+        return hash32(text.substring(from, from + length));
+    }
+
+    /** Generates 64 bit hash from byte array of the given length and seed.
+     *
+     * @param data byte array to hash
+     * @param length length of the array to hash
+     * @param seed initial seed value
+     * @return 64 bit hash of the given array
+     */
+    public static long hash64(final byte[] data, int length, int seed) {
+        final long m = 0xc6a4a7935bd1e995L;
+        final int r = 47;
+
+        long h = (seed & 0xffffffffl) ^ (length * m);
+
+        int length8 = length / 8;
+
+        for (int i = 0; i < length8; i++) {
+            final int i8 = i * 8;
+            long k = ((long) data[i8 + 0] & 0xff) + (((long) data[i8 + 1] & 0xff) << 8)
+                    + (((long) data[i8 + 2] & 0xff) << 16) + (((long) data[i8 + 3] & 0xff) << 24)
+                    + (((long) data[i8 + 4] & 0xff) << 32) + (((long) data[i8 + 5] & 0xff) << 40)
+                    + (((long) data[i8 + 6] & 0xff) << 48) + (((long) data[i8 + 7] & 0xff) << 56);
+
+            k *= m;
+            k ^= k >>> r;
+            k *= m;
+
+            h ^= k;
+            h *= m;
+        }
+
+        switch (length % 8) {
+            case 7:
+                h ^= (long) (data[(length & ~7) + 6] & 0xff) << 48;
+            case 6:
+                h ^= (long) (data[(length & ~7) + 5] & 0xff) << 40;
+            case 5:
+                h ^= (long) (data[(length & ~7) + 4] & 0xff) << 32;
+            case 4:
+                h ^= (long) (data[(length & ~7) + 3] & 0xff) << 24;
+            case 3:
+                h ^= (long) (data[(length & ~7) + 2] & 0xff) << 16;
+            case 2:
+                h ^= (long) (data[(length & ~7) + 1] & 0xff) << 8;
+            case 1:
+                h ^= (long) (data[length & ~7] & 0xff);
+                h *= m;
+        }
+        ;
+
+        h ^= h >>> r;
+        h *= m;
+        h ^= h >>> r;
+
+        return h;
+    }
+
+    /** Generates 64 bit hash from byte array with default seed value.
+     *
+     * @param data byte array to hash
+     * @param length length of the array to hash
+     * @return 64 bit hash of the given string
+     */
+    public static long hash64(final byte[] data, int length) {
+        return hash64(data, length, 0xe17a1465);
+    }
+
+    /** Generates 64 bit hash from a string.
+     *
+     * @param text string to hash
+     * @return 64 bit hash of the given string
+     */
+    public static long hash64(final String text) {
+        final byte[] bytes = text.getBytes();
+        return hash64(bytes, bytes.length);
+    }
+
+    /** Generates 64 bit hash from a substring.
+     *
+     * @param text string to hash
+     * @param from starting index
+     * @param length length of the substring to hash
+     * @return 64 bit hash of the given array
+     */
+    public static long hash64(final String text, int from, int length) {
+        return hash64(text.substring(from, from + length));
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/vlc/PhoneStateReceiver.java b/collect-library/src/main/java/org/videolan/vlc/PhoneStateReceiver.java
new file mode 100644
index 00000000..2b09928d
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/vlc/PhoneStateReceiver.java
@@ -0,0 +1,44 @@
+/*****************************************************************************
+ * PhoneStateReceiver.java
+ *****************************************************************************
+ * Copyright © 2011-2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.vlc;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.telephony.TelephonyManager;
+import org.videolan.libvlc.LibVLC;
+
+public class PhoneStateReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
+
+        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING) ||
+                state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
+
+            LibVLC libVLC = LibVLC.getExistingInstance();
+            if (libVLC != null && libVLC.isPlaying())
+                libVLC.pause();
+        }
+    }
+
+}
diff --git a/collect-library/src/main/java/org/videolan/vlc/RepeatType.java b/collect-library/src/main/java/org/videolan/vlc/RepeatType.java
new file mode 100644
index 00000000..a796e092
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/vlc/RepeatType.java
@@ -0,0 +1,26 @@
+/*****************************************************************************
+ * RepeatType.java
+ *****************************************************************************
+ * Copyright © 2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+package org.videolan.vlc;
+
+public enum RepeatType {
+    None,
+    Once,
+    All
+}
diff --git a/collect-library/src/main/java/org/videolan/vlc/Util.java b/collect-library/src/main/java/org/videolan/vlc/Util.java
new file mode 100644
index 00000000..f5a52091
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/vlc/Util.java
@@ -0,0 +1,546 @@
+/*****************************************************************************
+ * Util.java
+ *****************************************************************************
+ * Copyright © 2011-2013 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.vlc;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Environment;
+import android.preference.PreferenceManager;
+import android.telephony.TelephonyManager;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.WindowManager;
+import android.widget.Toast;
+import com.navinfo.collect.library.system.VLCApplication;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.videolan.libvlc.LibVLC;
+import org.videolan.libvlc.LibVlcException;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+public class Util {
+    public final static String TAG = "VLC/Util";
+    private final static boolean hasNavBar;
+    private Context context;
+    private static volatile Util mInstance;
+
+    /** A set of utility functions for the VLC application */
+
+    static {
+        HashSet<String> devicesWithoutNavBar = new HashSet<String>();
+        devicesWithoutNavBar.add("HTC One V");
+        devicesWithoutNavBar.add("HTC One S");
+        devicesWithoutNavBar.add("HTC One X");
+        devicesWithoutNavBar.add("HTC One XL");
+        hasNavBar = isICSOrLater() && !devicesWithoutNavBar.contains(android.os.Build.MODEL);
+    }
+
+    public static Util getInstance() {
+        if (mInstance == null) {
+            synchronized (Util.class) {
+                if (mInstance == null) {
+                    mInstance = new Util();
+                }
+            }
+        }
+        return mInstance;
+    }
+
+    public void init(Context con){
+        this.context = con;
+        // Are we using advanced debugging - locale?
+        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(con);
+        String p = pref.getString("set_locale", "");
+        if (p != null && !p.equals("")) {
+            Locale locale;
+            // workaround due to region code
+            if(p.equals("zh-TW")) {
+                locale = Locale.TRADITIONAL_CHINESE;
+            } else if(p.startsWith("zh")) {
+                locale = Locale.CHINA;
+            } else if(p.equals("pt-BR")) {
+                locale = new Locale("pt", "BR");
+            } else if(p.equals("bn-IN") || p.startsWith("bn")) {
+                locale = new Locale("bn", "IN");
+            } else {
+                /**
+                 * Avoid a crash of
+                 * java.lang.AssertionError: couldn't initialize LocaleData for locale
+                 * if the user enters nonsensical region codes.
+                 */
+                if(p.contains("-"))
+                    p = p.substring(0, p.indexOf('-'));
+                locale = new Locale(p);
+            }
+            Locale.setDefault(locale);
+            Configuration config = new Configuration();
+            config.locale = locale;
+            con.getResources().updateConfiguration(config,
+                    con.getResources().getDisplayMetrics());
+        }
+    }
+
+    public LibVLC getLibVlcInstance() throws LibVlcException {
+
+        LibVLC instance = LibVLC.getExistingInstance();
+
+        if (instance == null) {
+
+            Thread.setDefaultUncaughtExceptionHandler(new VlcCrashHandler());
+
+            instance = LibVLC.getInstance();
+
+            SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
+
+            updateLibVlcSettings(pref);
+
+            instance.init(context);
+
+        }
+
+        return instance;
+    }
+
+    public static float[] getFloatArray(SharedPreferences pref, String key) {
+        float[] array = null;
+        String s = pref.getString(key, null);
+        if (s != null) {
+            try {
+                JSONArray json = new JSONArray(s);
+                array = new float[json.length()];
+                for (int i = 0; i < array.length; i++)
+                    array[i] = (float) json.getDouble(i);
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+        }
+        return array;
+    }
+
+    public static void putFloatArray(Editor editor, String key, float[] array) {
+        try {
+            JSONArray json = new JSONArray();
+            for (float f : array)
+                json.put(f);
+            editor.putString("equalizer_values", json.toString());
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void updateLibVlcSettings(SharedPreferences pref) {
+        LibVLC instance = LibVLC.getExistingInstance();
+        if (instance == null)
+            return;
+
+        instance.setIomx(pref.getBoolean("enable_iomx", false));
+        instance.setSubtitlesEncoding(pref.getString("subtitles_text_encoding", ""));
+        instance.setTimeStretching(pref.getBoolean("enable_time_stretching_audio", false));
+        instance.setFrameSkip(pref.getBoolean("enable_frame_skip", false));
+        instance.setChroma(pref.getString("chroma_format", ""));
+        instance.setVerboseMode(pref.getBoolean("enable_verbose_mode", true));
+
+        if (pref.getBoolean("equalizer_enabled", false))
+            instance.setEqualizer(getFloatArray(pref, "equalizer_values"));
+
+        int aout;
+        try {
+            aout = Integer.parseInt(pref.getString("aout", "-1"));
+        }
+        catch (NumberFormatException nfe) {
+            aout = -1;
+        }
+        int deblocking;
+        try {
+            deblocking = Integer.parseInt(pref.getString("deblocking", "-1"));
+        }
+        catch(NumberFormatException nfe) {
+            deblocking = -1;
+        }
+        int networkCaching = pref.getInt("network_caching_value", 0);
+        if(networkCaching > 60000)
+            networkCaching = 60000;
+        else if(networkCaching < 0)
+            networkCaching = 0;
+        instance.setAout(aout);
+        instance.setDeblocking(deblocking);
+        instance.setNetworkCaching(networkCaching);
+    }
+
+    /** Print an on-screen message to alert the user */
+    public static void toaster(Context context, int stringId, int duration) {
+        Toast.makeText(context, stringId, duration).show();
+    }
+
+    public static void toaster(Context context, int stringId) {
+        toaster(context, stringId, Toast.LENGTH_SHORT);
+    }
+
+    public static File URItoFile(String URI) {
+        return new File(Uri.decode(URI).replace("file://",""));
+    }
+
+    public static String URItoFileName(String URI) {
+        return URItoFile(URI).getName();
+    }
+
+    public static String stripTrailingSlash(String s) {
+        if( s.endsWith("/") && s.length() > 1 )
+            return s.substring(0, s.length() - 1);
+        return s;
+    }
+
+    public static String readAsset(String assetName, String defaultS) {
+        try {
+            InputStream is = VLCApplication.getAppResources().getAssets().open(assetName);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF8"));
+            StringBuilder sb = new StringBuilder();
+            String line = r.readLine();
+            if(line != null) {
+                sb.append(line);
+                line = r.readLine();
+                while(line != null) {
+                    sb.append('\n');
+                    sb.append(line);
+                    line = r.readLine();
+                }
+            }
+            return sb.toString();
+        } catch (IOException e) {
+            return defaultS;
+        }
+    }
+
+    /**
+     * Convert time to a string
+     * @param millis e.g.time/length from file
+     * @return formated string (hh:)mm:ss
+     */
+    public static String millisToString(long millis)
+    {
+        return millisToString(millis, false);
+    }
+
+    /**
+     * Convert time to a string
+     * @param millis e.g.time/length from file
+     * @return formated string "[hh]h[mm]min" / "[mm]min[s]s"
+     */
+    public static String millisToText(long millis)
+    {
+        return millisToString(millis, true);
+    }
+
+    private static String millisToString(long millis, boolean text) {
+        boolean negative = millis < 0;
+        millis = Math.abs(millis);
+
+        millis /= 1000;
+        int sec = (int) (millis % 60);
+        millis /= 60;
+        int min = (int) (millis % 60);
+        millis /= 60;
+        int hours = (int) millis;
+
+        String time;
+        DecimalFormat format = (DecimalFormat)NumberFormat.getInstance(Locale.US);
+        format.applyPattern("00");
+        if (text) {
+            if (millis > 0)
+                time = (negative ? "-" : "") + hours + "h" + format.format(min) + "min";
+            else if (min > 0)
+                time = (negative ? "-" : "") + min + "min";
+            else
+                time = (negative ? "-" : "") + sec + "s";
+        }
+        else {
+            if (millis > 0)
+                time = (negative ? "-" : "") + hours + ":" + format.format(min) + ":" + format.format(sec);
+            else
+                time = (negative ? "-" : "") + min + ":" + format.format(sec);
+        }
+        return time;
+    }
+
+    public static Bitmap scaleDownBitmap(Context context, Bitmap bitmap, int width) {
+        /*
+         * This method can lead to OutOfMemoryError!
+         * If the source size is more than twice the target size use
+         * the optimized version available in AudioUtil::readCoverBitmap
+         */
+        if (bitmap != null) {
+            final float densityMultiplier = context.getResources().getDisplayMetrics().density;
+            int w = (int) (width * densityMultiplier);
+            int h = (int) (w * bitmap.getHeight() / ((double) bitmap.getWidth()));
+            bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
+        }
+        return bitmap;
+    }
+
+    public static Bitmap cropBorders(Bitmap bitmap, int width, int height)
+    {
+        int top = 0;
+        for (int i = 0; i < height / 2; i++) {
+            int pixel1 = bitmap.getPixel(width / 2, i);
+            int pixel2 = bitmap.getPixel(width / 2, height - i - 1);
+            if ((pixel1 == 0 || pixel1 == -16777216) &&
+                    (pixel2 == 0 || pixel2 == -16777216)) {
+                top = i;
+            } else {
+                break;
+            }
+        }
+
+        int left = 0;
+        for (int i = 0; i < width / 2; i++) {
+            int pixel1 = bitmap.getPixel(i, height / 2);
+            int pixel2 = bitmap.getPixel(width - i - 1, height / 2);
+            if ((pixel1 == 0 || pixel1 == -16777216) &&
+                    (pixel2 == 0 || pixel2 == -16777216)) {
+                left = i;
+            } else {
+                break;
+            }
+        }
+
+        if (left >= width / 2 - 10 || top >= height / 2 - 10)
+            return bitmap;
+
+        // Cut off the transparency on the borders
+        return Bitmap.createBitmap(bitmap, left, top,
+                (width - (2 * left)), (height - (2 * top)));
+    }
+
+    public static String getValue(String string, int defaultId)
+    {
+        return (string != null && string.length() > 0) ?
+                string : VLCApplication.getAppContext().getString(defaultId);
+    }
+
+    public static int convertPxToDp(int px) {
+        WindowManager wm = (WindowManager)VLCApplication.getAppContext().
+                getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+        DisplayMetrics metrics = new DisplayMetrics();
+        display.getMetrics(metrics);
+        float logicalDensity = metrics.density;
+        int dp = Math.round(px / logicalDensity);
+        return dp;
+    }
+
+    public static int convertDpToPx(int dp) {
+        return Math.round(
+                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
+                        VLCApplication.getAppResources().getDisplayMetrics())
+        );
+    }
+
+    public static boolean isFroyoOrLater()
+    {
+        return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO;
+    }
+
+    public static boolean isGingerbreadOrLater()
+    {
+        return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD;
+    }
+
+    public static boolean isHoneycombOrLater()
+    {
+        return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB;
+    }
+
+    public static boolean isICSOrLater()
+    {
+        return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+    }
+
+    public static boolean isJellyBeanOrLater()
+    {
+        return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN;
+    }
+
+    public static boolean hasExternalStorage() {
+        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
+    }
+
+    public static boolean hasNavBar()
+    {
+        return hasNavBar;
+    }
+
+    /** hasCombBar test if device has Combined Bar : only for tablet with Honeycomb or ICS */
+    public static boolean hasCombBar() {
+        return (!isPhone()
+                && ((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) &&
+                (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.JELLY_BEAN)));
+    }
+
+    public static boolean isPhone(){
+        TelephonyManager manager = (TelephonyManager)VLCApplication.getAppContext().getSystemService(Context.TELEPHONY_SERVICE);
+        if(manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE){
+            return false;
+        }else{
+            return true;
+        }
+    }
+
+    public static String[] getStorageDirectories()
+    {
+        String[] dirs = null;
+        BufferedReader bufReader = null;
+        try {
+            bufReader = new BufferedReader(new FileReader("/proc/mounts"));
+            ArrayList<String> list = new ArrayList<String>();
+            list.add(Environment.getExternalStorageDirectory().getPath());
+            String line;
+            while((line = bufReader.readLine()) != null) {
+                if(line.contains("vfat") || line.contains("exfat") ||
+                        line.contains("/mnt") || line.contains("/Removable")) {
+                    StringTokenizer tokens = new StringTokenizer(line, " ");
+                    String s = tokens.nextToken();
+                    s = tokens.nextToken(); // Take the second token, i.e. mount point
+
+                    if (list.contains(s))
+                        continue;
+
+                    if (line.contains("/dev/block/vold")) {
+                        if (!line.startsWith("tmpfs") &&
+                                !line.startsWith("/dev/mapper") &&
+                                !s.startsWith("/mnt/secure") &&
+                                !s.startsWith("/mnt/shell") &&
+                                !s.startsWith("/mnt/asec") &&
+                                !s.startsWith("/mnt/obb")
+                                ) {
+                            list.add(s);
+                        }
+                    }
+                }
+            }
+
+            dirs = new String[list.size()];
+            for (int i = 0; i < list.size(); i++) {
+                dirs[i] = list.get(i);
+            }
+        }
+        catch (FileNotFoundException e) {}
+        catch (IOException e) {}
+        finally {
+            if (bufReader != null) {
+                try {
+                    bufReader.close();
+                }
+                catch (IOException e) {}
+            }
+        }
+        return dirs;
+    }
+
+    public static String[] getCustomDirectories() {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(VLCApplication.getAppContext());
+        final String custom_paths = preferences.getString("custom_paths", "");
+        if(custom_paths.equals(""))
+            return new String[0];
+        else
+            return custom_paths.split(":");
+    }
+
+    public static String[] getMediaDirectories() {
+        ArrayList<String> list = new ArrayList<String>();
+        list.addAll(Arrays.asList(Util.getStorageDirectories()));
+        list.addAll(Arrays.asList(Util.getCustomDirectories()));
+        return list.toArray(new String[list.size()]);
+    }
+
+    public static void addCustomDirectory(String path) {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(VLCApplication.getAppContext());
+
+        ArrayList<String> dirs = new ArrayList<String>(
+                Arrays.asList(getCustomDirectories()));
+        dirs.add(path);
+        StringBuilder builder = new StringBuilder();
+        builder.append(dirs.remove(0));
+        for(String s : dirs) {
+            builder.append(":");
+            builder.append(s);
+        }
+        Editor editor = preferences.edit();
+        editor.putString("custom_paths", builder.toString());
+        editor.commit();
+    }
+
+    public static void removeCustomDirectory(String path) {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(VLCApplication.getAppContext());
+        if(!preferences.getString("custom_paths", "").contains(path))
+            return;
+        ArrayList<String> dirs = new ArrayList<String>(
+                Arrays.asList(preferences.getString("custom_paths", "").split(
+                        ":")));
+        dirs.remove(path);
+        String custom_path;
+        if(dirs.size() > 0) {
+            StringBuilder builder = new StringBuilder();
+            builder.append(dirs.remove(0));
+            for(String s : dirs) {
+                builder.append(":");
+                builder.append(s);
+            }
+            custom_path = builder.toString();
+        } else { // don't do unneeded extra work
+            custom_path = "";
+        }
+        Editor editor = preferences.edit();
+        editor.putString("custom_paths", custom_path);
+        editor.commit();
+    }
+
+    /**
+     * Get the formatted current playback speed in the form of 1.00x
+     */
+    public static String formatRateString(float rate) {
+        return String.format(Locale.US, "%.2fx", rate);
+    }
+
+    /**
+     * equals() with two strings where either could be null
+     */
+    public static boolean nullEquals(String s1, String s2) {
+        return (s1 == null ? s2 == null : s1.equals(s2));
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/vlc/VlcCrashHandler.java b/collect-library/src/main/java/org/videolan/vlc/VlcCrashHandler.java
new file mode 100644
index 00000000..c17eba4f
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/vlc/VlcCrashHandler.java
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * VlcCrashHandler.java
+ *****************************************************************************
+ * Copyright © 2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.vlc;
+
+import android.os.Environment;
+import android.text.format.DateFormat;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.Thread.UncaughtExceptionHandler;
+
+public class VlcCrashHandler implements UncaughtExceptionHandler {
+
+    private static final String TAG = "VLC/VlcCrashHandler";
+
+    private UncaughtExceptionHandler defaultUEH;
+
+    public VlcCrashHandler() {
+        this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
+    }
+
+    @Override
+    public void uncaughtException(Thread thread, Throwable ex) {
+
+        final Writer result = new StringWriter();
+        final PrintWriter printWriter = new PrintWriter(result);
+
+        // Inject some info about android version and the device, since google can't provide them in the developer console
+        StackTraceElement[] trace = ex.getStackTrace();
+        StackTraceElement[] trace2 = new StackTraceElement[trace.length+3];
+        System.arraycopy(trace, 0, trace2, 0, trace.length);
+        trace2[trace.length+0] = new StackTraceElement("Android", "MODEL", android.os.Build.MODEL, -1);
+        trace2[trace.length+1] = new StackTraceElement("Android", "VERSION", android.os.Build.VERSION.RELEASE, -1);
+        trace2[trace.length+2] = new StackTraceElement("Android", "FINGERPRINT", android.os.Build.FINGERPRINT, -1);
+        ex.setStackTrace(trace2);
+
+        ex.printStackTrace(printWriter);
+        String stacktrace = result.toString();
+        printWriter.close();
+        Log.e(TAG, stacktrace);
+
+        // Save the log on SD card if available
+        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            String sdcardPath = Environment.getExternalStorageDirectory().getPath();
+            writeLog(stacktrace, sdcardPath + "/vlc_crash");
+            writeLogcat(sdcardPath + "/vlc_logcat");
+        }
+
+        defaultUEH.uncaughtException(thread, ex);
+    }
+
+    private void writeLog(String log, String name) {
+        CharSequence timestamp = DateFormat.format("yyyyMMdd_kkmmss", System.currentTimeMillis());
+        String filename = name + "_" + timestamp + ".log";
+
+        try {
+            FileOutputStream stream = new FileOutputStream(filename);
+            OutputStreamWriter output = new OutputStreamWriter(stream);
+            BufferedWriter bw = new BufferedWriter(output);
+
+            bw.write(log);
+            bw.newLine();
+
+            bw.close();
+            output.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void writeLogcat(String name) {
+        CharSequence timestamp = DateFormat.format("yyyyMMdd_kkmmss", System.currentTimeMillis());
+        String filename = name + "_" + timestamp + ".log";
+        String[] args = { "logcat", "-v", "time", "-d" };
+
+        try {
+            Process process = Runtime.getRuntime().exec(args);
+            InputStreamReader input = new InputStreamReader(
+                    process.getInputStream());
+            OutputStreamWriter output = new OutputStreamWriter(
+                    new FileOutputStream(filename));
+            BufferedReader br = new BufferedReader(input);
+            BufferedWriter bw = new BufferedWriter(output);
+            String line;
+
+            while ((line = br.readLine()) != null) {
+                bw.write(line);
+                bw.newLine();
+            }
+
+            bw.close();
+            output.close();
+            br.close();
+            input.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/vlc/VlcRunnable.java b/collect-library/src/main/java/org/videolan/vlc/VlcRunnable.java
new file mode 100644
index 00000000..2c5ebe0b
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/vlc/VlcRunnable.java
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * VlcRunnable.java
+ *****************************************************************************
+ * Copyright © 2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+package org.videolan.vlc;
+
+public abstract class VlcRunnable implements Runnable {
+    private final Object user;
+
+    public VlcRunnable() {
+        this.user = null;
+    }
+
+    public VlcRunnable(Object o) {
+        this.user = o;
+    }
+
+    public abstract void run(Object o);
+
+    @Override
+    public void run() {
+        run(user);
+    }
+}
diff --git a/collect-library/src/main/java/org/videolan/vlc/WeakHandler.java b/collect-library/src/main/java/org/videolan/vlc/WeakHandler.java
new file mode 100644
index 00000000..4b6c30bc
--- /dev/null
+++ b/collect-library/src/main/java/org/videolan/vlc/WeakHandler.java
@@ -0,0 +1,37 @@
+/*****************************************************************************
+ * WeakHandler.java
+ *****************************************************************************
+ * Copyright © 2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.vlc;
+
+import android.os.Handler;
+
+import java.lang.ref.WeakReference;
+
+public abstract class WeakHandler<T> extends Handler {
+    private WeakReference<T> mOwner;
+
+    public WeakHandler(T owner) {
+        mOwner = new WeakReference<T>(owner);
+    }
+
+    public T getOwner() {
+        return mOwner.get();
+    }
+}
diff --git a/collect-library/src/main/res/drawable/transient_toast_bg.xml b/collect-library/src/main/res/drawable/transient_toast_bg.xml
new file mode 100644
index 00000000..9f1f934f
--- /dev/null
+++ b/collect-library/src/main/res/drawable/transient_toast_bg.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+    <corners android:topLeftRadius="3dp" android:topRightRadius="3dp" android:bottomLeftRadius="3dp" android:bottomRightRadius="3dp"></corners>
+    <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp"/>
+	<solid android:color="#AA535353"></solid>
+</shape>
diff --git a/collect-library/src/main/res/values/colors.xml b/collect-library/src/main/res/values/colors.xml
index 37318024..f3277d08 100644
--- a/collect-library/src/main/res/values/colors.xml
+++ b/collect-library/src/main/res/values/colors.xml
@@ -9,6 +9,7 @@
     <color name="black">#FF000000</color>
     <color name="white">#FFFFFFFF</color>
     <color name="transparent">#00FFFFFF</color>
+    <color name="background_light">#ffffffff</color>
     <color name="draw_line_blue1_color" comment="线数据样式">#028FFF</color>
     <color name="draw_line_blue2_color" comment="线数据样式">#4E55AF</color>
     <color name="draw_line_red_color" comment="线数据样式">#FFF6565D</color>