boss最近提出新的需求,说是项目中的语音输入(讯飞语音)界面不够友好,要求按照微信语音输入界面进行修改,于是乎有了本篇文章。
项目中用到的语音输入采用的是讯飞的SDK。集成讯飞语音输入,请参考官方文档。
先看看微信语音输入的界面吧。

在进行语音输入时需要按住中间的按钮,按钮的背景色能够跟随输入音量的大小进行扩大或者缩小,有文字输入后,按钮的左右两侧分别显示清空和完成。

一、首先进行页面分析。

根据以上微信操作分析,页面实现需要完成以下内容:
(1)通过监听按钮的touch事件,对页面进行变动。
(2)监听音量大小实现背景色直径的变动。
(3)在松开按钮到语音输入结果返回时,需要显示进度条。
1、第一点就是通过监听按钮的OnTouchListener,监听用户的ACTION_DOWN和ACTION_UP的动作,并进行响应的操作。

rl_voice.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN ://按下按钮后的操作break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP://松开按钮后的操作break;}return true;}});

2、第二点背景直径变化,偷懒了一下,利用了一个第三方框架(可以设置圆角的imageview框架),根据音量的变化,动态的改变了RoundedImageView的圆角和长宽。当然也可以自己去绘制,也是一样的。采用的第三方的框架依赖为:compile ‘com.makeramen:roundedimageview:2.3.0’。具体实现:

private void setVolume(int var1) {if(var1 > 5) {var1 = 5;}RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view_wave.getLayoutParams();params.height = dip2px(getContext(), 70) + dip2px(getContext(), var1*2);params.width = dip2px(getContext(), 70) + dip2px(getContext(), var1*2);view_wave.setLayoutParams(params);view_wave.setCornerRadius(params.height/2);}

3、第三点圆形进度条需要自定义view,参考的是Android 自定义漂亮的圆形进度条。
然后将以上内容组合,放入到自定义的Dialog中,语音输入的页面就基本上完成了。

二、调用讯飞语音SDK的相关API。

之前采用的讯飞语音demo上的页面,虽然采用了自定义页面,当时初始化及调用的方法是相同的,代码如下:
(1)进行初始化设置(SDK的初始化在app的onCreate方法中进行)

private void init() {mPreContent = mResultText.getText().toString().trim();mResultText.requestFocus();mIatResults = new LinkedHashMap<String, String>();// 初始化识别无UI识别对象// 使用SpeechRecognizer对象,可根据回调消息自定义界面;mIat = SpeechRecognizer.createRecognizer(mContext, mInitListener);// 初始化听写Dialog// 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源mIatDialog = new VoiceBottomDialog(mContext, R.style.MyBottomDialog, mInitListener);mIatDialog.setCanceledOnTouchOutside(false);// 设置参数setParam();// 显示听写对话框mIatDialog.setResultListener(mRecognizerDialogListener);mIatDialog.show();//外界传入的EditText,用于完成输入结果展示mIatDialog.setInputTextView(mResultText);mIatDialog.setHashMap(mIatResults);}
private void setParam() {if(mIat == null) {return;}// 清空参数mIat.setParameter(SpeechConstant.PARAMS, null);// 设置听写引擎mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);// 设置返回结果格式mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");String lag = SPDtadUtils.getXFString(mContext, "iat_language_preference","mandarin");if (lag.equals("en_us")) {// 设置语言mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");mIat.setParameter(SpeechConstant.ACCENT, null);} else {// 设置语言mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");// 设置语言区域mIat.setParameter(SpeechConstant.ACCENT, lag);}// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理mIat.setParameter(SpeechConstant.VAD_BOS, SPDtadUtils.getXFString(mContext, "iat_vadbos_preference", "4000"));// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音//**长按如果5s静音,即自动停止,可根据需求进行调节**mIat.setParameter(SpeechConstant.VAD_EOS, SPDtadUtils.getXFString(mContext, "iat_vadeos_preference", "5000"));// 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点mIat.setParameter(SpeechConstant.ASR_PTT, SPDtadUtils.getXFString(mContext, "iat_punc_preference", "1"));// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限// 注:AUDIO_FORMAT参数语记需要更新版本才能生效mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav");}

使用讯飞语音听写注意事项:输入时长<=60s。官方说了:不超过60秒。如果需大于60秒的,请移步到语音转写服务。
(2)自定义Dialog设置输入结果监听

---mSpeechRecognizer.setParameter("msc.skin", "default");int var3 = mSpeechRecognizer.startListening(recognizerListener);
---- private RecognizerListener recognizerListener = new RecognizerListener() {public void onBeginOfSpeech() {}public void onVolumeChanged(int var1, byte[] var2) {if(k == 1) {var1 = (var1 + 2) / 5;setVolume(var1);}}public void onEndOfSpeech() {if(null != mDialogListener) {mDialogListener.onEndOfSpeech();}//监听说完话后的网络请求Log.e("VoiceBottomDialog", "说完了");Toast.makeText(mContext, "已经结束了", Toast.LENGTH_SHORT).show();stopProgress();isEndofSpeech = true;stopSpeeching();}public void onResult(RecognizerResult var1, boolean var2) {if(null != mDialogListener) {mDialogListener.onResult(var1, var2);}if(var2) {isHaveResult = false;}}public void onError(SpeechError var1) {if(null != mDialogListener) {mDialogListener.onError(var1);}Log.e("VoiceBottomDialog", var1.getPlainDescription(true));if(var1.getErrorCode() >= 20001 && var1.getErrorCode() < 20004) {isNetOut = true;Toast.makeText(mContext, "网络异常", Toast.LENGTH_SHORT).show();}stopProgress();}public void onEvent(int var1, int var2, int var3, Bundle var4) {}};

以上就是实现的基本思路。

三、主要代码

以下是主要代码:
(1)管理类,主要调用对象

public class XFSpeechManager {private Activity mContext;// 用HashMap存储听写结果private HashMap<String, String> mIatResults;// 语音听写对象private SpeechRecognizer mIat;private TextView mResultText;// 语音听写UIprivate VoiceBottomDialog mIatDialog;// 引擎类型private String mEngineType = SpeechConstant.TYPE_CLOUD;public XFSpeechManager(Activity context, TextView resultText) {mContext = context;mResultText = resultText;if(requirePermission(20)) {init();}}public XFSpeechManager(Activity context, int requestCode, TextView resultText) {mContext = context;mResultText = resultText;if(requirePermission(requestCode)) {init();}}private void init() {mResultText.requestFocus();mIatResults = new LinkedHashMap<String, String>();// 初始化识别无UI识别对象// 使用SpeechRecognizer对象,可根据回调消息自定义界面;mIat = SpeechRecognizer.createRecognizer(mContext, mInitListener);// 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer// 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源mIatDialog = new VoiceBottomDialog(mContext, R.style.MyBottomDialog, mInitListener);mIatDialog.setCanceledOnTouchOutside(false);// 设置参数setParam();// 显示听写对话框mIatDialog.setResultListener(mRecognizerDialogListener);mIatDialog.setInputTextView(mResultText);mIatDialog.setHashMap(mIatResults);mIatDialog.show();}private void setParam() {if(mIat == null) {return;}// 清空参数mIat.setParameter(SpeechConstant.PARAMS, null);// 设置听写引擎mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);// 设置返回结果格式mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");String lag = SPDtadUtils.getXFString(mContext, "iat_language_preference","mandarin");if (lag.equals("en_us")) {// 设置语言mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");mIat.setParameter(SpeechConstant.ACCENT, null);} else {// 设置语言mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");// 设置语言区域mIat.setParameter(SpeechConstant.ACCENT, lag);}// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理mIat.setParameter(SpeechConstant.VAD_BOS, SPDtadUtils.getXFString(mContext, "iat_vadbos_preference", "4000"));// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音mIat.setParameter(SpeechConstant.VAD_EOS, SPDtadUtils.getXFString(mContext, "iat_vadeos_preference", "5000"));// 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点mIat.setParameter(SpeechConstant.ASR_PTT, SPDtadUtils.getXFString(mContext, "iat_punc_preference", "1"));// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限// 注:AUDIO_FORMAT参数语记需要更新版本才能生效mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav");}/*** 听写UI监听器*/private RecognizerResultDialogListener mRecognizerDialogListener = new RecognizerResultDialogListener() {@Overridepublic void onEndOfSpeech() {Log.e("VoiceBottomDialog", "已经被清掉了");}public void onResult(RecognizerResult results, boolean isLast) {printResult(results, isLast);}/*** 识别回调错误.*/public void onError(SpeechError error) {//mContext.showToastMessage(error.getPlainDescription(true));}};private void printResult(RecognizerResult results, boolean isLast) {String text = JsonParser.parseIatResult(results.getResultString());String sn = null;// 读取json结果中的sn字段try {JSONObject resultJson = new JSONObject(results.getResultString());sn = resultJson.optString("sn");} catch (JSONException e) {e.printStackTrace();}mIatResults.put(sn, text);StringBuffer resultBuffer = new StringBuffer();for (String key : mIatResults.keySet()) {resultBuffer.append(mIatResults.get(key));}String content = resultBuffer.toString();Log.e("VoiceBottomDialog", content);mIatDialog.setVoiceContent(content, isLast);if(isLast) {mIatResults.clear();}}/*** 初始化监听器。*/private InitListener mInitListener = new InitListener() {@Overridepublic void onInit(int code) {if (code != ErrorCode.SUCCESS) {Toast.makeText(mContext, "初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();}}};private boolean requirePermission(int requestCode){return PermissionUtils.hasPermission(mContext, requestCode, Manifest.permission.RECORD_AUDIO);}/*** 退出时释放连接*/public void onDestroy(){if( null != mIat ){// 退出时释放连接mIat.cancel();mIat.destroy();}}
}

(2)自定义Dialog

public class VoiceBottomDialog extends Dialog {private Context mContext;private VoiceBottomDialog mDialog;private RelativeLayout rl_voice;private EditText et_voice_content;private TextView tv_voice_empty;private TextView tv_voice_cancel;private TextView tv_voice_finish;private TextView tv_hint;private CompletedView cv_progress;private RoundedImageView view_wave;private TextView mResultText;private SpeechRecognizer mSpeechRecognizer;//gprivate RecognizerResultDialogListener mDialogListener;//hprivate long startTime;private long endTime;private volatile int k;private String preContent = "";private boolean isScroll = true;private boolean isHaveResult = false;private int mCurrentProgress = 0;private boolean isNetOut;//网络问题private boolean isEndofSpeech;private int selectionPosition;//光标位置private HashMap<String, String> mapResult;//用来存储临时语音文字结果的public VoiceBottomDialog(@NonNull Context context, InitListener initListener) {this(context, 0, initListener);}public VoiceBottomDialog(@NonNull Context context, @StyleRes int themeResId, InitListener initListener) {super(context, themeResId);mContext = context;mDialog = this;mSpeechRecognizer = SpeechRecognizer.createRecognizer(context.getApplicationContext(), initListener);init();}private void init() {final View view = LayoutInflater.from(mContext).inflate(R.layout.voiceinput, null);et_voice_content = (EditText) view.findViewById(R.id.tv_voice_content);rl_voice = (RelativeLayout) view.findViewById(R.id.rl_voice);tv_voice_empty = (TextView) view.findViewById(R.id.tv_voice_empty);tv_voice_cancel = (TextView) view.findViewById(R.id.tv_voice_cancel);tv_voice_finish = (TextView) view.findViewById(R.id.tv_voice_finish);tv_hint = (TextView) view.findViewById(R.id.tv_hint);view_wave = (RoundedImageView) view.findViewById(R.id.view_wave);cv_progress = (CompletedView) view.findViewById(R.id.cv_progress);setMatchWidth(view);setListener();}private void startProgress() {Log.e("VoiceBottomDialog", "开始progress");isScroll = true;mCurrentProgress = 0;cv_progress.setVisibility(View.VISIBLE);new Thread(new ProgressRunable()).start();}private void stopProgress() {Log.e("VoiceBottomDialog", "结束progress");isScroll = false;mCurrentProgress = 0;cv_progress.setVisibility(View.GONE);}public void setHashMap(HashMap<String, String> iatResults) {mapResult = iatResults;}class ProgressRunable implements Runnable {@Overridepublic void run() {while (isScroll && isHaveResult && !isNetOut && !isEndofSpeech) {mCurrentProgress += 1;cv_progress.setProgress(mCurrentProgress);try {Thread.sleep(20);} catch (Exception e) {e.printStackTrace();}if(mCurrentProgress >= 100) {mCurrentProgress = 0;}}}}private void setListener() {rl_voice.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN :startTime = SystemClock.currentThreadTimeMillis();if(mSpeechRecognizer == null) {Toast.makeText(mContext, "初始化失败", Toast.LENGTH_SHORT).show();break;}mSpeechRecognizer.setParameter("msc.skin", "default");int var3 = mSpeechRecognizer.startListening(recognizerListener);if(var3 != 0) {Toast.makeText(mContext, Html.fromHtml((new SpeechError(var3)).getHtmlDescription(true)), Toast.LENGTH_SHORT).show();}else {k = 1;}et_voice_content.setVisibility(View.VISIBLE);tv_hint.setVisibility(View.INVISIBLE);tv_voice_cancel.setVisibility(View.INVISIBLE);tv_voice_empty.setVisibility(View.INVISIBLE);tv_voice_finish.setVisibility(View.INVISIBLE);view_wave.setVisibility(View.VISIBLE);isNetOut = false;isEndofSpeech = false;selectionPosition = et_voice_content.getSelectionStart();stopProgress();break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:stopSpeeching();break;}return true;}});tv_voice_empty.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {hiddenKeyborder();et_voice_content.setText("");et_voice_content.setVisibility(View.INVISIBLE);tv_voice_empty.setVisibility(View.INVISIBLE);tv_voice_finish.setVisibility(View.INVISIBLE);preContent = "";tv_hint.setVisibility(View.VISIBLE);tv_voice_cancel.setVisibility(View.VISIBLE);mapResult.clear();stopProgress();}});tv_voice_cancel.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {stopProgress();mDialog.dismiss();}});tv_voice_finish.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {stopProgress();String trim = et_voice_content.getText().toString().trim();if(!TextUtils.isEmpty(trim)) {String preTrim = mResultText.getText().toString().trim();String content = preTrim + trim;mResultText.setText(content);}mapResult.clear();mDialog.dismiss();}});}private void stopSpeeching() {String result = et_voice_content.getText().toString().trim();tv_hint.setVisibility(View.VISIBLE);if(TextUtils.isEmpty(result)) {et_voice_content.setVisibility(View.INVISIBLE);tv_voice_cancel.setVisibility(View.VISIBLE);}else {tv_voice_empty.setVisibility(View.VISIBLE);tv_voice_finish.setVisibility(View.VISIBLE);tv_voice_cancel.setVisibility(View.INVISIBLE);}view_wave.setVisibility(View.INVISIBLE);endTime = SystemClock.currentThreadTimeMillis();if(mSpeechRecognizer == null) {return;}isHaveResult = true;if(endTime - startTime < 100 ) {Toast.makeText(mContext, "说话时间太短", Toast.LENGTH_SHORT).show();isHaveResult = false;}mSpeechRecognizer.stopListening();if(!isNetOut && isHaveResult && !isEndofSpeech) {startProgress();}}private void setMatchWidth(View view) {Window window = mDialog.getWindow();window.setGravity(Gravity.BOTTOM);window.setContentView(view);WindowManager.LayoutParams lp = window.getAttributes(); // 获取对话框当前的参数值lp.width = WindowManager.LayoutParams.MATCH_PARENT;//宽度占满屏幕lp.height = WindowManager.LayoutParams.WRAP_CONTENT;window.setAttributes(lp);}public void setResultListener(RecognizerResultDialogListener var1) {mDialogListener = var1;}/*** 设置语音输入的内容(返回的结果)* @param content* @param isLast*/public void setVoiceContent(String content, boolean isLast){if(!TextUtils.isEmpty(content)) {String startContent = "";String endContent = "";int selectionLength = 0;if(selectionPosition <= preContent.length()) {startContent = preContent.substring(0, selectionPosition);endContent = preContent.substring(selectionPosition);selectionLength = (startContent + content).length();content = startContent + content + endContent;}else {content = preContent + content;selectionLength = content.length();}et_voice_content.setText(content);et_voice_content.setSelection(selectionLength);if(et_voice_content.getVisibility() != View.VISIBLE) {et_voice_content.setVisibility(View.VISIBLE);tv_voice_empty.setVisibility(View.VISIBLE);tv_voice_finish.setVisibility(View.VISIBLE);tv_voice_cancel.setVisibility(View.INVISIBLE);}if(isLast) {preContent = et_voice_content.getText().toString().trim();stopProgress();}}else {stopProgress();}}public void setInputTextView(TextView resultText) {mResultText = resultText;}private RecognizerListener recognizerListener = new RecognizerListener() {public void onBeginOfSpeech() {}public void onVolumeChanged(int var1, byte[] var2) {if(k == 1) {var1 = (var1 + 2) / 5;setVolume(var1);//view_wave.invalidate();}}public void onEndOfSpeech() {if(null != mDialogListener) {mDialogListener.onEndOfSpeech();}//j();//监听说完话后的网络请求Log.e("VoiceBottomDialog", "说完了");Toast.makeText(mContext, "已经结束了", Toast.LENGTH_SHORT).show();stopProgress();isEndofSpeech = true;stopSpeeching();}public void onResult(RecognizerResult var1, boolean var2) {if(null != mDialogListener) {mDialogListener.onResult(var1, var2);}if(var2) {isHaveResult = false;}}public void onError(SpeechError var1) {if(null != mDialogListener) {mDialogListener.onError(var1);}Log.e("VoiceBottomDialog", var1.getPlainDescription(true));if(var1.getErrorCode() >= 20001 && var1.getErrorCode() < 20004) {isNetOut = true;Toast.makeText(mContext, "网络异常", Toast.LENGTH_SHORT).show();}stopProgress();}public void onEvent(int var1, int var2, int var3, Bundle var4) {}};//跟随音量大小,背景直径改变private void setVolume(int var1) {if(var1 > 5) {var1 = 5;}RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view_wave.getLayoutParams();params.height = dip2px(getContext(), 70) + dip2px(getContext(), var1*2);params.width = dip2px(getContext(), 70) + dip2px(getContext(), var1*2);view_wave.setLayoutParams(params);view_wave.setCornerRadius(params.height/2);}private int dip2px(Context context,float dipValue){final float scale=context.getResources().getDisplayMetrics().density;return (int)(dipValue*scale+0.5f);}
}

以上只是部分代码,感兴趣的话,大家可以一块交流。

仿微信语音输入页面(讯飞语音)相关推荐

  1. html语音输入功能讯飞,win10系统利用讯飞语音输入法实现电脑语音输入的方案介绍...

    有关win10系统利用讯飞语音输入法实现电脑语音输入的操作方法想必大家有所耳闻.但是能够对win10系统利用讯飞语音输入法实现电脑语音输入进行实际操作的人却不多.其实解决win10系统利用讯飞语音输入 ...

  2. html语音输入功能讯飞,图解讯飞语音输入法pc版语音悬浮窗的正确用法

    很多人很喜欢讯飞语音输入法电脑版,不用打字只需说话就能轻松得到想要的内容.在这里小编先来教一下大家语音悬浮窗的正确用法. 电脑讯飞语音输入法PC最新版,类似现在最新QQ带的语音输入软件,是云输入哟,讯 ...

  3. html语音输入功能讯飞,讯飞输入法电脑版语音输入功能怎么使用?

    讯飞语音电脑版语音功能的使用教程: 1.开启与关闭 点击语音麦克风开启语音栏(快捷键:F6),如图1所示: (图1) 语音栏开启后,可以点击 号按钮(快捷键:ESC)关闭语音栏. 2.音量校准 首次启 ...

  4. html语音输入功能讯飞,讯飞输入法中实现“语音输入”,手机代替麦克风

    讯飞输入法电脑版有离线语音输入吗 没有.如果是安卓手机,百度手机输入法62616964757a686964616fe59b9ee7ad9431333433626538和讯飞中文输入法在下载离线语音包之 ...

  5. 研究讯飞语音 demo,下载跑跑

    本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/53401000 未经博主允许不得转载. 博主地址是:http://blog.csd ...

  6. 讯飞语音 Great!!!

    http://www.xfyun.cn/doccenter/awd 开发集成 > Android平台 目录[隐藏] 1 概述 2 预备工作 3 语音听写 4 语音识别 5 语音合成 6 语义理解 ...

  7. iOS: 讯飞语音的使用

    一.介绍: 讯飞语音做的相当不错,容错率达到90%多,如果需要做语音方面的功能,它绝对是一个不错的选择.讯飞语音的功能很多:语音听写.语音识别.语音合成等,但我们最常用的还是语音听写.讯飞语音中包含界 ...

  8. “讯飞语音+”语音识别开放功能使用方法介绍

    1"讯飞语音+"功能介绍 "讯飞语音+"主要提供的语音服务包括语音合成.语音识别.语义理解和语音搜索. 语音合成 讯飞语音+提供的语音合成服务包括在线语音合成与 ...

  9. android 语音识别 之 讯飞语音移植

    转载自:http://blog.csdn.net/chenshufei2/article/details/8496905 一.简介 语音识别现在应用越来越广泛了 比如语音写短信.语音搜索商品.语音搜索 ...

  10. 微信小程序+讯飞语音实现个人语音助手

    由于 上传图片过于麻烦,建议 跳转到 github typora-copy-images-to: images 1. 介绍 ​ 本案例主要 实现一个微信小程序语音助手,可以以提供的功能如下: 语音输入 ...

最新文章

  1. PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头2
  2. oracle两张表 比较好,比较Oracle两张表的数据是否一样
  3. python的类程序的结构_python(8)---程序结构
  4. java判断当前时间距离第二天凌晨的秒数
  5. 暴雪帝国辉煌能否延续
  6. python简单小案例列表_python计算列表内各元素的个数实例
  7. iptables高级应用实例
  8. linux cent os7,Cent OS 7系统目录结构
  9. python爬虫技术总结_python爬虫知识点总结(二)爬虫的基本原理
  10. C++智能指针的几种用法
  11. 基于留一法的快速KNN代码
  12. 高速路上车辆组队链接的想法
  13. android Textview属性细节以及EditText属性
  14. Selenium面试问题及答案30题版
  15. 无线网卡连接internet,有线网卡向另一台电脑分享网络(笔记本当有线路由器)...
  16. Python3 flags
  17. 天蝎项目整机柜服务器技术规范v1.01,天蝎项目整机柜服务器技术规范v1.01
  18. Android联网失败报错:java.io.IOException: Cleartext HTTP traffic to xxx.xxx.xxx.xxx not permitted
  19. MySQL登录报错1045解决办法-1045-Access denied for user ‘root‘@‘‘(using password:YES)
  20. Ceph知识树和技能树

热门文章

  1. 数据库技术与应用习题2
  2. 蚂蚁小程序--自学笔记
  3. android fsck,android fsck_msdos分析(一)
  4. 逆向分析QQ消息自动回复机器人设计
  5. 服务器主板支持专用条,AMD专用条又要火了?在H110平台上竟然可以完美使用
  6. Android service进程保护
  7. android百度地图poi路线规划,百度地图开发之poi检索,线路规划(示例代码)
  8. 【WPF学习手记】WPF超链接使用
  9. 天津出差系列(六)----第六天
  10. 在html中制作多彩照片墙,60个照片墙布置方案 记录浪漫时刻