app/build.gradle
@@ -24,8 +24,8 @@ applicationId "com.future.driver" minSdkVersion 21 targetSdkVersion 29 versionCode 4 versionName "3.0.1" versionCode 1 versionName "1.0" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" ndk { @@ -35,7 +35,7 @@ applicationVariants.all { variant -> // 更新至Android Studio 3.3 gradle 4.10.1 variant.outputs.all { outputFileName = "fuban_driver-${defaultConfig.versionName}-${new Date().format("yyyy-MM-dd" , TimeZone.getTimeZone("GMT+08")) }.apk" outputFileName = "future_driver-${defaultConfig.versionName}-${new Date().format("yyyy-MM-dd" , TimeZone.getTimeZone("GMT+08")) }.apk" } } manifestPlaceholders = [ app/src/main/java/com/future/driver/base/BaseEvent.java
@@ -50,6 +50,9 @@ public static final int FACE_SUC = 10030; // 人脸失败 public static final int FACE_FAILED = 10031; // 人脸成功 public static final int START_RECORD = 10032; //开始录音任务 public static final int FINISH_RECORD = 10033; //结束录音任务 private String msg; private int code; app/src/main/java/com/future/driver/base/MyApplication.kt
@@ -141,7 +141,7 @@ val act = activities[activities.size - 1] // MyApplication.getTTsManager().setVideoText("收到新的订单") when (orderSimpleData.orderType) { 1,2 -> { 1,2,7 -> { (act as MyBaseActivity).showOrder( orderSimpleData.orderId.toString(), orderSimpleData.orderType.toString(), @@ -162,7 +162,7 @@ if (orderSimpleData.status == 2) { val act = activities[activities.size - 1] when (orderSimpleData.orderType) { 1, 2 -> { 1, 2,7 -> { (act as MyBaseActivity).toDorderAct( orderSimpleData.orderId.toString(), orderSimpleData.orderType.toString() @@ -195,7 +195,7 @@ ) val act = activities[activities.size - 1] when (orderSimpleData.orderType) { 1, 2 -> { 1, 2 ,7-> { (act as MyBaseActivity).showOrder( orderSimpleData.orderId.toString(), orderSimpleData.orderType.toString(), @@ -391,6 +391,11 @@ var aMapLocation: AMapLocation? = null var currentOrderId: String = "" var currentOrderType: String = "" var recordOrderType = "" //当前录音的订单类型 var recordOrderId = "" //当前录音的订单id var isRecording = false //当前是否在录音 var orderStatueViews: MutableList<OrderStatueView> = mutableListOf() var testHeartNunm = 0 app/src/main/java/com/future/driver/netUtls/Api.java
@@ -79,6 +79,7 @@ public static String queryCityOrderInfo = "api/orderCrossCity/queryOrderInfo"; //api/orderCrossCity/queryOrderInfo 获取订单跨城详情 public static String setOrderCrossCitySort = "api/orderCrossCity/setOrderCrossCitySort"; ///api/orderCrossCity/setOrderCrossCitySort 修改订单顺序(跨城) public static String setEnd = "api/order/specail"; //改目的地 public static String tape = "api/order/tape"; //提交录音 /** * 消息 app/src/main/java/com/future/driver/ui/UiUtil.kt
@@ -22,6 +22,9 @@ 6 -> { return "包车" } 7 -> { return "接送机/站" } } return "" } app/src/main/java/com/future/driver/ui/main/GetOrderFragment.kt
@@ -117,7 +117,7 @@ if (!data.remark.isNullOrEmpty()) { tv_remark.text = data.remark } if (orderType == "1") { if (orderType == "1"||orderType == "7") { tv_money.gone() } if (orderType == "5" || orderType == "4") { @@ -204,7 +204,7 @@ "2" -> { this.startActivity<TripActivity>("orderId" to orderId, "orderType" to orderType) } "1" -> { "1","7" -> { this.startActivity<TripActivity>("orderId" to orderId, "orderType" to orderType) } "3" -> { app/src/main/java/com/future/driver/ui/main/MainActivity.kt
@@ -6,8 +6,8 @@ import android.os.Handler import android.os.Looper import android.provider.Settings import android.util.Log import android.widget.Toast import androidx.core.app.ActivityCompat import cn.sinata.rxnetty.NettyClient import cn.sinata.xldutils.utils.* import com.amap.api.location.AMapLocation @@ -30,8 +30,10 @@ import com.future.driver.ui.main.event.MineEventActivity import com.future.driver.ui.mine.MineActivity import com.future.driver.ui.mine.MsgActivity import com.future.driver.utils.AudioRecordUtils import com.future.driver.utils.Cache.CacheKey import com.future.driver.utils.DateUtil import com.future.driver.utils.OSSUtil import com.future.driver.utils.download.DownloadUtil import com.google.gson.Gson import com.lljjcoder.style.citylist.Toast.ToastUtils @@ -42,8 +44,8 @@ import org.jetbrains.anko.startActivity import org.jetbrains.anko.toast class MainActivity : MyBaseActivity(), AMapLocationListener { class MainActivity : MyBaseActivity(), AMapLocationListener, AudioRecordUtils.OnAudioStatusUpdateListener { val mainFragment by lazy { MainFragment() @@ -55,17 +57,28 @@ setContentView(R.layout.activity_main) } private var recorder:AudioRecordUtils? = null //录音器 private val VOICE_LENGTH = 1000L*60*5 //实际5分钟一个片段 // private val VOICE_LENGTH = 1000L*15 //测试15秒一个片段 override fun initView() { MyApplication.canPlayVoice = true // var packageName = "com.android.providers.downloads"; // var intent = Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); // intent.setData(Uri.parse("package:" + packageName)); // startActivity(intent); if (CacheKey.getKeyStr(Const.REFUSE_LOCATION).isNotEmpty()&&!RxPermissions(this).isGranted(Manifest.permission.ACCESS_FINE_LOCATION)){ if (CacheKey.getKeyStr(Const.REFUSE_LOCATION).isNotEmpty()&&!RxPermissions(this).isGranted( Manifest.permission.ACCESS_FINE_LOCATION )){ toast("没有定位权限,您将无法收到新订单推送") }else{ if (!RxPermissions(this).isGranted(Manifest.permission.ACCESS_FINE_LOCATION)){ DialogUtil.getDelAndSureDialog(this,"去授权","否","《未来出行司机》需要获取您的当前位置信息,用于查询当前城市是否开通服务,我们会将您的位置实时上传至后端为您匹配和推送附近订单。如果拒绝定位权限,您将无法正常接单。",{ DialogUtil.getDelAndSureDialog( this, "去授权", "否", "《未来出行司机》需要获取您的当前位置信息,用于查询当前城市是否开通服务,我们会将您的位置实时上传至后端为您匹配和推送附近订单。如果拒绝定位权限,您将无法正常接单。", { }){ val subscribe = RxPermissions(this).request(Manifest.permission.ACCESS_FINE_LOCATION).subscribe { @@ -325,6 +338,13 @@ BaseEvent.FACE_FAILED -> { tv_face.visible() } BaseEvent.START_RECORD -> { if (!MyApplication.isRecording) startRecord() } BaseEvent.FINISH_RECORD -> { recorder?.stopRecord() } } } @@ -335,6 +355,70 @@ } } private fun startRecord(){ if (recorder == null){ recorder = AudioRecordUtils(getExternalFilesDir(null)?.path+"/") recorder?.setOnAudioStatusUpdateListener(this) } if (RxPermissions(this).isGranted(Manifest.permission.RECORD_AUDIO)&&RxPermissions(this).isGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)){ Log.e("mmp","订单${MyApplication.recordOrderId} 开始录音...") recorder?.startRecord() } else toast("缺少录音相关权限") } private fun updateVoice(filePath: String) { val ossUtil = OSSUtil(this) ossUtil.uploadSingleWithSize(filePath, object : OSSUtil.OSSUploadCallBack() { override fun onFinishWithSize(url: String?, size: Long) { super.onFinishWithSize(url, size) Log.e("mmp","录音保存路径:${url},大小:${size/1024}kb") val mapByAny = getMapByAny() mapByAny["fileFormat"] = "caf" mapByAny["fileLink"] = url mapByAny["fileSize"] = size/1024 mapByAny["orderId"] = MyApplication.recordOrderId mapByAny["orderType"] = MyApplication.recordOrderType callNet(false,Api.tape,mapByAny){ } } override fun onFial(message: String?) { super.onFial(message) runOnUiThread { Toast.makeText(this@MainActivity, "录音上传失败,请检查网络", Toast.LENGTH_SHORT).show() } } }) } override fun onUpdate(db: Double, time: Long) { MyApplication.isRecording = true if (time >= VOICE_LENGTH) { Log.e("mmp","订单${MyApplication.recordOrderId} 录音片段完成") recorder?.stopRecord() //结束录音 } } override fun onStop(filePath: String) { MyApplication.isRecording = false Thread { updateVoice(filePath) }.start() if (MyApplication.currentOrderId.isNotEmpty()){//行程未结束 继续录制下一段 Log.e("mmp","订单${MyApplication.recordOrderId} 开始下一片段录音") recorder?.startRecord() } } override fun onStartPlay() { } override fun onFinishPlay() { } override fun onDestroy() { super.onDestroy() MyApplication.canPlayVoice = false app/src/main/java/com/future/driver/ui/main/OrderOverActivity.kt
@@ -42,6 +42,7 @@ ll_order_cancel.gone() MyApplication.currentOrderType = "" MyApplication.currentOrderId = "" EventBus.getDefault().post(BaseEvent(BaseEvent.FINISH_RECORD)) ll_pay_result.gone() tv_show_pay_over.gone() } app/src/main/java/com/future/driver/ui/main/TripActivity.kt
@@ -103,7 +103,7 @@ override fun orderInfo(data: OrderSimpleData?) { data?.let { when(it.orderType){ 1,2,3 -> { 1, 2, 3,7 -> { if (it.status == 10 || it.status == 12) { Handler(Looper.getMainLooper()).post { toast("用户已取消订单") @@ -259,7 +259,7 @@ toast("只能在预约时间的半小时内出行") return@let } if (it.data.orderState == 4&& !rxPermissions.isGranted(Manifest.permission.RECORD_AUDIO)&& !rxPermissions.isGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)){ if (it.data.orderState == 4&& (!rxPermissions.isGranted(Manifest.permission.RECORD_AUDIO) || !rxPermissions.isGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE))){ DialogUtil.getDelAndSureDialog(this,"去授权","取消","根据平台规则,为了保证司乘安全,我们将会对行程进行录音,因此需要获取录音和文件存储权限",{ }){ rxPermissions.request(Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE).subscribe { @@ -296,7 +296,7 @@ "2" -> { showMoneyTypeDialog() } "1" -> { "1","7" -> { callStatue(6,{ startActivity<MajorSureMoneyActivity>( "orderId" to orderId, @@ -343,6 +343,7 @@ onlySureDialog.setOnDismissListener { timer.cancel() } EventBus.getDefault().post(BaseEvent(BaseEvent.START_RECORD)) } private fun callStatue(i: Int, click: () -> Unit, clickFail: () -> Unit) { @@ -484,6 +485,8 @@ private fun callOrder() { MyApplication.currentOrderId = orderId MyApplication.currentOrderType = orderType MyApplication.recordOrderId = orderId MyApplication.recordOrderType = orderType var map = getMapByAny() map["orderId"] = orderId map["orderType"] = orderType @@ -506,7 +509,7 @@ tv_end_address.text = it.data.endAddress tv_change_end.gone() } if (orderType == "1"){ if (orderType == "1"||orderType == "7"){ tv_red_money.gone() } tv_red_money.text = it.data.tipMoney.toString() + "元红包" @@ -625,6 +628,9 @@ changeCarFive(true) setTitleText("服务中") slide_btn.changeButtonText("送达该乘客") if (!MyApplication.isRecording){ EventBus.getDefault().post(BaseEvent(BaseEvent.START_RECORD)) } } } } @@ -726,8 +732,8 @@ if (byChangeEnd){ orderBean.data.orderState++ callStatue(orderBean.data.orderState,{ showStatueMapUI(orderBean) showRecordDialog() showStatueMapUI(orderBean) }) { orderBean.data.orderState-- } app/src/main/java/com/future/driver/ui/to_city/TripCityActivity.kt
@@ -1,8 +1,10 @@ package com.future.driver.ui.to_city import android.os.Bundle import android.os.CountDownTimer import android.os.Handler import android.os.Looper import android.view.Gravity import android.view.View import androidx.recyclerview.widget.LinearLayoutManager import cn.sinata.xldutils.utils.* @@ -41,6 +43,7 @@ import io.reactivex.schedulers.Schedulers import kotlinx.android.synthetic.main.activity_trip_city.* import kotlinx.android.synthetic.main.dialog_select_pay_type.view.* import kotlinx.android.synthetic.main.dialog_sure_and_del.view.* import kotlinx.android.synthetic.main.item_city_over.* import kotlinx.android.synthetic.main.item_city_over.view.* import kotlinx.android.synthetic.main.item_map_market.view.* @@ -95,6 +98,10 @@ setTitleText("已完成") tv_Right.text = "申请改派" orderId = intent.getStringExtra("orderId") MyApplication.recordOrderId = orderId MyApplication.recordOrderType = orderType recycler_view_order_list.layoutManager = LinearLayoutManager(this) recycler_view_order_list.adapter = tripItemAdapter callOrder() @@ -325,6 +332,7 @@ iv_move.gone() iv_to_gd.gone() cl_over_view.visible() EventBus.getDefault().post(BaseEvent(BaseEvent.FINISH_RECORD)) recycler_view_money.layoutManager = LinearLayoutManager(this) recycler_view_money.adapter = overAdapter orderBean?.let { @@ -345,6 +353,27 @@ } } return b } private fun showRecordDialog(){ val onlySureDialog = DialogUtil.getOnlySureDialog(this, "即将开始行程,\n行程中平台自动开启录音") {} val view = DialogUtil.getView(onlySureDialog) view.tv_view_two_base.gravity = Gravity.CENTER view.view_hint_close_base.visibility = View.INVISIBLE view.tv_count_timer.visible() val timer = object: CountDownTimer(3000, 1000){ override fun onTick(millisUntilFinished: Long) { view.tv_count_timer.text = "${(millisUntilFinished/1000)+1}S" } override fun onFinish() { view.tv_sure_base.callOnClick() } }.start() onlySureDialog.setOnDismissListener { timer.cancel() } EventBus.getDefault().post(BaseEvent(BaseEvent.START_RECORD)) } private fun getAllByOrder(): String? { @@ -734,6 +763,8 @@ changeCarFive(true) setTitleText("服务中") slide_btn.changeButtonText("送达乘客$orderPosition") if (!MyApplication.isRecording) EventBus.getDefault().post(BaseEvent(BaseEvent.START_RECORD)) } } } app/src/main/java/com/future/driver/utils/AudioRecordUtils.java
File was renamed from app/src/main/java/com/future/driver/utils/AudioRecoderUtils.java @@ -13,7 +13,7 @@ import cn.sinata.xldutils.utils.TimeUtils; public class AudioRecoderUtils { public class AudioRecordUtils { //文件路径 private String filePath; @@ -22,7 +22,7 @@ private MediaRecorder mMediaRecorder; private final String TAG = "fan"; public static final int MAX_LENGTH = 1000 * 60;// 最大录音时长1000*60*10; public static final int MAX_LENGTH = 1000 * 600;// 最大录音时长十分钟,实际行程设置为5分钟上传一次 private OnAudioStatusUpdateListener audioStatusUpdateListener; private MediaPlayer mMediaPlayer; @@ -30,12 +30,12 @@ /** * 文件存储默认sdcard/record */ public AudioRecoderUtils() { public AudioRecordUtils() { //默认保存路径为/sdcard/record/下 this(Environment.getExternalStorageDirectory() + "/record/"); } public AudioRecoderUtils(String filePath) { public AudioRecordUtils(String filePath) { File path = new File(filePath); if (!path.exists()) @@ -105,7 +105,7 @@ mMediaRecorder = null; audioStatusUpdateListener.onStop(filePath); filePath = ""; // filePath = ""; //这行代码会引起连续录音文件为空的bug } catch (RuntimeException e) { if (mMediaRecorder != null) { app/src/main/java/com/future/driver/utils/OSSUtil.java
@@ -15,6 +15,7 @@ import com.alibaba.sdk.android.oss.internal.OSSAsyncTask; import com.alibaba.sdk.android.oss.model.PutObjectRequest; import com.alibaba.sdk.android.oss.model.PutObjectResult; import com.future.driver.base.MyApplication; import java.io.File; import java.util.ArrayList; @@ -122,6 +123,56 @@ mTasks.add(task); } private void uploadVoice(final String url, final OSSUploadCallBack callBack) { String recordOrderId = MyApplication.Companion.getRecordOrderId(); String recordOrderType = MyApplication.Companion.getRecordOrderType(); final String objectKey = "driver/record/" +recordOrderType+"_"+recordOrderId+"_"+url.substring(url.lastIndexOf("/")+1); PutObjectRequest put = new PutObjectRequest(bucketName, objectKey, url); put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() { long temp = 0; @Override public void onProgress(PutObjectRequest request, long currentSize, long totalSize) { CURRENT_SIZE += currentSize - temp; temp = currentSize; callBack.onSizeProgress(CURRENT_SIZE, TOTAL_SIZE); } }); OSSAsyncTask<PutObjectResult> task = mOss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() { @Override public void onSuccess(PutObjectRequest request, PutObjectResult result) { mActivity.runOnUiThread(new Runnable() { @Override public void run() { URLs.add(mOss.presignPublicObjectURL(bucketName, objectKey)); callBack.onFinishWithSize(URLs.get(0),CURRENT_SIZE); mTasks.clear(); } }); } @Override public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) { // 请求异常 if (clientException != null) { clientException.printStackTrace(); // 本地异常如网络异常等 callBack.onFial("网络异常"); } if (serviceException != null) { serviceException.printStackTrace(); // 服务异常 callBack.onFial("服务器异常"); } } }); mTasks.add(task); } /** * 单文件上传 @@ -137,6 +188,17 @@ } TOTAL_COUNT = single.size(); upload(single, true, callBack); } /** * 单文件上传 * * @param url the url * @param callBack the call back */ public void uploadSingleWithSize(String url, OSSUploadCallBack callBack) { uploadVoice(url, callBack); } /** @@ -158,6 +220,10 @@ public void onFinish(String url) { } //单张上传成功 public void onFinishWithSize(String url,Long size) { } //批量上传成功 public void onFinish(ArrayList<String> urls) {