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>