使用libcurl第三方库实现Android异步任务

本文承接自前篇博客将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返回错误码见上面博客。

时间: 2024-10-15 01:00:52

使用libcurl第三方库实现Android异步任务的相关文章

2017年伊始,你需要尝试的25个Android第三方库

转载请注明出处:http://blog.csdn.net/crazy1235/article/details/55805071 medium 平台有位作者总结了2017年初最棒最受欢迎的25个第三方库,相信大家都应该尝试一下. Lottie 这是一个动画库.通过Adobe After Effects做出动画效果,然后通过Bodymovin(AE的插件)导出JSON数据,然后通过该库生成原生动画效果. 在Google Play Store上可以下载demo. 该项目在Github上已经由超过800

android开发常用组件和第三方库(二)

TimLiu-Android 自己总结的Android开源项目及库. github排名 https://github.com/trending, github搜索:https://github.com/search 目录 UI UI 卫星菜单 节选器 下拉刷新 模糊效果 HUD与Toast 进度条 UI其它 动画 网络相关 响应式编程 地图 数据库 图像浏览及处理 视频音频处理 测试及调试 动态更新热更新 消息推送 完整项目 插件 出名框架 其他 好的文章 收集android上开源的酷炫的交互动

android项目引入第三方库工程出现的问题及解决方案

一.导入libar库工程 1.使用第三方库工程libary,基本上都是从github上下载,解压后里面有个libary文件夹 2.将libary导入到eclipse中,步骤如下 1)在eclipse包管理器中,右键点击import,进入 2)选择红色部分,点击next 3)将libary导入,且勾选[copy projects into workspace](必须勾选),点击完成 二.android工程引用libary 1.新建一个android工程Mytest 2.右键MyTest属性 3.操

Android中的依赖问题(五种依赖、eclipse、AS、添加第三方库、jar)

这篇文章的主题是: 依赖是什么 eclipse中的依赖 AS中的依赖(有一篇详细的文章讲得非常好,这里就不再写了http://blog.csdn.net/yy1300326388/article/details/46422939) 另外相关的话题有↓,可以自行查看: 安卓的support包的历史 AS中grandle具体的内容 怎么做一个给别人用的Jar包和lib库 (另外,贴图有点麻烦,所以这里图片只放了一张,如果有博友觉得本文有帮助而且希望补充图片,可以留言) 依赖是什么 依赖这个东西在安卓

mac下cocos2dx(带jsoncpp第三方库)编译为android项目心得

在mac下好不容写完了游戏,本以为轻轻松松就能编译为android项目,想不到弄了将近1整天才将问题解决 首先不带jsoncpp的编译方式请参考:http://www.bold-it.com/ios/cocos2d-x-box2d-iosandroid-hybrid-tutorial/ 带jsoncpp第三方库的参考了http://blog.csdn.net/sniffer12345/article/details/7336732,对作者表示感谢. 我使用的是正常的jsoncpp版本,在json

Xamarin.Android Binding 源自github第三方库的绑定(中级教学)----aar文件

今天来个稍微复杂一点的源自github的android第三方库:CarouselView (今天我们依然不用在metadata.xml里面写代码,虽然在build时不会有error出现,但是会有烦人的warning出现,导致我们在dll里面找不到我们需要使用的class) 今天我们就是要解决这个问题,这个问题源自这个项目依赖的库 效果图: 今天我们的任务就是把它从Java整成C#,嘿嘿嘿嘿!!!! CarouselView的Github地址在这里:https://github.com/sayya

使用SlidingMenu的方法以及Android Studio 如何导入第三方库SlidingMenu

一.使用SlidingMenu的方法 1.引入SlidingMenu库 2.继承SlidingFragmentActivity 3.onCreate方法改成public 4.调用相关API  二.Android Studio 如何导入第三方库SlidingMenu? 材料:github网站下载的第三方库SlidingMenu-master.zip 步骤: 1.新建一个项目(我的项目是NewsReports) 2.在NewsReports目录下新建一个SlidingMenuLibraries文件夹

Android Studio导入第三方库(SlidingMenu)教程

搞了半天,android的初学者,看着网上各种例子,特此记录. 注意:本教程针对像SlidingMenu这样使用Android Studio结构的第三方库. 开始: 第一步,去GitHub下载SlidingMenu (下载地址:https://github.com/jfeinstein10/SlidingMenu),下载下来在你的电脑上应该是这样样子的: 第二步,建立一个Android Studio项目: 第三步,在咱们的SlidingMenudemo项目里建立个model,这样就避免了好多教程

网络数据的下载(NSUrlconnection异步下载和NSstring同步下载)和UI界面数据的刷新(都是抛弃第三方库的一些本质)

<1>NSString同步下载        //字符串的类方法,会根据url向服务器发起同步的数据请求,并将请求结果作为返回值    //同步请求数据,会对程序的UI主线程造成阻塞,用户体验极差 NSString *str = [NSString stringWithContentsOfURL:[NSURL URLWithString:kUrl] encoding:NSUTF8StringEncoding error:nil];    //json格式的数据 进行json解析 数据最外层是