v4l2视频采集摄像头

v4l2 --是Linux内核中关于视频设备的内核驱动框架,为上层访问底层的视频设备提供了统一的接口。
/dev/vidioX

1.打开设备文件
fd=open("/dev/video3",O_RDWR);
/dev/video3:视频设备文件名
O_RDWR:可读可写
fd: open成功反返回文件描述符

jpeg


yuv


2.查询设备支持哪种格式
struct v4l2_fmtdesc fmt; //查询设备格式所用结构体
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.index = 0;
int ret;
//通过ioctl(文件描述符,命令,补充参数(依赖于命令))函数发送命令,成功返回0
ret = ioctl(fd,VIDIOC_ENUM_FMT,&fmt);
printf("format:%s\n",fmt.description);//成功可显示视频所支持的格式
3.设置视频格式
struct v4l2_format s_fmt;
s_fmt.fmt.pix.width = 650;
s_fmt.fmt.pix.height = 480;
s_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
s_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;//4
s_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd,VIDIOC_S_FMT,&s_fmt);

4.申请内核态缓冲
struct v4l2_requestbuffers reqbuf;
//memset(&reqbuf,0,sizeof(reqbuf));
reqbuf.count = 1;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;

ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuf);

5.查询内核缓冲
struct v4l2_buffer buf;
//memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
ret = ioctl(fd,VIDIOC_QUERYBUF,&buf);

6.把内核空间分配好的缓冲映射到用户空间
ub.len = buf.length;
ub.start = mmap(NULL,buf.length,
PROT_READ|PROT_WRITE,
MAP_SHARED,
fd,buf.m.offset);
if(ub.start == MAP_FAILED)
{
perror("mmap");
return -1;
}

7.添加到采集队列
ret = ioctl(fd,VIDIOC_QBUF,&buf);

8.启动视频采集
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd,VIDIOC_STREAMON,&type);

9. 监测视频采集是否完成
int select(int nfds, //最大文件描述符加1
fd_set *readfds,//?
fd_set *writefds, //0
fd_set *exceptfds, //0
struct timeval *timeout);
10.从队列中取出缓冲
ioctl(fd,VIDIOC_DQBUF,&buf);
11.处理图像
process_image(ub.start,ub.len);
12.停止/再次采集
ioctl(fd,VIDIOC_STREAMOFF,&type);/ioctl(fd,VIDIOC_QBUF,&buf);

13.资源回收
munmap(ub.start,ub.len);
close(fd);

 

 

 

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <linux/videodev2.h>

#define CLEAR(x) memset(&(x), 0, sizeof(x))

int fd_fb;
char* pfb;
char yuyv[640*480*2];
char rgb[640*480*3];

struct buffer
{
void* start;
unsigned int length;
};

void process_image(struct buffer bb)
{
int i, j;
int y0, u0, y1, v0;
int r, g, b;
memcpy(yuyv, bb.start, bb.length);
//保存原始yuyv数据

//把yuyv转为rgb数据
for (i = 0; i < 640*480/2 ; i++)
{
y0 = yuyv[i*4];
y1 = yuyv[i*4+2];
u0 = yuyv[i*4+1];
v0 = yuyv[i*4+3];

//第i*2个点
b = (1.164383 * (y0 - 16) + 2.017232*(u0 - 128));
if (b > 255) b = 255;
if (b < 0) b = 0;
g= 1.164383 * (y0 - 16) - 0.391762*(u0 - 128) - 0.812968*(v0 - 128);
if (g > 255) g = 255;
if (g < 0) g = 0;
r= 1.164383 * (y0 - 16) + 1.596027*(v0 - 128);
if (r > 255) r = 255;
if (r < 0) r = 0;
rgb[i*3*2 + 0] = b;
rgb[i*3*2 + 1] = g;
rgb[i*3*2 + 2] = r;

//第i*2+1个点
b = (1.164383 * (y1 - 16) + 2.017232*(u0 - 128));
if (b > 255) b = 255;
if (b < 0) b = 0;
g= 1.164383 * (y1 - 16) - 0.391762*(u0 - 128) - 0.812968*(v0 - 128);
if (g > 255) g = 255;
if (g < 0) g = 0;
r= 1.164383 * (y1 - 16) + 1.596027*(v0 - 128);
if (r > 255) r = 255;
if (r < 0) r = 0;
rgb[i*3*2 + 3] = b;
rgb[i*3*2 + 4] = g;
rgb[i*3*2 + 5] = r;
}

for ( i = 0; i < 480; i++)
{
for(j=0; j<80; j++)
{
*(pfb+(i*800+j)*4 + 0) = 0x00;
*(pfb+(i*800+j)*4 + 1) = 0x00;
*(pfb+(i*800+j)*4 + 2) = 0x00;
}
for (j = 80; j < 720; j++)//????????640
{
*(pfb+(i*800+j)*4 + 0) = rgb[(i*640+j-80)*3 + 0];
*(pfb+(i*800+j)*4 + 1) = rgb[(i*640+j-80)*3 + 1];
*(pfb+(i*800+j)*4 + 2) = rgb[(i*640+j-80)*3 + 2];
}
for(j=720; j<800; j++)
{
*(pfb+(i*800+j)*4 + 0) = 0x00;
*(pfb+(i*800+j)*4 + 1) = 0x00;
*(pfb+(i*800+j)*4 + 2) = 0x00;
}
}
}

int main()
{
int fd_video;
//打开摄像头设备
fd_video = open("/dev/video3", O_RDWR);
if (fd_video < 0)
{
perror("video3 open");
return fd_video;
}
//打开屏幕设备
fd_fb = open("/dev/fb0", O_RDWR);
if (fd_fb < 0)
{
perror("fb open");
return fd_fb;
}
//设置视频的格式
struct v4l2_format s_fmt;
s_fmt.fmt.pix.width = 800;
s_fmt.fmt.pix.height = 480;
s_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
//s_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;//4
s_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int flag= ioctl(fd_video,VIDIOC_S_FMT,&s_fmt);
if(flag != 0)
{
printf("set format error\n");
return -1;
}

printf("%d %d\n",s_fmt.fmt.pix.width,s_fmt.fmt.pix.height);

//映射
pfb = (char *)mmap(NULL, 800*480*4, PROT_WRITE|PROT_READ,MAP_SHARED, fd_fb, 0);
if (pfb == NULL)
{
perror ("mmap");
return -1;
}
//此处作用为申请缓冲区
struct v4l2_requestbuffers req;
req.count=4;
req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory=V4L2_MEMORY_MMAP;
ioctl(fd_video,VIDIOC_REQBUFS,&req);
//缓冲区与应用程序关联
struct buffer *buffers;//start, length
//申请4个struct buffer空间
buffers = (struct buffer*)calloc (req.count, sizeof (struct buffer));
if (!buffers)
{
perror ("Out of memory");
exit (EXIT_FAILURE);
}
unsigned int n_buffers;
for (n_buffers = 0; n_buffers < req.count; n_buffers++)
{
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == ioctl (fd_video, VIDIOC_QUERYBUF, &buf))
exit(-1);
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = mmap (NULL,
buf.length,PROT_READ | PROT_WRITE ,MAP_SHARED,fd_video, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start)
exit(-1);
}

enum v4l2_buf_type type;
int i;
for (i = 0; i < 4; ++i)
{
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ioctl (fd_video, VIDIOC_QBUF, &buf);
}
while(1)
{
//开始捕获图像
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl (fd_video, VIDIOC_STREAMON, &type);


struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//取出图像数据
ioctl (fd_video, VIDIOC_DQBUF, &buf);
//在LCD屏幕上显示图像
process_image (buffers[buf.index]); //YUYV
//告知buf可以使用
ioctl (fd_video,VIDIOC_QBUF,&buf);
}

for (i = 0; i < 4; i++)
munmap(buffers[i].start, buffers[i].length);
free(buffers);
munmap(pfb, 800*480*4);


close(fd_video);
close(fd_fb);

}

代码不够完善,因为要结束摄像头按CTRL + C 最后面6行不会执行,这样的话不会执行munmap释放映射,free内存,close文件操作,

可以用信号signal函数SIGINT (ctrl +c)写个信号函数当按下CTRL + C 时处理最后面6行;

看代码

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <signal.h>

#define CLEAR(x) memset(&(x), 0, sizeof(x))

int fd_fb;
char* pfb;
int fd_video;
char yuyv[640*480*2];
char rgb[640*480*3];
struct buffer *buffers;//start, length

struct buffer
{
void* start;
unsigned int length;
};

void mysignal(int signo)
{
printf("success\n");
int i;
for (i = 0; i < 4; i++)
{
munmap(buffers[i].start, buffers[i].length);
}
free(buffers);
munmap(pfb, 800*480*4);
close(fd_video);
close(fd_fb);
exit(0);
}

void process_image(struct buffer bb)
{
int i, j;
int y0, u0, y1, v0;
int r, g, b;
memcpy(yuyv, bb.start, bb.length);
//保存原始yuyv数据

//把yuyv转为rgb数据
for (i = 0; i < 640*480/2 ; i++)
{
y0 = yuyv[i*4];
y1 = yuyv[i*4+2];
u0 = yuyv[i*4+1];
v0 = yuyv[i*4+3];

//第i*2个点
b = (1.164383 * (y0 - 16) + 2.017232*(u0 - 128));
if (b > 255) b = 255;
if (b < 0) b = 0;
g= 1.164383 * (y0 - 16) - 0.391762*(u0 - 128) - 0.812968*(v0 - 128);
if (g > 255) g = 255;
if (g < 0) g = 0;
r= 1.164383 * (y0 - 16) + 1.596027*(v0 - 128);
if (r > 255) r = 255;
if (r < 0) r = 0;
rgb[i*3*2 + 0] = b;
rgb[i*3*2 + 1] = g;
rgb[i*3*2 + 2] = r;

//第i*2+1个点
b = (1.164383 * (y1 - 16) + 2.017232*(u0 - 128));
if (b > 255) b = 255;
if (b < 0) b = 0;
g= 1.164383 * (y1 - 16) - 0.391762*(u0 - 128) - 0.812968*(v0 - 128);
if (g > 255) g = 255;
if (g < 0) g = 0;
r= 1.164383 * (y1 - 16) + 1.596027*(v0 - 128);
if (r > 255) r = 255;
if (r < 0) r = 0;
rgb[i*3*2 + 3] = b;
rgb[i*3*2 + 4] = g;
rgb[i*3*2 + 5] = r;
}

for ( i = 0; i < 480; i++)
{
for(j=0; j<80; j++)
{
*(pfb+(i*800+j)*4 + 0) = 0x00;
*(pfb+(i*800+j)*4 + 1) = 0x00;
*(pfb+(i*800+j)*4 + 2) = 0x00;
}
for (j = 80; j < 720; j++)//????????640
{
*(pfb+(i*800+j)*4 + 0) = rgb[(i*640+j-80)*3 + 0];
*(pfb+(i*800+j)*4 + 1) = rgb[(i*640+j-80)*3 + 1];
*(pfb+(i*800+j)*4 + 2) = rgb[(i*640+j-80)*3 + 2];
}
for(j=720; j<800; j++)
{
*(pfb+(i*800+j)*4 + 0) = 0x00;
*(pfb+(i*800+j)*4 + 1) = 0x00;
*(pfb+(i*800+j)*4 + 2) = 0x00;
}
}
}

int main()
{
//打开摄像头设备
fd_video = open("/dev/video3", O_RDWR);
if (fd_video < 0)
{
perror("video3 open");
return fd_video;
}
//打开屏幕设备
fd_fb = open("/dev/fb0", O_RDWR);
if (fd_fb < 0)
{
perror("fb open");
return fd_fb;
}
//设置视频的格式
struct v4l2_format s_fmt;
s_fmt.fmt.pix.width = 800;
s_fmt.fmt.pix.height = 480;
s_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
//s_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;//4
s_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int flag= ioctl(fd_video,VIDIOC_S_FMT,&s_fmt);
if(flag != 0)
{
printf("set format error\n");
return -1;
}

printf("%d %d\n",s_fmt.fmt.pix.width,s_fmt.fmt.pix.height);

//映射
pfb = (char *)mmap(NULL, 800*480*4, PROT_WRITE|PROT_READ,MAP_SHARED, fd_fb, 0);
if (pfb == NULL)
{
perror ("mmap");
return -1;
}
//此处作用为申请缓冲区
struct v4l2_requestbuffers req;
req.count=4;
req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory=V4L2_MEMORY_MMAP;
ioctl(fd_video,VIDIOC_REQBUFS,&req);
//缓冲区与应用程序关联

//申请4个struct buffer空间
buffers = (struct buffer*)calloc (req.count, sizeof (struct buffer));
if (!buffers)
{
perror ("Out of memory");
exit (EXIT_FAILURE);
}
unsigned int n_buffers;
for (n_buffers = 0; n_buffers < req.count; n_buffers++)
{
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == ioctl (fd_video, VIDIOC_QUERYBUF, &buf))
exit(-1);
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = mmap (NULL,
buf.length,PROT_READ | PROT_WRITE ,MAP_SHARED,fd_video, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start)
exit(-1);
}

enum v4l2_buf_type type;
int i;
for (i = 0; i < 4; ++i)
{
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ioctl (fd_video, VIDIOC_QBUF, &buf);
}
signal(SIGINT,mysignal);
while(1)
{
//开始捕获图像
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl (fd_video, VIDIOC_STREAMON, &type);


struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//取出图像数据
ioctl (fd_video, VIDIOC_DQBUF, &buf);
//在LCD屏幕上显示图像
process_image (buffers[buf.index]); //YUYV
//告知buf可以使用
ioctl (fd_video,VIDIOC_QBUF,&buf);
}
}

 

转载于:https://www.cnblogs.com/liudehao/p/5795582.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573234.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c 语言 16进制写法,C语言16进制中16怎么表示?

C语言16进制中16怎么表示&#xff1f;关注:275 答案:4 手机版解决时间 2021-02-16 21:21提问者童話被染上了傷2021-02-15 23:02C 中 16进制 16 是用10表示吗&#xff1f;8进制中逢8进一 也写作10&#xff1f;最佳答案二级知识专家X謝你的出現2021-02-15 23:4116进制 16 是用1…

关于JPA方法名创建自动查询

JPA 的根据解析方法名称自动对接口进行实现的方法能节省大量的资源&#xff0c;以下对于解析规则进行列举哈 商品实体类 package com.dionren.zhaoxie.entity.trade;import com.dionren.mvc.entity.EntityBase; import com.dionren.zhaoxie.entity.EntityShoeSku; import io.sw…

查到应看的网址

http://www.zhangxinxu.com/wordpress/2010/12/div-textarea-height-auto/ > div模拟textarea文本域轻松实现高度自适应 https://www.web-tinker.com/article/20054.html 一个很特殊的事件beforeunload(点击确定离开,取消继续) http://www.jb51.net/article/39486.htm ifr…

c语言程序前言,C语言 程序代码编写规范前言

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼一个好的程序编写规范是编写高质量程序的保证。清晰、规范的源程序不仅仅是方便阅读&#xff0c;更重要的是能够便于检查错误&#xff0c;提高调试效率&#xff0c;从而最终保证软件的质量和可维护性。说明l 本文档主要适用于刚刚开…

c语言去字母的其中三个,请问这个用c怎么做:输入一串字符,分别统计其中数字和字母的个数...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#includemain(){int acount0,bcount0,ccount0,dcount0;char a;printf("请输入一行字符:\n");a getchar();while (a !\n){switch (a){caseq:casew:casee:caser:caset:casey:caseu:casei:caseo:casep:casea:cases:cased:c…

[CF706D]Vasiliy's Multiset(异或字典树)

题目链接&#xff1a;http://codeforces.com/contest/706/problem/D 1 /*2 ━━━━━┒ギリギリ♂ eye&#xff01;3 ┓┏┓┏┓┃キリキリ♂ mind&#xff01;4 ┛┗┛┗┛┃&#xff3c;○&#xff0f;5 ┓┏┓┏┓┃ /6 ┛┗┛┗┛┃ノ)7 ┓┏┓┏┓┃8 ┛┗┛┗┛┃9 ┓┏…

信号与系统与c语言,2016年安徽医科大学生命科学学院信号系统与C语言程序设计之信号与系统复试笔试仿真模拟题...

一、计算题1&#xff0e; 已知系统的算子方程及初始条件如下&#xff0c;求其零输入响应。【答案】(l )由算子方程可以得出其系统的传输函数为由因此代入初始条件和&#xff0c;解出&#xff1a;求得特征根为&#xff1a;所以零输入响应为(2)由算子方程可以得出其系统的传输函数…

android状态栏

郭林《Android状态栏微技巧&#xff0c;带你真正理解沉浸式模式 》转载于:https://www.cnblogs.com/hsji/p/5803527.html

android 自定义属性 双向绑定,如何解决:“在使用自定义视图实现双向数据绑定时,找不到属性’android:text’”的getter?...

我经历了许多类似的问题,但没有一个答案似乎解决了我的问题.我实现了一个自定义EditText,我希望与双向数据绑定兼容.问题是,每次我尝试编译时都会收到错误&#xff1a;Error:java.lang.IllegalStateException: Failed to analyze: android.databinding.tool.util.LoggedErrorEx…

linux用grep查找包含两个关键字的命令

linux用grep查找包含两个关键字的命令 http://zhidao.baidu.com/link?urlVsFxeJXmU7W7hy1UH7eT6QAbUsVz9Ru2ABPuWYHWm4kBvE0ccLDwcvFi821FT5uWvgjJkNEgx80ICQaaR3HxMCr1BnLe8naTKZUwxseZ4qe http://www.linuxidc.com/Linux/2016-01/127944.htm ##查询历史记录 http://blog.sin…

Ext JS 6学习文档-第6章-高级组件

Ext JS 6学习文档-第6章-高级组件 高级组件 本章涵盖了高级组件&#xff0c;比如 tree 和 data view。它将为读者呈现一个示例项目为 图片浏览器&#xff0c;它使用 tree 和 data view 组件。以下是本章将要讨论的主题&#xff1a; TreesData views拖放图片浏览器 — 一个示例项…

android没有apk文件怎么打开方式,ios怎么打开apk文件,安卓无法打开apk文件

?  许多win7系统小伙伴在打开电脑中&#xff0c;经常会看到一些文件格式自己不知道是什么以及不知道要怎么打开&#xff0c;比如apk文件&#xff0c;APK是Android Package的缩写&#xff0c;即Android安装包&#xff0c;几乎所有的安卓应用程序都是这种格式&#xff0c;那么…

android屏幕基础知识

首先&#xff0c;先来上一张图&#xff0c;看看android屏幕分辨率的占比情况 什么是dp&#xff0c;dip&#xff0c;dpi&#xff0c;sp、px ?之间的关系是什么&#xff1f; px&#xff1a;构成图像的最小单位 dp/dip&#xff1a;密度无关像素 以160dpi为基准 1dp1px sp&#xf…

Android模糊查询excel文件内容,【excel】模糊查询关键字

求Excel大神指点迷津。如何批量模糊查找和替换。例如&#xff0c;A1&#xff1a;A100,每个单元格有一段文字。B1:B200,每个单元格有一个关键词。我的目的是在A1:A100中查找包含B1的单元格&#xff0c;找到后把这个单元格内容换成B1的内容。然后查找B2替换B2...一直到B200解决办…

日语的学习

1. 50 音图与假名 日本&#xff1a;に&#xff08;ni&#xff09;は&#xff08;ho&#xff09;ん&#xff08;nn&#xff09;谢谢&#xff1a;あ&#xff08;a&#xff09;り&#xff08;ri&#xff09;が&#xff08;ga&#xff09;と&#xff08;to&#xff09;う&#xff0…

android 翻转切换view,Android ViewFlipper翻转视图使用详解

简介ViewFlipper是Android自带的一个多页面管理控件且可以自动播放&#xff01;它和ViewPager有所不同&#xff0c;ViewPager继承自ViewGroup&#xff0c;是一页一页的&#xff0c;可以带动画效果&#xff0c;可以兼容低版本&#xff1b;而ViewFlipper继承ViewAnimator&#xf…

拓扑学初步

拓扑&#xff08;Topology&#xff09;原本是一个数学概念&#xff0c;描述的是几何图形或空间在连续改变形状后还能保持不变的性质。2016 年度的诺贝尔物理学奖颁给的三位物理学家&#xff0c;正是凭借他们在物理学中引入了拓扑的概念。0. 基本概念 & 定义 同胚&#xff1…

android 京东白条支付,京东网银钱包安卓版上线:整合京东白条和小金库

京东金融网银钱包移动版上线 京东账号可直接登录【TechWeb报道】4月1日消息&#xff0c;京东金融今日宣布网银钱包客户端正式在Android平台上线。网银钱包客户端近期也将登录苹果应用商店&#xff0c;用户使用京东账号将可以直接登录。据悉&#xff0c;网银钱包客户端是京东金融…

android 缓存头像,android 实现类似微信缓存和即时更新好友头像示例

引言使用微信时我们会发现&#xff0c;首次进入微信的好友列表时&#xff0c;会加载好友头像&#xff0c;但是再次进入时&#xff0c;就不用重新加载了&#xff0c;而且其他页面都不用重新加载&#xff0c;说明微信的好友头像是缓存在本地的&#xff0c;然后好友修改头像后&…

JQuery 之 跳出循环

1、跳出each循环  return false 跳出循环 return true 进入下一个循环2、跳出for循环  break;直接退出for这个循环。这个循环将不再被执行&#xff01;  continue;直接跳出本次for循环。下次继续执行。  return语句就是用于指定函数返回的值。即使函数主体中还有其他语…