Android NDK开发初步探索
来源:互联网 发布:互联网公司数据分析 编辑:程序博客网 时间:2024/05/22 00:50
Android NDK开发初步探索
在了解Anroid安全、权限与Linux进程的安全、权限之间的关联关系的时候突发奇想:是否使用socket连接来作为http客户端,以之请求网络就不需要在AndroidManifest.xml中申请Internet访问权限。为验证该想,遂作如下试验:
- 试验结果:NDK下无论是调用本地方法进行socket连接,还是调用本地方法读写SD卡上的文件,均需要在AndroidManifest.xml中作相应的权限请求配置;
- 试验环境:AndroidStudio2.2.3 + android-ndk-r13b + Gradle2.14.1
- 比对环境:Ubuntu14(win10虚拟机)+ codeblock13.12
测试步骤:
- 在codeblock中编写可执行的socket实现的http客户端文件httpGet.cpp文件;
- 在AndroidStudio中新建NDK项目:勾选
include C++ Support
,使用frtti和fexceptions; - 将httpGet.cpp代码移植到Android项目的cpp文件中,建立本地方法;
- 对比,分别测试在AndroidManifext.xml文件中配置Internet访问权限和不配置的运行结果。
核心代码:
1.httpGet.cpp
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h> #include<arpa/inet.h> #include<netdb.h> #include<stdlib.h> #include<netinet/in.h> #define BUFSIZE 0xF000void geturl(char* url){ int cfd; struct sockaddr_in cadd; struct hostent* pURL = NULL; char myurl[BUFSIZE]; char* pHost = 0; char host[BUFSIZE], GET[BUFSIZE]; char request[BUFSIZE]; static char text[BUFSIZE]; int i, j; //分离主机中的主机地址和相对路径 memset(myurl, 0, BUFSIZE); memset(host, 0, BUFSIZE); strcpy(myurl, url); for(pHost = myurl; *pHost != '/' && *pHost != '\0'; ++pHost); //获取相对路径保存到GET中 memset(GET, 0, BUFSIZE); if((int)(pHost - myurl) == strlen(myurl)) { strcpy(GET, "/");//即url中没有给出相对路径,需要自己手动的在url尾部加上/ } else { trcpy(GET, pHost); //地址段pHost到strlen(myurl)保存的是相对路径 } //将主机信息保存到host中 //此处将它置0, 即它只想的内容里面已经分离出了相对路径,剩下的为host信息(从myurl到pHost地址段存放的是HOST) *pHost = '\0'; strcpy(host, myurl); //设置socket参数 if(-1 == (cfd = socket(AF_INET, SOCK_STREAM, 0))) { printf("create socket failed of client!\n"); exit(-1); } printf("create socket success of client!\n"); pURL = gethostbyname(host); //讲上面获得的主机信息通过域名解析函数获得域名信息 //设置IP地址结构 bzero(&cadd, sizeof(struct sockaddr_in)); cadd.sin_family = AF_INET; cadd.sin_addr.s_addr = *((unsigned long*)pURL->h_addr_list[0]); cadd.sin_port = htons(80); //向WEB服务器发送URL信息 memset(request, 0, BUFSIZE); strcat(request, "GET "); strcat(request, GET); strcat(request," HTTP/1.1\r\n"); //设置http请求行的信息 strcat(request, "Accept: text/html, image/jpeg, image/png, vedio/x-mng, text/*, image/*, */*\r\n"); strcat(request, "Accept-Language: zh-cn\r\n"); strcat(request, "Accept-Encoding: x-gzip, x-deflate, gzip, deflat\r\n"); strcat(request, "Accpet-charset: utf-8, utf-8; q=0.5, *; q=0.5\r\n"); strcat(request, "HOST: "); strcat(request, host); strcat(request, "\r\n"); //strcat(request, "Content-Type: text/html\r\n"); //strcat(request, "Content-Length: 1024\r\n"); strcat(request, "Connection: Keep-Alive\r\n"); strcat(request, "Cache-Control: no-cache\r\n\r\n");//设置http请求头 //链接服务器 int cc; if(-1 == (cc = connect(cfd, (struct sockaddr*)&cadd, (socklen_t)sizeof(cadd)))) { printf("connect failed of client!\n"); exit(1); } printf("connect success!\n"); //向服务器发送url请求的request、 int cs; if(-1 == (cs = send(cfd, request, strlen(request), 0))) { printf("send request failed!\n"); exit(1); } printf("send reqeust success, and send length = %d\n", cs); //将http请求信息写入文件hPage int chfd; if(-1 == (chfd = open("hPage", O_RDWR|O_CREAT|O_TRUNC, 0766))) { printf("open or create hPage failed!\n"); exit(1); } printf("open or create hPage success!\n"); int chf; if(-1 == (chf = write(chfd, request, strlen(request)))) { printf("write to hPage failed!\n"); exit(1); } else if(chf == 0) { printf("the length of written to hPage is 0 byte!\n"); } else { printf("the length of written to hPage is %d bytes!\n", chf); } //客户端接受服务器的返回信息 memset(text, 0, BUFSIZE); int cr; if(-1 == (cr = recv(cfd, text, BUFSIZE, 0))) { printf("receive failed!\n"); exit(1); } else { printf("receive success!\n"); int cofd; for(;;) { //创建一个文件mPage用于保存网页的主要信息 if(-1 == (cofd = open("mPage.html", O_RDWR|O_CREAT|O_TRUNC, 0766))) { perror("open or create mPage failed!\n"); exit(1); } //将网页的主要内容text写入mPage中 nt cf; if(-1 == (cf = write(cofd, text, strlen(text)))) { perror("write to mPage failed!\n"); break; } else if(cf == 0) { printf("the length of written to mPage is 0 byte!\n"); break; } else { printf("the length of written to mPage is %d bytes", cf); break; } //将text清空,方便接受其他网页信息 memset(text, 0, BUFSIZE); //关闭文件描述符 //close(chfd); close(cofd); } } //free(BUFSIZE); close(cfd); }
2.native-lib.cpp(AndroidStudio jni)
#include"httpGet.cpp" #define OK 1 #define ERROR 0 ...extern "C"jintJava_com_xxx_ndk_MainActivity_urlFromJNI(JNIEnv* env, jobject thiz){ char address[] = "www.baidu.com"; char* pAdd = address; return geturl(pAdd);}
说明:linux下的httpGet.cpp移植到AndroidStudio下的native-lib.cpp文件需要作一些调整:1.需要修改open()方法里文件的创建位置(/sdcard/xxx.xx); 2.为方便起见,本地方法调用返回值为int类型,对于exit()方法,需要替换为return OK或者return ERROR。
编译.so文件
1.编译环境:Ubuntu14 + gcc;
2.编译步骤:
- 首先, 编译mylib.c:
$gcc -c -fPIC -o mylib.o mylib.c
-c表示只编译(compile),而不是链接。-o选项用于说明输出(output)文件名。gcc将生成一个目标(object)文件mylib.o。注意-fPIC选项。PIC指Position Independent Code。共享库要求有此选项,以便实现动态链接(dynamic linking)。- 生成共享库:
$gcc -shared -o mylib.so mylib.o
库文件以lib开始。共享库文件以.so为后缀。-shared表示生成一个共享库。注意,由于该文件并不包含main()函数,因此,生词.so文件必须分两步,先编译,后链接。
0 0
- Android NDK开发初步探索
- Android NDK开发初步
- Android NDK开发初步
- android 开发之画布初步探索
- Android NDK Opengl es开发初步接触
- 初步探索NFC开发
- android艺术开发探索之jni,NDK开发
- android NDK 初步知识
- android ndk初步1
- Android NDK初步涉猎
- Android基于SDK,NDK开发视频通话软件探索
- Android开发艺术探索_JNI和NDK编程(十四)
- iOS开发 HealthKit初步探索
- iOS开发 HomeKit初步探索
- Android NDK探索连载-1 NDK是什么
- android-自定义View初步探索
- Android NDK开发配置NDK
- Android NDK : NDK开发概要
- [勇者闯LeetCode] 13. Roman to Integer
- 转载:应该考虑进行何种测试
- 抢红包
- Project Lombok
- HDU 1213 how many tables
- Android NDK开发初步探索
- Win8安装Rational Rose教程
- centos7 yum安装redis3.2.8
- https 证书
- 蓝桥杯 ALGO-145 算法训练 4-1打印下述图形
- RxJava入门(一)
- 蓝桥杯 ALGO-143 算法训练 字符串变换
- RabbitMQ官网教程1——Hello World
- windows下搭建ffmpeg+nginx+rtmp-module搭建实时视频环境