diff --git a/common/src/main/java/com/yunbao/common/manager/imrongcloud/RongcloudIMManager.java b/common/src/main/java/com/yunbao/common/manager/imrongcloud/RongcloudIMManager.java index abf9f7b62..ae27de871 100644 --- a/common/src/main/java/com/yunbao/common/manager/imrongcloud/RongcloudIMManager.java +++ b/common/src/main/java/com/yunbao/common/manager/imrongcloud/RongcloudIMManager.java @@ -12,11 +12,12 @@ import androidx.annotation.NonNull; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.CircleCrop; import com.bumptech.glide.request.RequestOptions; +import com.iflytek.cloud.SpeechConstant; +import com.iflytek.cloud.SpeechUtility; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.bean.IMLoginModel; import com.yunbao.common.event.RongIMConnectionStatusEvent; import com.yunbao.common.manager.IMLoginManager; -import com.yunbao.common.views.weight.Recognizer; import org.greenrobot.eventbus.EventBus; @@ -61,7 +62,8 @@ public class RongcloudIMManager { Log.e(CLASSNAME, "initRongIM:"); initPhotoGlide(); //初始化科大讯飞语音转文字 - Recognizer.setAppId("671d2ae3"); + String params = SpeechConstant.APPID + "=" + "671d2ae3"; + SpeechUtility.createUtility(application.getApplicationContext(), params); } private static RongIMClient.OnReceiveMessageWrapperListener mListener; diff --git a/common/src/main/java/com/yunbao/common/views/weight/Recognizer.java b/common/src/main/java/com/yunbao/common/views/weight/Recognizer.java deleted file mode 100644 index e566f5f6c..000000000 --- a/common/src/main/java/com/yunbao/common/views/weight/Recognizer.java +++ /dev/null @@ -1,362 +0,0 @@ -package com.yunbao.common.views.weight; - -import android.content.Context; -import android.graphics.drawable.AnimationDrawable; -import android.os.Bundle; -import android.util.AttributeSet; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.Toast; - -import com.iflytek.cloud.ErrorCode; -import com.iflytek.cloud.InitListener; -import com.iflytek.cloud.RecognizerListener; -import com.iflytek.cloud.RecognizerResult; -import com.iflytek.cloud.SpeechConstant; -import com.iflytek.cloud.SpeechError; -import com.iflytek.cloud.SpeechRecognizer; -import com.iflytek.cloud.SpeechUtility; -import com.yunbao.common.R; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; - -import java.util.Locale; -import java.util.Random; - - -public class Recognizer extends RelativeLayout { - private static final String TAG = "Recognizer"; - - private ImageView imgMic; - - private Random random; - private IRecognizedResult mResultCallBack; - private SpeechRecognizer mIat = null; - private AnimationDrawable animStart; - private AnimationDrawable animEnd; - private static String mAppId; - - /** - * 开发者可以通过此接口设置自己从科大讯飞官网申请的 appId。 此方法可以在 SDK init 之后调用。 - * - *

注意: appid 必须和下载的SDK保持一致,否则会出现10407错误 - * - * @param appId 自定义的 appId - */ - public static void setAppId(String appId) { - mAppId = appId; - } - - public Recognizer(Context context) { - super(context); - initViews(); - } - - public Recognizer(Context context, AttributeSet attrs) { - super(context, attrs); - initViews(); - } - - private void initViews() { -// setClickable(true); -// setBackgroundColor(getResources().getColor(R.color.white)); -// RelativeLayout recognizerContainer = -// (RelativeLayout) -// LayoutInflater.from(getContext()) -// .inflate(R.layout.rc_view_recognizer, null); -// View rlMic = recognizerContainer.findViewById(R.id.rl_mic); -// rlMic.setOnClickListener( -// new OnClickListener() { -// @Override -// public void onClick(View view) { -// if (mIat == null || !mIat.isListening()) { -// startRecognize(); -// } else { -// reset(); -// } -// } -// }); -// imgMic = (ImageView) recognizerContainer.findViewById(R.id.img_mic); -// -// -// addView(recognizerContainer); -// random = new Random(); -// String params = SpeechConstant.APPID + "=" + mAppId; -// SpeechUtility.createUtility(getContext().getApplicationContext(), params); - } - - /** - * 初始化监听器。 - */ - private static InitListener mInitListener = - new InitListener() { - - @Override - public void onInit(int code) { - Log.e(TAG, "onInit " + code); - } - }; - - public void startRecognize() { -// if (null == mIat) { -// mIat = SpeechRecognizer.createRecognizer(getContext(), mInitListener); -// } -// if (mIat.isListening()) { -// return; -// } -// setParam(); -// int ret = mIat.startListening(this); -// if (ret != ErrorCode.SUCCESS) { -// Log.e(TAG, "startRecognize ret error " + ret); -// } - } - - /** - * 参数设置,设置听写参数,详见《科大讯飞MSC API手册(Android)》SpeechConstant类 - * - * @param - * @return - */ - private void setParam() { - // 清空参数 - mIat.setParameter(SpeechConstant.PARAMS, null); - - // 设置听写引擎 - mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); - // 设置返回结果格式 - mIat.setParameter(SpeechConstant.RESULT_TYPE, "json"); - - mIat.setParameter(SpeechConstant.DOMAIN, "iat"); - if ("zh".equals(Locale.getDefault().getLanguage().toLowerCase())) { - mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); - mIat.setParameter(SpeechConstant.ACCENT, "mandarin "); - } else { - mIat.setParameter(SpeechConstant.LANGUAGE, "en_us"); - } - // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理 - mIat.setParameter(SpeechConstant.VAD_BOS, "4000"); - // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音 - mIat.setParameter(SpeechConstant.VAD_EOS, "1000"); - // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点 - mIat.setParameter(SpeechConstant.ASR_PTT, "1"); - } - - private void setRandomImageResource() { -// int num = random.nextInt(3) + 1; -// switch (num) { -// case 1: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_01); -// break; -// case 2: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_02); -// break; -// default: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_03); -// break; -// } - } - - private void changeVolume(int volume) { -// if (null != imgMic) { -// switch (volume / 2) { -// case 0: -// setRandomImageResource(); -// break; -// case 1: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_02); -// break; -// case 2: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_03); -// break; -// case 3: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_04); -// break; -// case 4: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_05); -// break; -// case 5: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_06); -// break; -// case 6: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_07); -// break; -// case 7: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_08); -// break; -// case 8: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_09); -// break; -// case 9: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_10); -// break; -// case 10: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_11); -// break; -// case 11: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_12); -// break; -// case 12: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_13); -// break; -// default: -// imgMic.setImageResource(R.mipmap.rc_recognize_volume_14); -// break; -// } -// } - } - - private void endOfSpeech() { -// if (null == imgMic) return; -// imgMic.setImageResource(R.drawable.rc_anim_speech_end); -// animEnd = (AnimationDrawable) imgMic.getDrawable(); -// imgMic.clearAnimation(); -// animEnd.start(); - } - - private void beginOfSpeech() { -// if (null == imgMic) return; -// imgMic.setImageResource(R.drawable.rc_anim_speech_start); -// animStart = (AnimationDrawable) imgMic.getDrawable(); -// imgMic.clearAnimation(); -// animStart.start(); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (null != mIat) { - mIat.cancel(); - mIat.destroy(); - mIat = null; - } - if (null != mResultCallBack) { - mResultCallBack = null; - } - if (animEnd != null) { - animEnd.stop(); - animEnd = null; - } - if (animStart != null) { - animStart.stop(); - animEnd = null; - } - mInitListener = null; - } - - private void printResult(RecognizerResult result) { - String json = result.getResultString(); - String text = parseRecognizeResult(result); - Log.e(TAG, "printResult " + text); - try { - JSONObject obj = new JSONObject(json); - boolean isLast = obj.getBoolean("ls"); - if (isLast) { - endOfSpeech(); - } - } catch (JSONException e) { - e.printStackTrace(); - } - - if (mResultCallBack != null) { - mResultCallBack.onResult(text); - } - } -// -// @Override -// public void onResult(RecognizerResult recognizerResult, boolean b) { -// printResult(recognizerResult); -// if (imgMic != null) { -// imgMic.setImageResource(R.mipmap.rc_recognize_disable); -// } -// } -// -// @Override -// public void onError(SpeechError speechError) { -// if (speechError.getErrorCode() == ErrorCode.ERROR_NO_NETWORK) { -// Toast.makeText( -// getContext(), -// getContext().getString(R.string.load_failure), -// Toast.LENGTH_SHORT) -// .show(); -// } -// if (imgMic != null) { -// imgMic.setImageResource(R.mipmap.rc_recognize_disable); -// } -// } -// -// @Override -// public void onEvent(int eventType, int i1, int i2, Bundle bundle) { -// Log.e(TAG, "RecognizerView onEvent eventType: " + eventType); -// } -// -// @Override -// public void onVolumeChanged(int volume, byte[] bytes) { -// changeVolume(volume); -// } -// -// @Override -// public void onBeginOfSpeech() { -// Log.e(TAG, "RecognizerView onBeginOfSpeech"); -// beginOfSpeech(); -// } -// -// @Override -// public void onEndOfSpeech() { -// Log.e(TAG, "RecognizerView onEndOfSpeech"); -// endOfSpeech(); -// } - - public void setCallBack(IRecognizedResult resultCallBack) { - mResultCallBack = resultCallBack; - } - - private void reset() { - if (null != mIat) { - mIat.cancel(); - mIat.destroy(); - mIat = null; - } - if (null != animEnd) { - animEnd.stop(); - animEnd = null; - } - if (animStart != null) { - animStart.stop(); - animStart = null; - } - if (imgMic != null) { -// imgMic.setImageResource(R.mipmap.rc_recognize_disable); - } - } - - public String parseRecognizeResult(RecognizerResult results) { - StringBuilder ret = new StringBuilder(); - try { - JSONTokener jsonTokener = new JSONTokener(results.getResultString()); - JSONObject jsonObject = new JSONObject(jsonTokener); - - JSONArray words = jsonObject.getJSONArray("ws"); - for (int i = 0; i < words.length(); i++) { - // 转写结果词,默认使用第一个结果 - JSONArray items = words.getJSONObject(i).getJSONArray("cw"); - JSONObject obj = items.getJSONObject(0); - ret.append(obj.getString("w")); - // 如果需要多候选结果,解析数组其他字段 - // for(int j = 0; j < items.length(); j++) - // { - // JSONObject obj = items.getJSONObject(j); - // ret.append(obj.getString("w")); - // } - } - } catch (Exception e) { - e.printStackTrace(); - } - return ret.toString(); - } -} diff --git a/common/src/main/res/mipmap-xxhdpi/icon_withdraw.png b/common/src/main/res/mipmap-xxhdpi/icon_withdraw.png new file mode 100644 index 000000000..f92d292a4 Binary files /dev/null and b/common/src/main/res/mipmap-xxhdpi/icon_withdraw.png differ diff --git a/common/src/main/res/mipmap-xxhdpi/voice_fluctuations.gif b/common/src/main/res/mipmap-xxhdpi/voice_fluctuations.gif new file mode 100644 index 000000000..90c6a18db Binary files /dev/null and b/common/src/main/res/mipmap-xxhdpi/voice_fluctuations.gif differ diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index 2bdd4222f..98cd7738e 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -139,6 +139,7 @@ public class LiveAudienceActivity extends LiveActivity { private int liveBg = 0; //直播间进入房间队列 private Handler liveHandler = new Handler(); + private ImageView voicePress; @Override public T findViewById(@IdRes int id) { @@ -178,7 +179,7 @@ public class LiveAudienceActivity extends LiveActivity { private void initView() { // 竖直滑动 ViewPager verticalViewPager = findViewById(R.id.view_pager); - + voicePress = findViewById(R.id.voice_press); verticalViewPager.setEnableScroll(IMLoginManager.get(mContext).isSlide()); //判断是否有直播悬浮窗,有直接关闭 if (EasyFloat.isShow("LiveFloatView")) { @@ -623,7 +624,7 @@ public class LiveAudienceActivity extends LiveActivity { } public void setEnableScroll(boolean enableScroll) { - verticalViewPager.setEnableScroll(enableScroll); + verticalViewPager.setEnableScroll(IMLoginManager.get(mContext).isSlide()); } @Subscribe(threadMode = ThreadMode.MAIN) @@ -645,7 +646,7 @@ public class LiveAudienceActivity extends LiveActivity { manager.onAdd(liveBean, mLiveType, mLiveTypeVal, mLiveSDK); } } else { - verticalViewPager.setEnableScroll(true); + verticalViewPager.setEnableScroll(IMLoginManager.get(mContext).isSlide()); } } @@ -908,6 +909,18 @@ public class LiveAudienceActivity extends LiveActivity { case MESSAGE_BOTTOM: manager.messageBottom(); break; + case VOICE_PRESS: + voicePress.setVisibility(event.isVoicePress() ? View.VISIBLE : View.GONE); + if (IMLoginManager.get(mContext).isSlide()) { + if (event.isVoicePress()) { + verticalViewPager.setEnableScroll(false); + } else { + verticalViewPager.setEnableScroll(true); + } + } + + break; + } diff --git a/live/src/main/java/com/yunbao/live/dialog/TextHintDialog.java b/live/src/main/java/com/yunbao/live/dialog/TextHintDialog.java new file mode 100644 index 000000000..0ac78c6ac --- /dev/null +++ b/live/src/main/java/com/yunbao/live/dialog/TextHintDialog.java @@ -0,0 +1,48 @@ +package com.yunbao.live.dialog; + +import android.os.Bundle; +import android.os.Handler; +import android.view.Gravity; +import android.view.Window; +import android.view.WindowManager; + +import com.yunbao.common.dialog.AbsDialogFragment; +import com.yunbao.common.utils.DpUtil; +import com.yunbao.live.R; + +public class TextHintDialog extends AbsDialogFragment { + + + @Override + protected int getLayoutId() { + return R.layout.view_text_hint; + } + + @Override + protected int getDialogStyle() { + return R.style.dialog4; + } + + @Override + protected boolean canCancel() { + return false; + } + + @Override + protected void setWindowAttributes(Window window) { + window.setWindowAnimations(com.yunbao.common.R.style.bottomToTopAnim); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = DpUtil.dp2px(309); + params.height = DpUtil.dp2px(44); + params.gravity = Gravity.CENTER; + window.setAttributes(params); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + new Handler().postDelayed(() -> dismiss(), 2000); + } + + +} diff --git a/live/src/main/java/com/yunbao/live/dialog/VoiceDialog.java b/live/src/main/java/com/yunbao/live/dialog/VoiceDialog.java new file mode 100644 index 000000000..ae8294607 --- /dev/null +++ b/live/src/main/java/com/yunbao/live/dialog/VoiceDialog.java @@ -0,0 +1,292 @@ +package com.yunbao.live.dialog; + +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.iflytek.cloud.ErrorCode; +import com.iflytek.cloud.InitListener; +import com.iflytek.cloud.RecognizerListener; +import com.iflytek.cloud.RecognizerResult; +import com.iflytek.cloud.SpeechConstant; +import com.iflytek.cloud.SpeechError; +import com.iflytek.cloud.SpeechRecognizer; +import com.yunbao.common.dialog.AbsDialogFragment; +import com.yunbao.common.glide.ImgLoader; +import com.yunbao.common.utils.DpUtil; +import com.yunbao.live.R; +import com.yunbao.live.activity.LiveAudienceActivity; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; + +import java.util.Locale; + +import pl.droidsonroids.gif.GifImageView; + +public class VoiceDialog extends AbsDialogFragment { + // 语音识别对象 + private SpeechRecognizer mIat = null; + private String TAG = "VoiceDialog"; + private ImageView voiceFluctuations, iconWithdraw; + private TextView voiceChat, fingersSlide; + private GifImageView gifView; + private SpannableStringBuilder builder = new SpannableStringBuilder(); + private boolean isSend = true; + + public boolean isSend() { + return isSend; + } + + @Override + public void onStop() { + super.onStop(); + if (mIat != null) { + mIat.cancel(); + mIat.destroy(); + mIat = null; + } + + } + + public String sendMessage() { + + return voiceChat.getText().toString(); + } + + @Override + protected int getLayoutId() { + return R.layout.view_voice_dialog; + } + + @Override + protected int getDialogStyle() { + return R.style.dialog4; + } + + @Override + protected boolean canCancel() { + return false; + } + + @Override + protected void setWindowAttributes(Window window) { + window.setWindowAnimations(com.yunbao.common.R.style.bottomToTopAnim); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = DpUtil.dp2px(350); + params.height = DpUtil.dp2px(200); + params.gravity = Gravity.CENTER; + window.setAttributes(params); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + voiceFluctuations = (ImageView) findViewById(R.id.voice_fluctuations); + iconWithdraw = (ImageView) findViewById(R.id.icon_withdraw); + voiceChat = (TextView) findViewById(R.id.voice_chat); + fingersSlide = (TextView) findViewById(R.id.fingers_slide); + gifView = (GifImageView) findViewById(R.id.gif_view); + startRecognize(); + iconWithdraw.setVisibility(View.GONE); + } + + /** + * 上划取消 + */ + public void withdraw() { + voiceFluctuations.setVisibility(View.GONE); + gifView.setVisibility(View.GONE); + iconWithdraw.setVisibility(View.VISIBLE); + fingersSlide.setText(getString(R.string.release_cancel_send)); + isSend = false; + } + + /** + * 上划取消 + */ + public void notWithdraw() { + voiceFluctuations.setVisibility(View.VISIBLE); + iconWithdraw.setVisibility(View.GONE); + fingersSlide.setText(getString(R.string.fingers_slide)); + gifView.setVisibility(View.VISIBLE); + isSend = true; + } + + /** + * 科大讯飞内置录音机 + */ + RecognizerListener recognizerListener = new RecognizerListener() { + @Override + public void onVolumeChanged(int volume, byte[] bytes) { + if (volume > 20) { + gifView.setVisibility(View.VISIBLE); + voiceFluctuations.setVisibility(View.GONE); + } + } + + @Override + public void onBeginOfSpeech() { + Log.e(TAG, "onBeginOfSpeech 开始讲话"); + voiceFluctuations.setVisibility(View.GONE); + gifView.setVisibility(View.VISIBLE); + } + + @Override + public void onEndOfSpeech() { + Log.e(TAG, "onBeginOfSpeech 结束讲话"); + ImgLoader.displayGif(mContext, R.mipmap.img_p, voiceFluctuations); + if (TextUtils.isEmpty(voiceChat.getText())) { + dismiss(); + TextHintDialog textHintDialog = new TextHintDialog(); + textHintDialog.show(((LiveAudienceActivity) mContext).getSupportFragmentManager(), "TextHintDialog"); + } + } + + @Override + public void onResult(RecognizerResult recognizerResult, boolean b) { + printResult(recognizerResult); + } + + @Override + public void onError(SpeechError speechError) { + if (speechError.getErrorCode() == ErrorCode.ERROR_NO_NETWORK) { + Toast.makeText( + getContext(), + getContext().getString(com.yunbao.common.R.string.load_failure), + Toast.LENGTH_SHORT) + .show(); + } + + } + + @Override + public void onEvent(int i, int i1, int i2, Bundle bundle) { + + } + }; + + /** + * 结束录音 + */ + private void endOfSpeech() { + } + + /** + * 初始化监听器。 + */ + private InitListener mInitListener = + code -> Log.e(TAG, "onInit " + code); + + /** + * 开始识别 + */ + public void startRecognize() { + if (null == mIat) { + mIat = SpeechRecognizer.createRecognizer(getContext(), mInitListener); + } + if (mIat.isListening()) { + return; + } + setParam(); + int ret = mIat.startListening(recognizerListener); + if (ret != ErrorCode.SUCCESS) { + Log.e(TAG, "startRecognize ret error " + ret); + } + } + + /** + * 参数设置,设置听写参数,详见《科大讯飞MSC API手册(Android)》SpeechConstant类 + * + * @param + * @return + */ + private void setParam() { + // 清空参数 + mIat.setParameter(SpeechConstant.PARAMS, null); + + // 设置听写引擎 + mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); + // 设置返回结果格式 + mIat.setParameter(SpeechConstant.RESULT_TYPE, "json"); + + mIat.setParameter(SpeechConstant.DOMAIN, "iat"); + if ("zh".equals(Locale.getDefault().getLanguage().toLowerCase())) { + mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); + mIat.setParameter(SpeechConstant.ACCENT, "mandarin "); + } else { + mIat.setParameter(SpeechConstant.LANGUAGE, "en_us"); + } + // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理 + mIat.setParameter(SpeechConstant.VAD_BOS, "10000"); + // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音 + mIat.setParameter(SpeechConstant.VAD_EOS, "30000"); + // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点 + mIat.setParameter(SpeechConstant.ASR_PTT, "1"); + } + + /** + * 打印数据结果 + * + * @param result + */ + private void printResult(RecognizerResult result) { + String json = result.getResultString(); + String text = parseRecognizeResult(result); + Log.e(TAG, "printResult " + text); + try { + JSONObject obj = new JSONObject(json); + boolean isLast = obj.getBoolean("ls"); + if (isLast) { + endOfSpeech(); + } + builder.append(text); + voiceChat.setText(builder); + } catch (JSONException e) { + e.printStackTrace(); + } + + + } + + /** + * 转译语音返回 + * + * @param results + * @return + */ + public String parseRecognizeResult(RecognizerResult results) { + StringBuilder ret = new StringBuilder(); + try { + JSONTokener jsonTokener = new JSONTokener(results.getResultString()); + JSONObject jsonObject = new JSONObject(jsonTokener); + + JSONArray words = jsonObject.getJSONArray("ws"); + for (int i = 0; i < words.length(); i++) { + // 转写结果词,默认使用第一个结果 + JSONArray items = words.getJSONObject(i).getJSONArray("cw"); + JSONObject obj = items.getJSONObject(0); + ret.append(obj.getString("w")); + // 如果需要多候选结果,解析数组其他字段 + // for(int j = 0; j < items.length(); j++) + // { + // JSONObject obj = items.getJSONObject(j); + // ret.append(obj.getString("w")); + // } + } + } catch (Exception e) { + e.printStackTrace(); + } + return ret.toString(); + } +} diff --git a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java index 6ba536c79..b4e43512d 100644 --- a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java +++ b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java @@ -20,6 +20,16 @@ public class LiveAudienceEvent extends BaseModel { private int liveTypeVal; private MsgModel msgModel;//全服消息 private AiAutomaticSpeechModel aiAutomaticSpeechModel;//机器人消息 + private boolean voicePress = false; + + public boolean isVoicePress() { + return voicePress; + } + + public LiveAudienceEvent setVoicePress(boolean voicePress) { + this.voicePress = voicePress; + return this; + } public AiAutomaticSpeechModel getAiAutomaticSpeechModel() { return aiAutomaticSpeechModel; @@ -149,7 +159,8 @@ public class LiveAudienceEvent extends BaseModel { AI_AUTOMATIC_SPEECH(26, "机器人助手"), STAR_CHALLENGE_UPGRADE_NOTIFY(27, "星级挑战成功"), MESSAGE_BOTTOM(28, "聊天消息滚动到底部"), - FLOAT_SETTING(29, "悬浮窗设置"); + FLOAT_SETTING(29, "悬浮窗设置"), + VOICE_PRESS(30, "长按展示图片"); private int type; private String name; diff --git a/live/src/main/java/com/yunbao/live/views/LiveAudienceViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveAudienceViewHolder.java index 625a8d5a1..affaa6ea0 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveAudienceViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveAudienceViewHolder.java @@ -12,29 +12,28 @@ import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.ViewFlipper; -import com.opensource.svgaplayer.SVGACallback; import com.opensource.svgaplayer.SVGADrawable; import com.opensource.svgaplayer.SVGAImageView; import com.opensource.svgaplayer.SVGAParser; import com.opensource.svgaplayer.SVGAVideoEntity; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.Constants; -import com.yunbao.common.bean.MsgModel; import com.yunbao.common.bean.NewPeopleInfo; import com.yunbao.common.event.MessageIMEvent; import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.API; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; -import com.yunbao.common.manager.imrongcloud.MessageIMManager; import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.SVGAViewUtils; @@ -48,6 +47,7 @@ import com.yunbao.live.bean.LiveChatBean; import com.yunbao.live.dialog.LiveHDDialogFragment; import com.yunbao.live.dialog.LiveMicUserDialogFragment; import com.yunbao.live.dialog.LivePromotionDialogFragment; +import com.yunbao.live.dialog.VoiceDialog; import com.yunbao.live.event.LiveAudienceEvent; import org.greenrobot.eventbus.EventBus; @@ -79,6 +79,7 @@ public class LiveAudienceViewHolder extends AbsLiveViewHolder { private ImageView giftImage, liveNewPeople; private String newPeopleUrl = null; private View mNewPeopleRedDot; + private LinearLayout voiceButton; public LiveAudienceViewHolder(Context context, ViewGroup parentView) { super(context, parentView); @@ -179,6 +180,7 @@ public class LiveAudienceViewHolder extends AbsLiveViewHolder { return R.layout.view_live_audience; } + @SuppressLint("ClickableViewAccessibility") @Override public void init() { super.init(); @@ -188,6 +190,7 @@ public class LiveAudienceViewHolder extends AbsLiveViewHolder { findViewById(R.id.btn_red_pack).setOnClickListener(this); findViewById(R.id.btn_gift).setOnClickListener(this); findViewById(R.id.btn_zg).setOnClickListener(this); + voiceButton = (LinearLayout) findViewById(R.id.voice_button); giftImage = (ImageView) findViewById(R.id.gift_image); liveNewPeople = (ImageView) findViewById(R.id.live_new_people); svga_new_user_gif = (SVGAImageView) findViewById(R.id.svga_new_user_gif); @@ -262,8 +265,57 @@ public class LiveAudienceViewHolder extends AbsLiveViewHolder { String language = locale.getLanguage(); ImgLoader.display(mContext, TextUtils.equals(language, "zh") ? R.mipmap.live_icon_new_people_cn : R.mipmap.live_icon_newpeople_en, liveNewPeople); + + voiceButton.setOnTouchListener((v, event) -> { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + downY = event.getY(); + //按下 + handler.postDelayed(mLongPressed, 500); + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + float moveY = event.getY(); + if (downY - moveY > 120) { + voiceDialog.withdraw(); + } + if ((downY - moveY < 100) && (downY - moveY > 30)) { + voiceDialog.notWithdraw(); + } + } else if (event.getAction() == MotionEvent.ACTION_UP) { + //松开 + handler.removeCallbacks(mLongPressed); + Bus.get().post(new LiveAudienceEvent() + .setVoicePress(false) + .setType(LiveAudienceEvent.LiveAudienceType.VOICE_PRESS)); + + if (voiceDialog != null) { + if (voiceDialog.isSend() && !TextUtils.isEmpty(voiceDialog.sendMessage())) { + ((LiveActivity) mContext).sendChatMessage(voiceDialog.sendMessage(), null, null); + } + + voiceDialog.dismiss(); + voiceDialog = null; + } + } + return true; + }); + } + private float downY = 0; + + private VoiceDialog voiceDialog = null; + private Runnable mLongPressed = new Runnable() { + @Override + public void run() { + if (voiceDialog == null) { + voiceDialog = new VoiceDialog(); + } + voiceDialog.show(((LiveAudienceActivity) mContext).getSupportFragmentManager(), "VoiceDialog"); + Bus.get().post(new LiveAudienceEvent() + .setVoicePress(true) + .setType(LiveAudienceEvent.LiveAudienceType.VOICE_PRESS)); + } + }; + public static Handler handler = new Handler(); public static Runnable runnable; @@ -360,13 +412,13 @@ public class LiveAudienceViewHolder extends AbsLiveViewHolder { return; } Bundle bundle = new Bundle(); - String url = newPeopleUrl+ (newPeopleUrl.contains("?")?"&":"?") + "g=Appapi&m=Turntable&a=tricky"; + String url = newPeopleUrl + (newPeopleUrl.contains("?") ? "&" : "?") + "g=Appapi&m=Turntable&a=tricky"; url += "&uid=" + CommonAppConfig.getInstance().getUid() + "&token=" + CommonAppConfig.getInstance().getToken() + "&anchorUid=" + mLiveUid; bundle.putString("url", url); bundle.putInt("show_type", 0); - bundle.putInt("height",DpUtil.dp2px(1)); - // bundle.putBoolean("banScrollY",true); + bundle.putInt("height", DpUtil.dp2px(1)); + // bundle.putBoolean("banScrollY",true); LiveHDDialogFragment liveHDDialogFragment = new LiveHDDialogFragment(); liveHDDialogFragment.setArguments(bundle); liveHDDialogFragment.show(((LiveAudienceActivity) mContext).getSupportFragmentManager(), "LiveHDDialogFragment"); diff --git a/live/src/main/res/drawable/bg_voice_chat.xml b/live/src/main/res/drawable/bg_voice_chat.xml new file mode 100644 index 000000000..ef4188aec --- /dev/null +++ b/live/src/main/res/drawable/bg_voice_chat.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/live/src/main/res/layout/activity_live_detail.xml b/live/src/main/res/layout/activity_live_detail.xml index b709ef276..9cb9f4e07 100644 --- a/live/src/main/res/layout/activity_live_detail.xml +++ b/live/src/main/res/layout/activity_live_detail.xml @@ -9,6 +9,13 @@ android:layout_height="match_parent" android:overScrollMode="never" /> - + \ No newline at end of file diff --git a/live/src/main/res/layout/view_live_audience.xml b/live/src/main/res/layout/view_live_audience.xml index 6bc6f15f7..00dccb471 100644 --- a/live/src/main/res/layout/view_live_audience.xml +++ b/live/src/main/res/layout/view_live_audience.xml @@ -245,7 +245,7 @@ android:layout_centerVertical="true" android:layout_marginStart="10dp" android:layout_marginTop="5dp" - + android:clickable="false" android:orientation="horizontal"> + android:background="@drawable/bc_sound_recording_right" + android:clickable="true" + android:focusable="true" + android:focusableInTouchMode="true" + android:gravity="center"> diff --git a/live/src/main/res/layout/view_text_hint.xml b/live/src/main/res/layout/view_text_hint.xml new file mode 100644 index 000000000..f95a9a5e1 --- /dev/null +++ b/live/src/main/res/layout/view_text_hint.xml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/live/src/main/res/layout/view_voice_dialog.xml b/live/src/main/res/layout/view_voice_dialog.xml new file mode 100644 index 000000000..0d7d75834 --- /dev/null +++ b/live/src/main/res/layout/view_voice_dialog.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/live/src/main/res/mipmap-xxxhdpi/icon_voice_press.png b/live/src/main/res/mipmap-xxxhdpi/icon_voice_press.png new file mode 100644 index 000000000..769c6b9d0 Binary files /dev/null and b/live/src/main/res/mipmap-xxxhdpi/icon_voice_press.png differ diff --git a/live/src/main/res/mipmap-xxxhdpi/img_p.png b/live/src/main/res/mipmap-xxxhdpi/img_p.png new file mode 100644 index 000000000..07df06059 Binary files /dev/null and b/live/src/main/res/mipmap-xxxhdpi/img_p.png differ diff --git a/live/src/main/res/values/strings.xml b/live/src/main/res/values/strings.xml index c36459deb..7ef32f6ac 100644 --- a/live/src/main/res/values/strings.xml +++ b/live/src/main/res/values/strings.xml @@ -21,4 +21,7 @@ 開通貴族 享受專屬特權! 前往貴族中心 + 手指上滑,取消發送 + 松開取消發送 + 已超过10秒未识别到录音 diff --git a/main/src/main/java/com/yunbao/main/activity/MainActivity.java b/main/src/main/java/com/yunbao/main/activity/MainActivity.java index 8f634d496..ec9db6525 100644 --- a/main/src/main/java/com/yunbao/main/activity/MainActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/MainActivity.java @@ -1264,12 +1264,11 @@ public class MainActivity extends AbsActivity implements MainAppBarLayoutListene @Subscribe(threadMode = ThreadMode.MAIN) public void onLiveFloatEvent(LiveFloatEvent event) { - - new Handler().post(() -> LiveFloatView.getInstance() - .cacheLiveData(event.getmLiveBean(), event.getmLiveType(), event.getmLiveSDK(), event.getmLiveTypeVal()) - .builderFloat(mContext, event.getmLiveBean().getPull(), LiveAudienceActivity.class)); - - + if (event != null && event.getmLiveBean() != null && !TextUtils.isEmpty(event.getmLiveBean().getPull())){ + new Handler().post(() -> LiveFloatView.getInstance() + .cacheLiveData(event.getmLiveBean(), event.getmLiveType(), event.getmLiveSDK(), event.getmLiveTypeVal()) + .builderFloat(mContext, event.getmLiveBean().getPull(), LiveAudienceActivity.class)); + } } } diff --git a/main/src/main/java/com/yunbao/main/activity/TestActivity.java b/main/src/main/java/com/yunbao/main/activity/TestActivity.java index 911447166..d4094b529 100644 --- a/main/src/main/java/com/yunbao/main/activity/TestActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/TestActivity.java @@ -6,30 +6,18 @@ import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; -import com.yunbao.common.views.weight.IRecognizedResult; -import com.yunbao.common.views.weight.Recognizer; import com.yunbao.main.R; public class TestActivity extends AppCompatActivity { private TextView contextLayout; - private Recognizer recognizer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); contextLayout = findViewById(R.id.context_layout); - recognizer = findViewById(R.id.recognizer); SpannableStringBuilder builder = new SpannableStringBuilder(); - recognizer.setCallBack(new IRecognizedResult() { - @Override - public void onResult(String data) { - builder.append(data); - contextLayout.setText(builder); - } - - }); } } \ No newline at end of file diff --git a/main/src/main/res/layout/activity_test.xml b/main/src/main/res/layout/activity_test.xml index 558c7c8cc..df80af1e9 100644 --- a/main/src/main/res/layout/activity_test.xml +++ b/main/src/main/res/layout/activity_test.xml @@ -12,11 +12,5 @@ android:layout_height="0dp" android:layout_weight="1" /> - - \ No newline at end of file