本文承接自前篇博客将Cocos2d-x的libcurl单独打包到Android
在此基础上,又进行了进一步的使用:
1)增加libcurl异步方法
2)实现Android异步任务
下面直接上代码:
1】jni之first.c:first.h无变化,first.c添加如下代码,切记C变量必须把声明方法函数的开始
/*
* Copyright (C) 2009 The Android Open Source Project
*
* 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 "first.h"
int first(int x, int y)
{
return x + y;
}
#define MULTI_CURL_NUM 3
char* URL = "http://www.baidu.com";
char* PROXY = "";
unsigned int TIMEOUT = 10000;
char* urlA[3] = {"http://www.baidu.com","http://www.cocoachina.com/bbs/read.php?tid=228963","http://www.cnblogs.com/zhaoyl/p/4001151.html"};
//异步方法获取返回数据
size_t curl_writer(void* buffer,size_t size,size_t count,void* stream)
{
// std::string* pStream = static_cast<std::string*>(stream);
// (*pStream).append((char*)buffer,size * count);
// log("pStream=%s",pStream);
return size*count;
}
//增加URL请求,异步实质上是多个同步请求的组合
CURL* curl_easy_handler(const char* sUrl,const char* sProxy,char* sRsp,unsigned int uiTimeout)
{
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL,sUrl);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL,1);
if(uiTimeout > 0)
{
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS,uiTimeout);
}
if(sProxy[0]!='\0')
{
curl_easy_setopt(curl, CURLOPT_PROXY,sProxy);
}
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,curl_writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA,&sRsp);
// log("curl_write = %lu",sizeof(sRsp));
return curl;
}
//select方法,选择当前可读写的文件
int curl_multi_select(CURLM* curl_m)
{
int ret = 0;
int idx1 = 0;
struct timeval timeout_tv;
fd_set fd_read;
fd_set fd_write;
fd_set fd_except;
int max_fd = -1;
int ret_code;
FD_ZERO(&fd_read);
FD_ZERO(&fd_write);
FD_ZERO(&fd_except);
timeout_tv.tv_sec = 60;
timeout_tv.tv_usec = 0;
curl_multi_fdset(curl_m, &fd_read, &fd_write, &fd_except, &max_fd);
// log("max_fd = %d",max_fd);
if(max_fd == -1)
{
return -1;
}
// ret_code = ::select(max_fd+1, &fd_read, &fd_write, &fd_except, &timeout_tv);
ret_code = select(max_fd+1, &fd_read, &fd_write, &fd_except, &timeout_tv);
// log("ret_code = %d",ret_code);
switch (ret_code) {
case -1:
ret = -1;
break;
case 0:
default:
ret = 0;
break;
}
return ret;
}
//异步方法入口
int curl_multi_demo(int num,CURLcode* result)
{
int idx;
static int count = 0;
CURLM* curl_m = curl_multi_init();
char* RspArray[num];
int running_handles = 0;
int msgs_left;
CURLMsg* msg;
// int s[num];
CURL* CurlArray[num];
for(idx = 0; idx < num; ++idx)
{
CurlArray[idx] = NULL;
CurlArray[idx] = curl_easy_handler(URL, PROXY, RspArray[idx], TIMEOUT);
if(CurlArray[idx] == NULL)
{
return -1;
}
curl_multi_add_handle(curl_m, CurlArray[idx]);
}
// log("running_handles out up = %d",running_handles);
while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles))
{
// log("running_handles = %d",running_handles);
}
// log("running_handles out = %d",running_handles);
while(running_handles)
{
if(-1 == curl_multi_select(curl_m))
{
// log( "select error" );
break;
}else{
while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles))
{
// log("select:%d ",running_handles);
}
}
// log("select: %d",running_handles);
}
while ((msg = curl_multi_info_read(curl_m, &msgs_left)))
{
if(CURLMSG_DONE == msg->msg);
{
int idx;
for(idx = 0; idx < num; ++idx)
{
if(msg->easy_handle == CurlArray[idx]) break;
}
if(idx == num)
{
// log("curl not found");
}else{
// log("curl [%d] completed with status: %d",idx,msg->data.result);
// log("rsp: %s",RspArray[idx]);
result[count++] = msg->data.result;//将求求结果状态传入result数组,该数组是指针
}
}
}
for(idx = 0; idx < num; ++idx)
{
curl_multi_remove_handle(curl_m, CurlArray[idx]);
}
for(idx = 0; idx < num; ++idx)
{
curl_easy_cleanup(CurlArray[idx]);
}
curl_multi_cleanup(curl_m);
return 0;
}
//同步方法入口
int curl_easy_demo(int num)
{
int idx = 0;
char* RspArray[num];
for(idx = 0; idx < num; ++idx)
{
CURL* curl = curl_easy_handler(URL, PROXY, RspArray[idx], TIMEOUT);
CURLcode code = curl_easy_perform(curl);
// log("curl [%d] completed with status:%d",idx,code);
curl_easy_cleanup(curl);
}
return 0;
}
2】jni之second.c
#include "first.h"
#include <jni.h>
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
//extern "C"
jint
Java_com_example_libdemo_MainActivity_add( JNIEnv* env,
jobject this,
jint x,
jint y)
{
/* //libcurl同步方法案例
CURL* curl;
CURLcode res;
curl = curl_easy_init();
if(NULL == curl)
{
return first(1,999);
}
curl_easy_setopt(curl, CURLOPT_URL,"http://www.baidu.com");
curl_easy_setopt(curl, CURLOPT_READFUNCTION,NULL);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL,1);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT,20);
curl_easy_setopt(curl, CURLOPT_TIMEOUT,20);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
*/
//libcurl异步方法案例
CURLcode result[3];
int sum;
gettimeofday(&begin_tv, NULL);
curl_multi_demo(3,result);
gettimeofday(&end_tv, NULL);
long eclapsed = (end_tv.tv_sec - begin_tv.tv_sec)*1000 + (end_tv.tv_usec - begin_tv.tv_usec) / 1000;
// log("eclapsed time: %ld ms",eclapsed);
sum = (int)result[0] + (int)result[1];
return first(sum,(int)result[2]);
}3】src之MainActivity.java
package com.example.libdemo;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
private Button button;
private TextView tv;
private TextView textView;
private ProgressBar progressBar;
private static final String TAG = "ASYNC_TASK";
private int x = 123;
private int y = 456;
private MyTask mTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.loadLibrary("twolib-second");
tv = (TextView)findViewById(R.id.textView2);
button = (Button) this.findViewById(R.id.button1);
textView = (TextView) findViewById(R.id.textView3);
this.button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
mTask = new MyTask();
mTask.execute("test");
}
});
}
public native int add(int x,int y);
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
//异步任务
private class MyTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
// super.onPreExecute();
Log.i(TAG, "onPreExecute() called");
textView.setText("Loading...");
}
//处理耗时任务
@Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
try {
int z = add(x, y);
tv = (TextView) findViewById(R.id.textView2);
tv.setText( "The sum dskdshd of " + x + " and " + y + " is " + z );
return new String("test");
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
// super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
textView.setText("loading..." + "%");
}
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
// super.onPostExecute(result);
textView.setTag(result);
}
}
}1、关于代码中用到的UI,读者自行拖到layout中,此处不在详细介绍
2、Android中目前比较常用的为handle机制,由于作者Android水平有限,选择了最简单的异步任务实现。有兴趣的读者,自行实现其他方法
3、运行截图:点击最左侧按钮后,返回下面的结果,如果是0表面程序中的3个URL请求成功,如果返回其他则失败,curl返回错误码见上面博客。
原文地址:http://blog.csdn.net/yuxikuo_1/article/details/41926065