使用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返回错误码见上面博客。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。