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


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文件中添加使用权限:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />


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

HttpPostModule.h

#ifndef HTTP_POST_MODULE_H
#define	HTTP_POST_MODULE_H

#include <string>
#include "curl/curl.h"
#include <iostream>
using namespace std;
typedef size_t (*WriteFunc)(char *ptr, size_t size, size_t nmemb,
		void *userdata);
/*
 * 发送http请求
 * 使用开源curl库进行相应的实现
 * */
class HttpPostModule
{
public:
	HttpPostModule();
	virtual ~HttpPostModule();

	static void Init();
	static void Cleanup();
public:
	//设置超时
	bool SetTimeOut(unsigned short usSecond);

	//设置 请求的url
	bool SetURL(const string& strURL);
	//设置http头
	bool SetHttpHead(const string& strHttpHead);
	//设置返回数据回调函数
	bool SetWriteFunction(WriteFunc pFunc);
	//发送http请求
	int SendPostRequest(void);

private:
	CURL* m_pCurl;
public:

};
//NetModule end
#endif


HttpPostModule.cpp

#include "HttpPostModule.h"

HttpPostModule::HttpPostModule() :
		m_pCurl(NULL)
{
	m_pCurl = curl_easy_init();
	curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1L);
}
HttpPostModule::~HttpPostModule()
{
	curl_easy_cleanup(m_pCurl);
	m_pCurl = NULL;
}
void HttpPostModule::Init()
{
	curl_global_init(CURL_GLOBAL_ALL);

}
void HttpPostModule::Cleanup()
{
	curl_global_cleanup();

}
bool HttpPostModule::SetTimeOut(unsigned short usSecond)
{
	if (m_pCurl == NULL)
		return false;
	int nRet = curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, usSecond);
	if (nRet == CURLE_OK)
		return true;
	else
	{
		cout << "SetTimeOut ERROR code =" << nRet << endl;
		return false;
	}
}
bool HttpPostModule::SetURL(const string& strURL)
{
	if (m_pCurl == NULL)
		return false;
	int nRet = curl_easy_setopt(m_pCurl, CURLOPT_URL, strURL.c_str());
	if (nRet == CURLE_OK)
		return true;
	else
	{
		cout << "SetURL ERROR code =" << nRet << endl;
		return false;
	}
}
bool HttpPostModule::SetHttpHead(const string& strHttpHead)
{
	if (m_pCurl == NULL)
		return false;
	curl_slist *plist = curl_slist_append(NULL, strHttpHead.c_str());
	int nRet = curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, plist);
	if (nRet == CURLE_OK)
		return true;
	else
	{
		cout << "SetHttpHead ERROR code =" << nRet << endl;
		return false;
	}
}
bool HttpPostModule::SetWriteFunction(WriteFunc pFunc)
{
	if (m_pCurl == NULL)
		return false;
	curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, NULL);
	int nRet = curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, pFunc);
	if (nRet == CURLE_OK)
		return true;
	else
	{
		cout << "SetCallbackFunc ERROR code =" << nRet << endl;
		return false;
	}
}

int HttpPostModule::SendPostRequest(void)
{
	if (m_pCurl == NULL)
		return -1;
	int nRet = curl_easy_perform(m_pCurl);
	if (nRet == CURLE_OK)
		return 0;
	else
	{
		return nRet;
	}
}


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

DownloadModule.h

#ifndef DOWNLOAD_MODULE_H
#define DOWNLOAD_MODULE_H
#include <string>
#include "curl/curl.h"
using namespace std;

class DownLoadModule
{
public:
	DownLoadModule();
	virtual ~DownLoadModule();
	static void Init();
	static void Cleanup();

public:
	static size_t DownLoadPackage(void *ptr, size_t size, size_t nmemb,
			void *userdata);
private:
	long GetLocalFileLenth(const string& strFileName);
public:
	/*
	 * param1 string 下载文件的url地址。
	 * param2 string 下载到的路径  注意要以/结尾
	 * param3 string 下载后的文件名
	 * return 0 下载成功/-1代表初始化失败/其他为curl返回错误码
	 * */
	int DownLoad(std::string strUrl, std::string strStoragePath,
			std::string strFileName);
private:
	CURL *m_pCurl;
};

#endif

DownloadModule.cpp

#include <sys/stat.h>
#include <unistd.h>
#include "DownloadModule.h"


DownLoadModule::DownLoadModule() :
		m_pCurl(NULL)
{
	m_pCurl = curl_easy_init();
}
DownLoadModule::~DownLoadModule()
{
	curl_easy_cleanup(m_pCurl);
	m_pCurl = NULL;
}
void DownLoadModule::Init()
{
	curl_global_init(CURL_GLOBAL_ALL);

}
void DownLoadModule::Cleanup()
{
	curl_global_cleanup();

}

size_t DownLoadModule::DownLoadPackage(void *ptr, size_t size, size_t nmemb,
		void *userdata)
{
	FILE *fp = (FILE*) userdata;
	size_t written = fwrite(ptr, size, nmemb, fp);
	return written;
}

long DownLoadModule::GetLocalFileLenth(const string& strFileName)
{
	unsigned long filesize = 0;
	struct stat statbuff;
	if (stat(strFileName.c_str(), &statbuff) < 0)
	{
		return filesize;
	}
	else
	{
		filesize = statbuff.st_size;
	}
	return filesize;

}
int DownLoadModule::DownLoad(std::string strUrl, std::string strStoragePath,
		std::string strFileName)
{
	Init();
	// Create a file to save package.
	if (0 != access(strStoragePath.c_str(), F_OK))
		mkdir(strStoragePath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
	;
	const string outFileName = strStoragePath + "/" + strFileName;
	//================断点续载===================
	long localLen = GetLocalFileLenth(outFileName.c_str());
	FILE *fp = fopen(outFileName.c_str(), "a+b");
	if (!fp)
	{
		return -1;
	}
	fseek(fp, 0, SEEK_END);

	// Download pacakge
	CURLcode res;
	curl_easy_setopt(m_pCurl, CURLOPT_URL, strUrl.c_str());
	curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, DownLoadPackage);
	curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, fp);
	curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, true);
	//curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, 30);
	curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1L);
	curl_easy_setopt(m_pCurl, CURLOPT_HEADER, 0L);
	curl_easy_setopt(m_pCurl, CURLOPT_NOBODY, 0L);
	curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L);
	curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM, localLen);

	res = curl_easy_perform(m_pCurl);
	Cleanup();

	if (res != 0)
	{
		fclose(fp);
		return res;
	}
	fclose(fp);
	return 0;
}



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


java端代码 MainActivity.class

package com.example.curltest;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {
	static {
		System.loadLibrary("curl");
		System.loadLibrary("curlTest");
	}
	public native void Init();
	public native void Cleanup();
	public native void TestDownload();
	public native void TestHttpPost();
	private final String TAG = "curlTest";
	private void postDispose(String Data)
	{
		Log.i(TAG, Data);
	}
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Init();
		Button btnPost =  (Button) findViewById(R.id.main_post);
		Button btnDownload =  (Button) findViewById(R.id.main_download);
		btnPost.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				TestHttpPost();
			}
		});
		btnDownload.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				TestDownload();
			}
		});

	}
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Cleanup();
	}
}


JNI代码Main.cpp

#include <jni.h>
#include "DownloadModule.h"
#include "HttpPostModule.h"
#include "JNIUtil.h"
extern "C"
{
jobject g_objAc = NULL;
void Java_com_example_curltest_MainActivity_TestDownload(JNIEnv* env,
		jobject obj)
{
	DownLoadModule download;
	const char* url =
			"http://s3.amazonaws.com/hum9-lwg8-qa2w/PsiphonAndroid.apk";
	int nRet = download.DownLoad(url, "/sdcard/Download", "PsiphonAndroid.apk");
	if (nRet == 0)
		LOGI("download success!");
	else
		LOGE("download error code:%d", nRet);
}
size_t PostDispose(char *buffer, size_t size, size_t nmemb, void *userdata)
{
	JNIUtil util;
	jobject jdata = util.String2Jstring(buffer);
	JNIEnv* env = util.GetJNIEnv();
	jclass cMainActivity = env->GetObjectClass(g_objAc);
	jmethodID methodPostDispose = env->GetMethodID(cMainActivity, "postDispose",
			"(Ljava/lang/String;)V");
	env->CallVoidMethod(g_objAc, methodPostDispose, jdata);
	return nmemb;
}
void Java_com_example_curltest_MainActivity_TestHttpPost(JNIEnv* env,
		jobject obj)
{
	HttpPostModule post;
	post.SetTimeOut(60);
	post.SetHttpHead("Content-Type:application/json;charset=UTF-8");
	post.SetWriteFunction(PostDispose);
	post.SetURL("http://api.map.baidu.com/place/v2/suggestion?query=tiananmen&region=131&output=json&ak=fTF5Wt01MNLs7ci9G9G6X76d");
	int nRet = post.SendPostRequest();
	if (nRet == 0)
		LOGI("post success!");
	else
		LOGE("post error code:%d", nRet);
}
void Java_com_example_curltest_MainActivity_Init(JNIEnv* env, jobject obj)
{
	HttpPostModule::Init();
	JavaVM* vm;
	env->GetJavaVM(&vm);
	JNIUtil::Init(env);
	g_objAc = env->NewGlobalRef(obj);
}
void Java_com_example_curltest_MainActivity_Cleanup(JNIEnv* env, jobject obj)
{
	HttpPostModule::Cleanup();
	env->DeleteGlobalRef(g_objAc);
	g_objAc = NULL;
	JNIUtil::CleanUp(env);
}
}

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

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

整个项目工程源码:

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






 


 


 






  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值