AMR格式语音采集/编码/转码/解码/播放
1、opencore-amr源码下载
https://sourceforge.net/projects/opencore-amr/files/opencore-amr/
2、opencore-amr编译
交叉编译到arm平台
./configure --host=arm-linux-gnueabihf --prefix='/home/dong/pocdemo/opencore-amr-0.1.3/arm'
make
make install
3、opencore-amr的应用
1) opencore-amr静态库的使用
arm-linux-gnueabihf-g++ -o demo demo.c -I ./opencore-amr/include/opencore-amrnb libpoc.a ./opencore-amr/lib/libopencore-amrnb.a -lpthread
2) opencore-amr动态库的使用
arm-linux-gnueabihf-g++ -o demo demo.c -I ./opencore-amr/include/opencore-amrnb -L ./ -lpoc -L ./opencore-amr/lib -lopencore-amrnb -lpthread
3) opencore-amr静态库动态库混合的使用
arm-linux-gnueabihf-g++ -o demo demo.c -I ./opencore-amr/include/opencore-amrnb -L ./ -lpoc ./opencore-amr/lib/libopencore-amrnb.a -lpthread
4、源码包里的 opencore-amr/test/amrnb-enc-sine.c
编码一段正玄波
- /* ------------------------------------------------------------------
- * Copyright (C) 2009 Martin Storsjo
- *
- * 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.
- * -------------------------------------------------------------------
- */
- #include <stdio.h>
- #include <stdint.h>
- #include <math.h>
- #include <interf_enc.h>
- int main(int argc, char *argv[]) {
- int i, j;
- void* amr;
- FILE* out;
- int sample_pos = ;
- if (argc < ) {
- fprintf(stderr, "%s out.amr\n", argv[]);
- return ;
- }
- amr = Encoder_Interface_init();
- out = fopen(argv[], "wb");
- if (!out) {
- perror(argv[]);
- return ;
- }
- fwrite("#!AMR\n", , , out);
- for (i = ; i < ; i++) {
- short buf[];
- uint8_t outbuf[];
- int n;
- for (j = ; j < ; j++) {
- buf[j] = *sin(**3.141592654*sample_pos/);
- sample_pos++;
- }
- n = Encoder_Interface_Encode(amr, MR475, buf, outbuf, );
- fwrite(outbuf, , n, out);
- }
- fclose(out);
- Encoder_Interface_exit(amr);
- return ;
- }
arm-linux-gnueabihf-gcc -o amrnb-enc-sine amrnb-enc-sine.c -I ./opencore-amr/include/opencore-amrnb ./opencore-amr/lib/libopencore-amrnb.a
5、PCM与AMR互转
https://github.com/gansidui/pcm_amr_codec
dong@ubuntu:~/amr/example$ tree
.
├── build_example_amr2pcm_arm.sh
├── build_example_pcm2amr_x86.sh
├── codec
│ ├── amrnb.c
│ ├── amrnb.h
│ ├── audio_format_convert.c
│ ├── audio_format_convert.h
│ └── bs.h
├── dec
├── example_amr2pcm.c
├── example_pcm2amr.c
├── libopencore-amrnb.so.0
├── opencore-amr
│ ├── include
│ │ ├── opencore-amrnb
│ │ │ ├── interf_dec.h
│ │ │ └── interf_enc.h
│ │ └── opencore-amrwb
│ │ ├── dec_if.h
│ │ └── if_rom.h
│ └── lib
│ ├── libopencore-amrnb.a
│ ├── libopencore-amrnb.la
│ ├── libopencore-amrnb.so -> libopencore-amrnb.so.0.0.3
│ ├── libopencore-amrnb.so.0 -> libopencore-amrnb.so.0.0.3
│ ├── libopencore-amrnb.so.0.0.3
│ ├── libopencore-amrwb.a
│ ├── libopencore-amrwb.la
│ ├── libopencore-amrwb.so -> libopencore-amrwb.so.0.0.3
│ ├── libopencore-amrwb.so.0 -> libopencore-amrwb.so.0.0.3
│ ├── libopencore-amrwb.so.0.0.3
│ └── pkgconfig
│ ├── opencore-amrnb.pc
│ └── opencore-amrwb.pc
├── run_dec.sh
├── run_enc.sh
├── test.amr
└── test.amr.pcm
1) gcc可以直接编译
#arm-linux-gnueabihf-gcc example_amr2pcm.c ./codec/audio_format_convert.c ./codec/amrnb.c ./codec/bs.h -o dec -I'./opencore-amr/include/opencore-amrnb' -I'./opencore-amr/include/opencore-amrwb' -I'./codec' ./opencore-amr/lib/libopencore-amrnb.a ./opencore-amr/lib/libopencore-amrwb.a
2) g++和gcc编译需要一点小改动
更改audio_format_convert.h
//#ifdef __cplusplus
//extern "C" {
//#endif
...
...
//#ifdef __cplusplus
//}
//#endif
amrnb.c的第294和368行
int ret = Encoder_Interface_Encode(amrnb_enc, MR475, &samples[offset / sizeof (int16_t)], tmp, amrnb_dtx);
参数mode改成MR475
arm-linux-gnueabihf-g++ example_amr2pcm.c ./codec/audio_format_convert.c ./codec/amrnb.c ./codec/bs.h -o dec -I'./opencore-amr/include/opencore-amrnb' -I'./opencore-amr/include/opencore-amrwb' -I'./codec' ./opencore-amr/lib/libopencore-amrnb.a ./opencore-amr/lib/libopencore-amrwb.a
我的项目整理下编译指令 build.sh
arm-linux-gnueabihf-g++ -o poc_client \
poc_client.c \
./codec/audio_format_convert.c \
./codec/amrnb.c \
./codec/bs.h \
./fifo/app_fifo.c \
./fifo/app_fifo.h \
./list/list.c \
./list/list.h \
-I'./opencore-amr/include/opencore-amrnb' \
-I'./opencore-amr/include/opencore-amrwb' \
-I'./codec' \
./opencore-amr/lib/libopencore-amrnb.a \
./opencore-amr/lib/libopencore-amrwb.a \
./poc/libpoc.a \
-I ./alsa/include -L ./alsa/lib -lasound \
-lpthread
6、alsa播放pcm音频
播放pcm文件
- /**alsa play test
- *ALSA用户空间编译,ALSA驱动的声卡在用户空间,不宜直接使用
- *文件接口中,而应使用alsa-lib
- *打开---->设置参数--->读写音频数据 ALSA全部使用alsa-lib中的API
- *交叉编译
- *export LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH
- *arm-linux-gcc -o alsa_play alsa_play_test.c -L. -lasound
- *需要交叉编译后的libasound.so库的支持
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include "alsa/asoundlib.h"
- int main(int argc, char *argv[])
- {
- int i;
- int ret;
- int buf[];
- unsigned int val;
- int dir=;
- char *buffer;
- int size;
- snd_pcm_uframes_t frames;
- snd_pcm_uframes_t periodsize;
- snd_pcm_t *playback_handle;//PCM设备句柄pcm.h
- snd_pcm_hw_params_t *hw_params;//硬件信息和PCM流配置
- if (argc != ) {
- printf("error: alsa_play_test [music name]\n");
- exit();
- }
- printf("play song %s by wolf\n", argv[]);
- FILE *fp = fopen(argv[], "rb");
- if(fp == NULL)
- return ;
- fseek(fp, , SEEK_SET);
- //1. 打开PCM,最后一个参数为0意味着标准配置
- ret = snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, );
- if (ret < ) {
- perror("snd_pcm_open");
- exit();
- }
- //2. 分配snd_pcm_hw_params_t结构体
- ret = snd_pcm_hw_params_malloc(&hw_params);
- if (ret < ) {
- perror("snd_pcm_hw_params_malloc");
- exit();
- }
- //3. 初始化hw_params
- ret = snd_pcm_hw_params_any(playback_handle, hw_params);
- if (ret < ) {
- perror("snd_pcm_hw_params_any");
- exit();
- }
- //4. 初始化访问权限
- ret = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
- if (ret < ) {
- perror("snd_pcm_hw_params_set_access");
- exit();
- }
- //5. 初始化采样格式SND_PCM_FORMAT_U8,8位
- ret = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_U8);
- if (ret < ) {
- perror("snd_pcm_hw_params_set_format");
- exit();
- }
- //6. 设置采样率,如果硬件不支持我们设置的采样率,将使用最接近的
- //val = 44100,有些录音采样频率固定为8KHz
- val = ;
- ret = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &val, &dir);
- if (ret < ) {
- perror("snd_pcm_hw_params_set_rate_near");
- exit();
- }
- //7. 设置通道数量
- ret = snd_pcm_hw_params_set_channels(playback_handle, hw_params, );
- if (ret < ) {
- perror("snd_pcm_hw_params_set_channels");
- exit();
- }
- /* Set period size to 32 frames. */
- frames = ;
- periodsize = frames * ;
- ret = snd_pcm_hw_params_set_buffer_size_near(playback_handle, hw_params, &periodsize);
- if (ret < )
- {
- printf("Unable to set buffer size %li : %s\n", frames * , snd_strerror(ret));
- }
- periodsize /= ;
- ret = snd_pcm_hw_params_set_period_size_near(playback_handle, hw_params, &periodsize, );
- if (ret < )
- {
- printf("Unable to set period size %li : %s\n", periodsize, snd_strerror(ret));
- }
- //8. 设置hw_params
- ret = snd_pcm_hw_params(playback_handle, hw_params);
- if (ret < ) {
- perror("snd_pcm_hw_params");
- exit();
- }
- /* Use a buffer large enough to hold one period */
- snd_pcm_hw_params_get_period_size(hw_params, &frames, &dir);
- size = frames * ; /* 2 bytes/sample, 2 channels */
- buffer = (char *) malloc(size);
- fprintf(stderr,
- "size = %d\n",
- size);
- while ()
- {
- ret = fread(buffer, , size, fp);
- if(ret == )
- {
- fprintf(stderr, "end of file on input\n");
- break;
- }
- else if (ret != size)
- {
- }
- //9. 写音频数据到PCM设备
- while(ret = snd_pcm_writei(playback_handle, buffer, frames)<)
- {
- usleep();
- if (ret == -EPIPE)
- {
- /* EPIPE means underrun */
- fprintf(stderr, "underrun occurred\n");
- //完成硬件参数设置,使设备准备好
- snd_pcm_prepare(playback_handle);
- }
- else if (ret < )
- {
- fprintf(stderr,
- "error from writei: %s\n",
- snd_strerror(ret));
- }
- }
- }
- //10. 关闭PCM设备句柄
- snd_pcm_close(playback_handle);
- return ;
- }
arm-linux-gnueabihf-gcc -o test test.c -I ./alsa/include -L ./alsa/lib -lasound -lpthread
./test file.pcm
播放pcm缓存
- #include <alsa/asoundlib.h>
- int main()
- {
- int ret;
- snd_pcm_t *pcm_handle;
- snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
- snd_pcm_hw_params_t *hwparams;
- char *pcm_name;
- pcm_name = strdup("plughw:0,0");
- snd_pcm_hw_params_alloca(&hwparams);
- ret = snd_pcm_open(&pcm_handle, pcm_name, stream, );
- if (ret < ) {
- printf("snd_pcm_open failed\n");
- return(-);
- }
- ret = snd_pcm_hw_params_any(pcm_handle, hwparams);
- if (ret < ) {
- printf("snd_pcm_hw_params_any failed\n");
- return(-);
- }
- int rate = ;
- int exact_rate;
- int dir;
- int periods = ;
- snd_pcm_uframes_t periodsize = ;
- ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams,
- SND_PCM_ACCESS_RW_INTERLEAVED);
- if (ret < ) {
- printf("snd_pcm_hw_params_set_access failed\n");
- return(-);
- }
- ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams,
- SND_PCM_FORMAT_S16_LE);
- if (ret < ) {
- printf("snd_pcm_hw_params_set_format failed\n");
- return(-);
- }
- exact_rate = rate;
- ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
- &exact_rate, );
- if (ret < ) {
- printf("snd_pcm_hw_params_set_rate_near failed\n");
- return(-);
- }
- if (rate != exact_rate) {
- printf("The rate %d Hz is not supported by your hardware\n"
- "==> Using %d Hz instead\n", rate, exact_rate);
- }
- ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, );
- if (ret < ) {
- printf("snd_pcm_hw_params_set_channels failed\n");
- return(-);
- }
- /*
- ret = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0);
- if (ret < 0) {
- printf("snd_pcm_hw_params_set_periods failed\n");
- return(-1);
- }
- */
- ret = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams,
- (periodsize * periods) >> );
- if (ret < ) {
- printf("snd_pcm_hw_params_set_buffer_size failed\n");
- return(-);
- }
- ret = snd_pcm_hw_params(pcm_handle, hwparams);
- if (ret < ) {
- printf("snd_pcm_hw_params failed\n");
- return(-);
- }
- unsigned char *data;
- int l1, l2;
- short s1, s2;
- int frames;
- data = malloc(periodsize);
- frames = periodsize >> ;
- for (l1 = ; l1 < ; l1++) {
- for (l2 = ; l2 < frames; l2++) {
- s1 = (l2 % ) * - ;
- s2 = (l2 % ) * - ;
- data[*l2] = (unsigned char)s1;
- data[*l2+] = s1 >> ;
- data[*l2+] = (unsigned char)s2;
- data[*l2+] = s2 >> ;
- }
- while ((ret = snd_pcm_writei(pcm_handle, data, frames)) < ) {
- snd_pcm_prepare(pcm_handle);
- printf("<<<<<<<<<<<<<<Buffer Underrun>>>>>>>>>>>>\n");
- }
- }
- snd_pcm_drop(pcm_handle);
- snd_pcm_drain(pcm_handle);
- return ;
- }
arm-linux-gnueabihf-gcc -o test test.c -I ./alsa/include -L ./alsa/lib -lasound -lpthread
./test
7、alsa采集pcm音频
采集pcm到缓存/文件
- /*
- read from the default PCM device and writes to standard output for 5 seconds of data
- */
- #define ALSA_PCM_NEW_HW_PARAMS_API
- #include <alsa/asoundlib.h>
- snd_pcm_t * handle;
- snd_pcm_hw_params_t * params;
- snd_pcm_uframes_t frames;
- char * buffer;
- unsigned int val;
- int alsa_capture_init()
- {
- int dir;
- int rc;
- /* open PCM device for recording (capture). */
- rc = snd_pcm_open(&handle, "default",SND_PCM_STREAM_CAPTURE,);
- if( rc < )
- {
- return -;
- }
- /* allocate a hardware parameters object */
- snd_pcm_hw_params_alloca(¶ms);
- /* fill it with default values. */
- snd_pcm_hw_params_any(handle,params);
- /* set the desired hardware parameters */
- snd_pcm_hw_params_set_access(handle,params,
- SND_PCM_ACCESS_RW_INTERLEAVED);
- /* signed 16-bit little-endian format */
- snd_pcm_hw_params_set_format(handle,params,
- SND_PCM_FORMAT_S16_LE);
- /* two channels(stereo) */
- snd_pcm_hw_params_set_channels(handle,params,);
- /* sampling rate */
- val = ;
- snd_pcm_hw_params_set_rate_near(handle,params,&val,&dir);
- /* set period size */
- frames = ;
- snd_pcm_hw_params_set_period_size_near(handle,params,&frames,&dir);
- /* write parameters to the driver */
- rc = snd_pcm_hw_params(handle,params);
- if ( rc < )
- {
- return -;
- }
- /* use a buffer large enough to hold one period */
- snd_pcm_hw_params_get_period_size(params,&frames,&dir);
- /* loop for 5 seconds */
- snd_pcm_hw_params_get_period_time(params, &val, &dir);
- return ;
- }
- int main()
- {
- long loops;
- int ret;
- int size;
- FILE * out_fd;
- out_fd = fopen("out_pcm.raw","wb+");
- alsa_capture_init();
- loops = / val;
- /* 2 bytes/sample, 1 channels */
- size = frames * ;
- buffer = ( char * ) malloc(size);
- while( loops > )
- {
- loops--;
- ret = snd_pcm_readi(handle,buffer,frames);
- if ( ret == -EPIPE )
- {
- /* EPIPE means overrun */
- fprintf(stderr,"overrun occured\n");
- snd_pcm_prepare(handle);
- }
- else if ( ret < )
- {
- fprintf(stderr,"error from read: %s\n",
- snd_strerror(ret));
- }
- else if ( ret != (int)frames)
- {
- fprintf(stderr,"short read, read %d frames\n",ret);
- }
- ret = fwrite(buffer, , size, out_fd);
- // ret = write(1, buffer, size);
- if ( ret != size )
- {
- fprintf(stderr,"short write: wrote %d bytes\n",ret);
- }
- }
- snd_pcm_drain(handle);
- snd_pcm_close(handle);
- free(buffer);
- fclose(out_fd);
- }
arm-linux-gnueabihf-gcc -o test test.c -I ./alsa/include -L ./alsa/lib -lasound -lpthread
./test
8、综合应用实例
采集一段PCM格式语音数据 ,转码成AMR格式然后发送至rtp网络
- #if 1
- int i;
- char outbuf[PCM_DATA_LENGTH];
- for (i = ; i < *; i++) {
- ret = snd_pcm_readi(handle,buffer,frames);
- if ( ret == -EPIPE )
- {
- printf("overrun occured\n");
- snd_pcm_prepare(handle);
- }
- buffer_pcm2amr_encode((char*)buffer, PCM_DATA_LENGTH, outbuf);
- //n = Encoder_Interface_Encode(amr, MR795, buf, outbuf, 0);
- amrFrame->m_nFrameLen = ;
- amrFrame->m_nFrameCount = ;
- amrFrame->m_pFrame = outbuf;
- NxZDPttAccess_AmrFrame(snCurCallSessionId, amrFrame);
- }
- #else
- //------------------------------------
- //sin data test
- int i, j;
- int sample_pos = ;
- for (i = ; i < ; i++) {
- short buf[];
- char outbuf[];
- int n;
- for (j = ; j < ; j++) {
- buf[j] = *sin(**3.141592654*sample_pos/);
- sample_pos++;
- }
- buffer_pcm2amr_encode((char*)buf, , outbuf);
- //n = Encoder_Interface_Encode(amr, MR515, buf, outbuf, 0);
- amrFrame->m_nFrameLen = ;
- amrFrame->m_nFrameCount = ;
- amrFrame->m_pFrame = outbuf;
- NxZDPttAccess_AmrFrame(snCurCallSessionId, amrFrame);
- }
- //-------------------------------------
- #endif
接收一段AMR格式语音数据,转码成PCM格式,然后写入声卡播放
- #if 1
- int i;
- for (i = ; i < pAmrFrame->m_nFrameCount; i++) {
- int ret = buffer_amr2pcm_decode(pAmrFrame->m_pFrame + i*pAmrFrame->m_nFrameLen, pAmrFrame->m_nFrameLen, pcm_data_buf);
- if(ret > ){
- if((ret = snd_pcm_writei(pcm_handle, pcm_data_buf, PCM_DATA_LENGTH/)) < ) {
- snd_pcm_prepare(pcm_handle);
- printf("<<<<<<<<<<<<<<Buffer Underrun>>>>>>>>>>>>\n");
- }
- }
- }
- #else
- unsigned char *data;
- int l1, l2;
- short s1, s2;
- int frames;
- int periodsize = ;
- data = (unsigned char*)malloc(periodsize);
- frames = periodsize >> ;
- for (l1 = ; l1 < ; l1++) {
- for (l2 = ; l2 < frames; l2++) {
- s1 = (l2 % ) * - ;
- s2 = (l2 % ) * - ;
- data[*l2] = (unsigned char)s1;
- data[*l2+] = s1 >> ;
- data[*l2+] = (unsigned char)s2;
- data[*l2+] = s2 >> ;
- }
- if((ret = snd_pcm_writei(pcm_handle, data, frames)) < ) {
- snd_pcm_prepare(pcm_handle);
- printf("<<<<<<<<<<<<<<Buffer Underrun>>>>>>>>>>>>\n");
- }
- }
- #endif
9、拓展
tinyalsa做了很多琐事,省了不少时间,感谢作者。
https://github.com/tinyalsa/tinyalsa
generation-sine-wave
https://github.com/ichgw/generation-sine-wave
https://github.com/moutend/getSineWave
https://github.com/munnellg/SineWave
AMR格式语音采集/编码/转码/解码/播放的更多相关文章
- G711格式语音采集/编码/转码/解码/播放
2019-05-01 语音g711格式和AMR格式类似,应用很简单,很多人已经整理过了,收录于此,以备不时之需,用别人现成的足矣,我们的时间应该用来干更有意义的事. 1.PCM to G711 Fas ...
- 如何将微信上传AMR格式语音转化为MP3格式
1. 服务器安装ffmpeg 2. 执行命令 ffmpeg -i {amr_file_path} -f mp3 -acodec libmp3lame -y {mp3_file_path} public ...
- 在java中使用ffmpeg将amr格式的语音转为mp3格式
ffmpeg是一个非常强大的音视频处理工具,官网是:http://ffmpeg.org/. 由于ffmpeg在windows上和linux系统上的执行文件不一样(Windows上不需要安装ffmpeg ...
- 使用X264编码yuv格式的视频帧使用ffmpeg解码h264视频帧
前面一篇博客介绍在centos上搭建点击打开链接ffmpeg及x264开发环境.以下就来问个样例: 1.利用x264库将YUV格式视频文件编码为h264格式视频文件 2.利用ffmpeh库将h264格 ...
- 通过javascript 直接播放amr格式的语言
前段时间做了个功能(有2.3个月了,突然想起来了,就记录一下),语言播放.一开始觉得很简单~~~ 计划应用的是H5的audio标签,但因为这个标签不支持amr格式的语言,但是手机端传到后台的录音却都是 ...
- C# Window Form解决播放amr格式音乐问题
最近搞一个项目,需要获取微信端语音文件,下载之后发现是AMR格式的录音文件,这下把我搞晕了,C#中的4种播放模式不支持播放AMR,想到都觉得头痛,如何是好?最后找到的方案,其实也简单:windows ...
- WebRTC VideoEngine超详细教程(三)——集成X264编码和ffmpeg解码
转自:http://blog.csdn.net/nonmarking/article/details/47958395 本系列目前共三篇文章,后续还会更新 WebRTC VideoEngine超详细教 ...
- 特殊字符url编码以后再解码后出现错误(¬ , ¢, ¤, £)
Url编码的原内容是 “¬ify_url=xxxx” 经过url编码以后再解码回来 “¬”的部分就变成了“¬” 解决方案:把原文里面待url编码的&符号先替换成 ...
- JavaScript中url 传递参数(特殊字符)解决方法及转码解码的介绍
有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了.下表中列出了一些URL特殊符号及编码 十六进制值 1. + URL 中+号表示空格 %2B 2. 空 ...
随机推荐
- iptables 指令语法
iptables 指令 语法: iptables [-t table] command [match] [-j target/jump] -t 参数用来指定规则表,内建的规则表有三个,分别是:nat. ...
- PowerDesigner 同步Name到Comment 及 同步 Comment 到Name
PowerDesigner中使用方法为: PowerDesigner->Tools->Execute Commands->Edit/Run Scripts 代码一:将Name ...
- Objective-c官方文档 怎么使用对象
版权声明:原创作品,谢绝转载!否则将追究法律责任. 对象发送和接受消息 尽管有不同的方法来发送消息在对象之间,到目前位置是想中括号那样[obj doSomeThing]:左边是接受消息的接收器,右 ...
- Android英文文档翻译系列(6)——LocalBroadcastManager
public class LocalBroadcastManager extends Object java.lang.Object ↳ android.support.v4.content.L ...
- WP8.1学习系列(第十六章)——交互UX之命令模式
命令模式 在本文中 命令类型 命令放置 相关主题 你可以在应用商店应用的几个曲面中放置命令和控件,包括应用画布.弹出窗口.对话框和应用栏.在正确的时间选择合适的曲面可能就是易于使用的应用和很难使用 ...
- 【Spring源码分析系列】搭建Spring实现容器的基本实现
前言 bean是Spring中最核心的东西,因为Spring就像一个大水桶,而bean就像是容器中的水,先新建一个小例子来看一下: 一.使用eclipse构建项目,项目结构如下 二.类文件内容 < ...
- HTTP协议剖析 (附HttpWatch工具监控网络请求)
工具:HttpWatch Prov7.2.13破解版(带正版key) HTTP协议概述 思考2个要点: 第一:浏览器和服务器是通过什么连接的 第二:这种连接方式是怎么实现的 通过Interne ...
- selenium中javascript调试
之前写了使用js输入长文件的文章,有同事在使用时,发现竟然无法输入,也不知道是什么原因,且用的还是id方式. 在参考网文后,才发现是js写的有问题,现总结一下 javascript调试,在firefo ...
- 解决远程登陆Linux误按ctrl+s锁屏
很多刚从windows转移到linux上来工作的朋友,在用vi/vim编辑文件时,常常会习惯性的按下Ctrl+s来保存文件内容.殊不知这样按下去后面会造成整个终端不响应了,ssh连接还好说,直接关 ...
- Mongodb 副本集 数据同步简单测试
副本集的搭建,请见 CENTOS6.5 虚拟机MONGODB创建副本集 接下来将简单说明下副本集之间的数据同步. 1.首先,进入primary节点 MOGO_PATH/bin/mongo -por ...