android JNI使用curl库进行文件下载和http请求

来源:互联网 发布:粤11选5遗漏数据查询 编辑:程序博客网 时间:2024/05/16 19:27

1.CURL几个基本函数的说明:


1) curl_global_init();这个函数是进行curl库的初始化,这个函数与curl_global_cleanup配套使用,当调用了一次后,在没有调用curl_global_cleanup之前不要再次调用。


2) curl_global_cleanup();curl_global_init进行的一些操作进行清理。


3) CURL *curl_easy_init( );用于产生一个CURL对象用于进行网络相关的操作,此对象类似于文件指针,不使用它的时候需要进行清理释放。


4) void curl_easy_cleanup(CURL *curl);用于对CURL*的清理释放。


5) void curl_easy_reset(CURL *handle );重新初始化CURL句柄的选项设置。


6) CURLcode curl_easy_getinfo(CURL *curl,CURLINFO info, ... );查询CRUL会话的内部信息,具体说明请参考curl自带文档。


7.) CURLcode curl_easy_setopt(CURL *curl,CURLoption option, ...);此函数是curl中最核心的函数,基本所有的网络操作的设定都需要它去进行,他的参数等也非常的复杂,建议自行搜索这个函数相关的内容。


8) CURLcode curl_easy_perform(CURL *curl);针对curl_easy_setopt设置好的内容参数进行相应的网络操作。


 

2.CURL库在Android JNI中的具体使用(HTTP请求和文件下载):

创建android工程以后需要在AndroidManifest.xml文件中添加使用权限:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <uses-permission android:name="android.permission.INTERNET" />  
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
  3. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  


使用curl封装的一个简单的http请求类HttpPostModule

HttpPostModule.h

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #ifndef HTTP_POST_MODULE_H  
  2. #define HTTP_POST_MODULE_H  
  3.   
  4. #include <string>  
  5. #include "curl/curl.h"  
  6. #include <iostream>  
  7. using namespace std;  
  8. typedef size_t (*WriteFunc)(char *ptr, size_t size, size_t nmemb,  
  9.         void *userdata);  
  10. /* 
  11.  * 发送http请求 
  12.  * 使用开源curl库进行相应的实现 
  13.  * */  
  14. class HttpPostModule  
  15. {  
  16. public:  
  17.     HttpPostModule();  
  18.     virtual ~HttpPostModule();  
  19.   
  20.     static void Init();  
  21.     static void Cleanup();  
  22. public:  
  23.     //设置超时  
  24.     bool SetTimeOut(unsigned short usSecond);  
  25.   
  26.     //设置 请求的url  
  27.     bool SetURL(const string& strURL);  
  28.     //设置http头  
  29.     bool SetHttpHead(const string& strHttpHead);  
  30.     //设置返回数据回调函数  
  31.     bool SetWriteFunction(WriteFunc pFunc);  
  32.     //发送http请求  
  33.     int SendPostRequest(void);  
  34.   
  35. private:  
  36.     CURL* m_pCurl;  
  37. public:  
  38.   
  39. };  
  40. //NetModule end  
  41. #endif  


HttpPostModule.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "HttpPostModule.h"  
  2.   
  3. HttpPostModule::HttpPostModule() :  
  4.         m_pCurl(NULL)  
  5. {  
  6.     m_pCurl = curl_easy_init();  
  7.     curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1L);  
  8. }  
  9. HttpPostModule::~HttpPostModule()  
  10. {  
  11.     curl_easy_cleanup(m_pCurl);  
  12.     m_pCurl = NULL;  
  13. }  
  14. void HttpPostModule::Init()  
  15. {  
  16.     curl_global_init(CURL_GLOBAL_ALL);  
  17.   
  18. }  
  19. void HttpPostModule::Cleanup()  
  20. {  
  21.     curl_global_cleanup();  
  22.   
  23. }  
  24. bool HttpPostModule::SetTimeOut(unsigned short usSecond)  
  25. {  
  26.     if (m_pCurl == NULL)  
  27.         return false;  
  28.     int nRet = curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, usSecond);  
  29.     if (nRet == CURLE_OK)  
  30.         return true;  
  31.     else  
  32.     {  
  33.         cout << "SetTimeOut ERROR code =" << nRet << endl;  
  34.         return false;  
  35.     }  
  36. }  
  37. bool HttpPostModule::SetURL(const string& strURL)  
  38. {  
  39.     if (m_pCurl == NULL)  
  40.         return false;  
  41.     int nRet = curl_easy_setopt(m_pCurl, CURLOPT_URL, strURL.c_str());  
  42.     if (nRet == CURLE_OK)  
  43.         return true;  
  44.     else  
  45.     {  
  46.         cout << "SetURL ERROR code =" << nRet << endl;  
  47.         return false;  
  48.     }  
  49. }  
  50. bool HttpPostModule::SetHttpHead(const string& strHttpHead)  
  51. {  
  52.     if (m_pCurl == NULL)  
  53.         return false;  
  54.     curl_slist *plist = curl_slist_append(NULL, strHttpHead.c_str());  
  55.     int nRet = curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, plist);  
  56.     if (nRet == CURLE_OK)  
  57.         return true;  
  58.     else  
  59.     {  
  60.         cout << "SetHttpHead ERROR code =" << nRet << endl;  
  61.         return false;  
  62.     }  
  63. }  
  64. bool HttpPostModule::SetWriteFunction(WriteFunc pFunc)  
  65. {  
  66.     if (m_pCurl == NULL)  
  67.         return false;  
  68.     curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, NULL);  
  69.     int nRet = curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, pFunc);  
  70.     if (nRet == CURLE_OK)  
  71.         return true;  
  72.     else  
  73.     {  
  74.         cout << "SetCallbackFunc ERROR code =" << nRet << endl;  
  75.         return false;  
  76.     }  
  77. }  
  78.   
  79. int HttpPostModule::SendPostRequest(void)  
  80. {  
  81.     if (m_pCurl == NULL)  
  82.         return -1;  
  83.     int nRet = curl_easy_perform(m_pCurl);  
  84.     if (nRet == CURLE_OK)  
  85.         return 0;  
  86.     else  
  87.     {  
  88.         return nRet;  
  89.     }  
  90. }  


使用curl封装的一个简单的文件下载类DownloadModule,文件下载支持断点续传。

DownloadModule.h

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #ifndef DOWNLOAD_MODULE_H  
  2. #define DOWNLOAD_MODULE_H  
  3. #include <string>  
  4. #include "curl/curl.h"  
  5. using namespace std;  
  6.   
  7. class DownLoadModule  
  8. {  
  9. public:  
  10.     DownLoadModule();  
  11.     virtual ~DownLoadModule();  
  12.     static void Init();  
  13.     static void Cleanup();  
  14.   
  15. public:  
  16.     static size_t DownLoadPackage(void *ptr, size_t size, size_t nmemb,  
  17.             void *userdata);  
  18. private:  
  19.     long GetLocalFileLenth(const string& strFileName);  
  20. public:  
  21.     /* 
  22.      * param1 string 下载文件的url地址。 
  23.      * param2 string 下载到的路径  注意要以/结尾 
  24.      * param3 string 下载后的文件名 
  25.      * return 0 下载成功/-1代表初始化失败/其他为curl返回错误码 
  26.      * */  
  27.     int DownLoad(std::string strUrl, std::string strStoragePath,  
  28.             std::string strFileName);  
  29. private:  
  30.     CURL *m_pCurl;  
  31. };  
  32.   
  33. #endif  

DownloadModule.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <sys/stat.h>  
  2. #include <unistd.h>  
  3. #include "DownloadModule.h"  
  4.   
  5.   
  6. DownLoadModule::DownLoadModule() :  
  7.         m_pCurl(NULL)  
  8. {  
  9.     m_pCurl = curl_easy_init();  
  10. }  
  11. DownLoadModule::~DownLoadModule()  
  12. {  
  13.     curl_easy_cleanup(m_pCurl);  
  14.     m_pCurl = NULL;  
  15. }  
  16. void DownLoadModule::Init()  
  17. {  
  18.     curl_global_init(CURL_GLOBAL_ALL);  
  19.   
  20. }  
  21. void DownLoadModule::Cleanup()  
  22. {  
  23.     curl_global_cleanup();  
  24.   
  25. }  
  26.   
  27. size_t DownLoadModule::DownLoadPackage(void *ptr, size_t size, size_t nmemb,  
  28.         void *userdata)  
  29. {  
  30.     FILE *fp = (FILE*) userdata;  
  31.     size_t written = fwrite(ptr, size, nmemb, fp);  
  32.     return written;  
  33. }  
  34.   
  35. long DownLoadModule::GetLocalFileLenth(const string& strFileName)  
  36. {  
  37.     unsigned long filesize = 0;  
  38.     struct stat statbuff;  
  39.     if (stat(strFileName.c_str(), &statbuff) < 0)  
  40.     {  
  41.         return filesize;  
  42.     }  
  43.     else  
  44.     {  
  45.         filesize = statbuff.st_size;  
  46.     }  
  47.     return filesize;  
  48.   
  49. }  
  50. int DownLoadModule::DownLoad(std::string strUrl, std::string strStoragePath,  
  51.         std::string strFileName)  
  52. {  
  53.     Init();  
  54.     // Create a file to save package.  
  55.     if (0 != access(strStoragePath.c_str(), F_OK))  
  56.         mkdir(strStoragePath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);  
  57.     ;  
  58.     const string outFileName = strStoragePath + "/" + strFileName;  
  59.     //================断点续载===================  
  60.     long localLen = GetLocalFileLenth(outFileName.c_str());  
  61.     FILE *fp = fopen(outFileName.c_str(), "a+b");  
  62.     if (!fp)  
  63.     {  
  64.         return -1;  
  65.     }  
  66.     fseek(fp, 0, SEEK_END);  
  67.   
  68.     // Download pacakge  
  69.     CURLcode res;  
  70.     curl_easy_setopt(m_pCurl, CURLOPT_URL, strUrl.c_str());  
  71.     curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, DownLoadPackage);  
  72.     curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, fp);  
  73.     curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, true);  
  74.     //curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, 30);  
  75.     curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1L);  
  76.     curl_easy_setopt(m_pCurl, CURLOPT_HEADER, 0L);  
  77.     curl_easy_setopt(m_pCurl, CURLOPT_NOBODY, 0L);  
  78.     curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L);  
  79.     curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM, localLen);  
  80.   
  81.     res = curl_easy_perform(m_pCurl);  
  82.     Cleanup();  
  83.   
  84.     if (res != 0)  
  85.     {  
  86.         fclose(fp);  
  87.         return res;  
  88.     }  
  89.     fclose(fp);  
  90.     return 0;  
  91. }  



具体功能实现:下载一个APK文件和发送一个百度地图API的Http请求。


Java端代码 MainActivity.class

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.example.curltest;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.util.Log;  
  6. import android.view.View;  
  7. import android.view.View.OnClickListener;  
  8. import android.widget.Button;  
  9.   
  10. public class MainActivity extends Activity {  
  11.     static {  
  12.         System.loadLibrary("curl");  
  13.         System.loadLibrary("curlTest");  
  14.     }  
  15.     public native void Init();  
  16.     public native void Cleanup();  
  17.     public native void TestDownload();  
  18.     public native void TestHttpPost();  
  19.     private final String TAG = "curlTest";  
  20.     private void postDispose(String Data)  
  21.     {  
  22.         Log.i(TAG, Data);  
  23.     }  
  24.     @Override  
  25.     protected void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         setContentView(R.layout.activity_main);  
  28.         Init();  
  29.         Button btnPost =  (Button) findViewById(R.id.main_post);  
  30.         Button btnDownload =  (Button) findViewById(R.id.main_download);  
  31.         btnPost.setOnClickListener(new OnClickListener() {  
  32.               
  33.             @Override  
  34.             public void onClick(View v) {  
  35.                 // TODO Auto-generated method stub  
  36.                 TestHttpPost();  
  37.             }  
  38.         });  
  39.         btnDownload.setOnClickListener(new OnClickListener() {  
  40.               
  41.             @Override  
  42.             public void onClick(View v) {  
  43.                 // TODO Auto-generated method stub  
  44.                 TestDownload();  
  45.             }  
  46.         });  
  47.   
  48.     }  
  49.     @Override  
  50.     protected void onDestroy() {  
  51.         // TODO Auto-generated method stub  
  52.         super.onDestroy();  
  53.         Cleanup();  
  54.     }  
  55. }  


JNI代码Main.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <jni.h>  
  2. #include "DownloadModule.h"  
  3. #include "HttpPostModule.h"  
  4. #include "JNIUtil.h"  
  5. extern "C"  
  6. {  
  7. jobject g_objAc = NULL;  
  8. void Java_com_example_curltest_MainActivity_TestDownload(JNIEnv* env,  
  9.         jobject obj)  
  10. {  
  11.     DownLoadModule download;  
  12.     const char* url =  
  13.             "http://s3.amazonaws.com/hum9-lwg8-qa2w/PsiphonAndroid.apk";  
  14.     int nRet = download.DownLoad(url, "/sdcard/Download""PsiphonAndroid.apk");  
  15.     if (nRet == 0)  
  16.         LOGI("download success!");  
  17.     else  
  18.         LOGE("download error code:%d", nRet);  
  19. }  
  20. size_t PostDispose(char *buffer, size_t size, size_t nmemb, void *userdata)  
  21. {  
  22.     JNIUtil util;  
  23.     jobject jdata = util.String2Jstring(buffer);  
  24.     JNIEnv* env = util.GetJNIEnv();  
  25.     jclass cMainActivity = env->GetObjectClass(g_objAc);  
  26.     jmethodID methodPostDispose = env->GetMethodID(cMainActivity, "postDispose",  
  27.             "(Ljava/lang/String;)V");  
  28.     env->CallVoidMethod(g_objAc, methodPostDispose, jdata);  
  29.     return nmemb;  
  30. }  
  31. void Java_com_example_curltest_MainActivity_TestHttpPost(JNIEnv* env,  
  32.         jobject obj)  
  33. {  
  34.     HttpPostModule post;  
  35.     post.SetTimeOut(60);  
  36.     post.SetHttpHead("Content-Type:application/json;charset=UTF-8");  
  37.     post.SetWriteFunction(PostDispose);  
  38.     post.SetURL("http://api.map.baidu.com/place/v2/suggestion?query=tiananmen&region=131&output=json&ak=fTF5Wt01MNLs7ci9G9G6X76d");  
  39.     int nRet = post.SendPostRequest();  
  40.     if (nRet == 0)  
  41.         LOGI("post success!");  
  42.     else  
  43.         LOGE("post error code:%d", nRet);  
  44. }  
  45. void Java_com_example_curltest_MainActivity_Init(JNIEnv* env, jobject obj)  
  46. {  
  47.     HttpPostModule::Init();  
  48.     JavaVM* vm;  
  49.     env->GetJavaVM(&vm);  
  50.     JNIUtil::Init(env);  
  51.     g_objAc = env->NewGlobalRef(obj);  
  52. }  
  53. void Java_com_example_curltest_MainActivity_Cleanup(JNIEnv* env, jobject obj)  
  54. {  
  55.     HttpPostModule::Cleanup();  
  56.     env->DeleteGlobalRef(g_objAc);  
  57.     g_objAc = NULL;  
  58.     JNIUtil::CleanUp(env);  
  59. }  
  60. }  

里面的JNIUtil工具类在我的另一篇博客有详细说明。

http://blog.csdn.net/csdn49532/article/details/50635338

整个项目工程源码:

http://download.csdn.net/detail/csdn49532/9434453


0 0
原创粉丝点击