NAPI 是 Linux 上采用的一种提高网络处理效率的技术,它的核心概念就是不采用中断的方式读取数据,而代之以首先采用中断唤醒数据接收的服务程序,然后 通过poll的方法来轮询数据。采用NAPI技术可以大大改善短长度数据包接收的效率,减少中断触发的时间。
可以这样理解,在NAPI机制没有出现时,由于网络设备接收数据是采用中断方式的,假设每次数据包很小,小到只有几个字节。而刚好在1秒内有5000个这样的数据包。那么系统就是在1秒内产生5000个中断,这无疑给会占据CPU的大部分资源。NAPI的出现就是要解决这样的问题。
概念的东西就不多提了。下面开始源码之旅啦!
首先在分配CAN设备时,采用netif_napi_add函数注册轮询函数d_can_poll()。
struct net_device *alloc_d_can_dev(int num_objs)
{
struct net_device *dev;
struct d_can_priv *priv;
dev = alloc_candev(sizeof(struct d_can_priv), num_objs/2);
if (!dev)
return NULL;
priv = netdev_priv(dev);
netif_napi_add(dev, &priv->napi, d_can_poll, num_objs/2);
priv->dev = dev;
priv->can.bittiming_const = &d_can_bittiming_const;
priv->can.do_set_mode = d_can_set_mode;
priv->can.do_get_berr_counter = d_can_get_berr_counter;
priv->can.ctrlmode_supported = (CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_BERR_REPORTING |
CAN_CTRLMODE_3_SAMPLES);
return dev;
}
netif_napi_add()函数原型如下:
void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
int (*poll)(struct napi_struct *, int), int weight)
{
INIT_LIST_HEAD(&napi->poll_list);
napi->gro_count = 0;
napi->gro_list = NULL;
napi->skb = NULL;
napi->poll = poll;
napi->weight = weight;
list_add(&napi->dev_list, &dev->napi_list);
napi->dev = dev;
#ifdef CONFIG_NETPOLL
spin_lock_init(&napi->poll_lock);
napi->poll_owner = -1;
#endif
set_bit(NAPI_STATE_SCHED, &napi->state);
}
轮询函数d_can_poll()如下:
static int d_can_poll(struct napi_struct *napi, int quota)
{
int lec_type = 0;
int work_done = 0;
struct net_device *dev = napi->dev;
struct d_can_priv *priv = netdev_priv(dev);
if (!priv->irqstatus)
goto end;
/* status events have the highest priority */
if (priv->irqstatus == STATUS_INTERRUPT) {
priv->current_status = d_can_read(priv, D_CAN_ES);
/* handle Tx/Rx events */
if (priv->current_status & D_CAN_ES_TXOK)
d_can_write(priv, D_CAN_ES,
priv->current_status & ~D_CAN_ES_TXOK);
if (priv->current_status & D_CAN_ES_RXOK)
d_can_write(priv, D_CAN_ES,
priv->current_status & ~D_CAN_ES_RXOK);
/* handle state changes */
if ((priv->current_status & D_CAN_ES_EWARN) &&
(!(priv->last_status & D_CAN_ES_EWARN))) {
netdev_dbg(dev, "entered error warning state\n");
work_done += d_can_handle_state_change(dev,
D_CAN_ERROR_WARNING);
}
if ((priv->current_status & D_CAN_ES_EPASS) &&
(!(priv->last_status & D_CAN_ES_EPASS))) {
netdev_dbg(dev, "entered error passive state\n");
work_done += d_can_handle_state_change(dev,
D_CAN_ERROR_PASSIVE);
}
if ((priv->current_status & D_CAN_ES_BOFF) &&
(!(priv->last_status & D_CAN_ES_BOFF))) {
netdev_dbg(dev, "entered bus off state\n");
work_done += d_can_handle_state_change(dev,
D_CAN_BUS_OFF);
}
/* handle bus recovery events */
if ((!(priv->current_status & D_CAN_ES_BOFF)) &&
(priv->last_status & D_CAN_ES_BOFF)) {
netdev_dbg(dev, "left bus off state\n");
priv->can.state = CAN_STATE_ERROR_ACTIVE;
}
if ((!(priv->current_status & D_CAN_ES_EPASS)) &&
(priv->last_status & D_CAN_ES_EPASS)) {
netdev_dbg(dev, "left error passive state\n");
priv->can.state = CAN_STATE_ERROR_ACTIVE;
}
priv->last_status = priv->current_status;
/* handle lec errors on the bus */
lec_type = d_can_has_handle_berr(priv);
if (lec_type)
work_done += d_can_handle_bus_err(dev, lec_type);
} else if ((priv->irqstatus >= D_CAN_MSG_OBJ_RX_FIRST) &&
(priv->irqstatus <= D_CAN_MSG_OBJ_RX_LAST)) {
/* handle events corresponding to receive message objects */
work_done += d_can_do_rx_poll(dev, (quota - work_done));
} else if ((priv->irqstatus >= D_CAN_MSG_OBJ_TX_FIRST) &&
(priv->irqstatus <= D_CAN_MSG_OBJ_TX_LAST)) {
/* handle events corresponding to transmit message objects */
d_can_do_tx(dev);
}
end:
if (work_done < quota) {
napi_complete(napi);
/* enable all IRQs */
d_can_interrupts(priv, ENABLE_ALL_INTERRUPTS);
}
return work_done;
}
在中断处理函数中,先禁止接收中断,且告诉网络子系统,将以轮询方式快速收包,其中禁止接收中断完全由硬件功能决定,而告诉内核将以轮询方式处理包则是使用函数napi_schedule()。
static irqreturn_t d_can_isr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct d_can_priv *priv = netdev_priv(dev);
priv->irqstatus = d_can_read(priv, D_CAN_INT);
if (!priv->irqstatus)
return IRQ_NONE;
/* disable all interrupts and schedule the NAPI */
d_can_interrupts(priv, DISABLE_ALL_INTERRUPTS);
napi_schedule(&priv->napi);
return IRQ_HANDLED;
}
其中的napi_schedule_prep()函数是为了判定现在是否已经进入了轮询模式。
static inline void napi_schedule(struct napi_struct *n)
{
if (napi_schedule_prep(n))
__napi_schedule(n);
}
轮询功能的关闭则需要使用:
if (work_done < quota) {
napi_complete(napi);
/* enable all IRQs */
d_can_interrupts(priv, ENABLE_ALL_INTERRUPTS);
}
因为可能存在多个napi_struct的实例,要求每个实例能够独立的使能或者禁止。因此,需要驱动开发人员保证在网卡接口关闭时,禁止所有的napi_struct的实例。在d_can_open()函数中使用napi_enable(),在d_can_close()函数中使用napi_disable()。
napi_enable(&priv->napi);
napi_disable(&priv->napi);
网上找到的,备份一份
package com.example.bank;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CheckPCard {
/*********************************** 身份证验证开始 ****************************************/
/**
* 身份证号码验证 1、号码的结构 公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,
* 八位数字出生日期码,三位数字顺序码和一位数字校验码。 2、地址码(前六位数)
* 表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。 3、出生日期码(第七位至十四位)
* 表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。 4、顺序码(第十五位至十七位)
* 表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号, 顺序码的奇数分配给男性,偶数分配给女性。 5、校验码(第十八位数)
* (1)十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0, ... , 16 ,先对前17位数字的权求和
* Ai:表示第i位置上的身份证号码数字值 Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4
* 2 (2)计算模 Y = mod(S, 11) (3)通过模得到对应的校验码 Y: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0
* X 9 8 7 6 5 4 3 2
*/
/**
* 功能:身份证的有效验证
*
* @param IDStr
* 身份证号
* @return 有效:返回"" 无效:返回String信息
* @throws ParseException
*/
@SuppressWarnings("unchecked")
public static String IDCardValidate(String IDStr) throws ParseException {
String errorInfo = "";// 记录错误信息
String[] ValCodeArr = { "1", "0", "x", "9", "8", "7", "6", "5", "4",
"3", "2" };
String[] Wi = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7",
"9", "10", "5", "8", "4", "2" };
String Ai = "";
// ================ 号码的长度 15位或18位 ================
if (IDStr.length() != 15 && IDStr.length() != 18) {
errorInfo = "身份证号码长度应该为15位或18位。";
return errorInfo;
}
// =======================(end)========================
// ================ 数字 除最后以为都为数字 ================
if (IDStr.length() == 18) {
Ai = IDStr.substring(0, 17);
} else if (IDStr.length() == 15) {
Ai = IDStr.substring(0, 6) + "19" + IDStr.substring(6, 15);
}
if (isNumeric(Ai) == false) {
errorInfo = "身份证15位号码都应为数字 ; 18位号码除最后一位外,都应为数字。";
return errorInfo;
}
// =======================(end)========================
// ================ 出生年月是否有效 ================
String strYear = Ai.substring(6, 10);// 年份
String strMonth = Ai.substring(10, 12);// 月份
String strDay = Ai.substring(12, 14);// 月份
if (isDate(strYear + "-" + strMonth + "-" + strDay) == false) {
errorInfo = "身份证生日无效。";
return errorInfo;
}
GregorianCalendar gc = new GregorianCalendar();
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150
|| (gc.getTime().getTime() - s.parse(
strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
errorInfo = "身份证生日不在有效范围。";
return errorInfo;
}
if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
errorInfo = "身份证月份无效";
return errorInfo;
}
if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
errorInfo = "身份证日期无效";
return errorInfo;
}
// =====================(end)=====================
// ================ 地区码时候有效 ================
Hashtable h = GetAreaCode();
if (h.get(Ai.substring(0, 2)) == null) {
errorInfo = "身份证地区编码错误。";
return errorInfo;
}
// ==============================================
// ================ 判断最后一位的值 ================
int TotalmulAiWi = 0;
for (int i = 0; i < 17; i++) {
TotalmulAiWi = TotalmulAiWi
+ Integer.parseInt(String.valueOf(Ai.charAt(i)))
* Integer.parseInt(Wi[i]);
}
int modValue = TotalmulAiWi % 11;
String strVerifyCode = ValCodeArr[modValue];
Ai = Ai + strVerifyCode;
if (IDStr.length() == 18) {
if (Ai.equals(IDStr) == false) {
errorInfo = "身份证无效,不是合法的身份证号码";
return errorInfo;
}
} else {
return "";
}
// =====================(end)=====================
return "";
}
/**
* 功能:设置地区编码
*
* @return Hashtable 对象
*/
@SuppressWarnings("unchecked")
private static Hashtable GetAreaCode() {
Hashtable hashtable = new Hashtable();
hashtable.put("11", "北京");
hashtable.put("12", "天津");
hashtable.put("13", "河北");
hashtable.put("14", "山西");
hashtable.put("15", "内蒙古");
hashtable.put("21", "辽宁");
hashtable.put("22", "吉林");
hashtable.put("23", "黑龙江");
hashtable.put("31", "上海");
hashtable.put("32", "江苏");
hashtable.put("33", "浙江");
hashtable.put("34", "安徽");
hashtable.put("35", "福建");
hashtable.put("36", "江西");
hashtable.put("37", "山东");
hashtable.put("41", "河南");
hashtable.put("42", "湖北");
hashtable.put("43", "湖南");
hashtable.put("44", "广东");
hashtable.put("45", "广西");
hashtable.put("46", "海南");
hashtable.put("50", "重庆");
hashtable.put("51", "四川");
hashtable.put("52", "贵州");
hashtable.put("53", "云南");
hashtable.put("54", "西藏");
hashtable.put("61", "陕西");
hashtable.put("62", "甘肃");
hashtable.put("63", "青海");
hashtable.put("64", "宁夏");
hashtable.put("65", "新疆");
hashtable.put("71", "台湾");
hashtable.put("81", "香港");
hashtable.put("82", "澳门");
hashtable.put("91", "国外");
return hashtable;
}
/**
* 功能:判断字符串是否为数字
*
* @param str
* @return
*/
private static boolean isNumeric(String str) {
Pattern pattern = Pattern.compile("[0-9]*");
Matcher isNum = pattern.matcher(str);
if (isNum.matches()) {
return true;
} else {
return false;
}
}
/**
* 功能:判断字符串是否为日期格式
*
* @param str
* @return
*/
public static boolean isDate(String strDate) {
Pattern pattern = Pattern
.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
Matcher m = pattern.matcher(strDate);
if (m.matches()) {
return true;
} else {
return false;
}
}
/*********************************** 身份证验证结束 ****************************************/
}
很多人不会使用第三方应用,特写此篇使用下第三方应用:代码具体如下:
【ConstantS.java】
public interface ConstantS {
// 应用的key 请到官方申请正式的appkey替换APP_KEY
public static final String APP_KEY = "2045436852";
// 替换为开发者REDIRECT_URL
public static final String REDIRECT_URL = "http://www.sina.com";
// 新支持scope:支持传入多个scope权限,用逗号分隔
public static final String SCOPE = "email,direct_messages_read,direct_messages_write,"
+ "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
+ "follow_app_official_microblog," + "invitation_write";
public static final String CLIENT_ID = "client_id";
public static final String RESPONSE_TYPE = "response_type";
public static final String USER_REDIRECT_URL = "redirect_uri";
public static final String DISPLAY = "display";
public static final String USER_SCOPE = "scope";
public static final String PACKAGE_NAME = "packagename";
public static final String KEY_HASH = "key_hash";
}
【MainActivity.java】
import java.text.SimpleDateFormat;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
import com.weibo.sdk.android.Oauth2AccessToken;
import com.weibo.sdk.android.Weibo;
import com.weibo.sdk.android.WeiboAuthListener;
import com.weibo.sdk.android.WeiboDialogError;
import com.weibo.sdk.android.WeiboException;
import com.weibo.sdk.android.sso.SsoHandler;
import com.weibo.sdk.android.util.AccessTokenKeeper;
public class MainActivity extends Activity {
/** 显示认证后的信息,如AccessToken */
private TextView mText;
/** 微博API接口类,提供登陆等功能 */
private Weibo mWeibo;
/** 封装了 "access_token","expires_in","refresh_token",并提供了他们的管理功能 */
private Oauth2AccessToken mAccessToken;
/** 注意:SsoHandler 仅当sdk支持sso时有效 */
private SsoHandler mSsoHandler;
private Intent intent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mText = (TextView) findViewById(R.id.show);
mWeibo = Weibo.getInstance(ConstantS.APP_KEY, ConstantS.REDIRECT_URL,
ConstantS.SCOPE);
// 触发sso测试button
findViewById(R.id.share).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(),
ShareActivity.class);
intent.putExtra("id", R.id.share);
startActivity(intent);
}
});
// 触发sso测试button
findViewById(R.id.sso).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mSsoHandler = new SsoHandler(MainActivity.this, mWeibo);
mSsoHandler.authorize(new AuthDialogListener(), null);
}
});
// 从 SharedPreferences 中读取上次已保存好 AccessToken 等信息,
// 第一次启动本应用,AccessToken 不可用
mAccessToken = AccessTokenKeeper.readAccessToken(this);
if (mAccessToken.isSessionValid()) {
String date = new java.text.SimpleDateFormat("yyyy/MM/dd hh:mm:ss")
.format(new java.util.Date(mAccessToken.getExpiresTime()));
mText.setText("access_token 仍在有效期内,无需再次登录: \naccess_token:"
+ mAccessToken.getToken() + "\n有效期:" + date);
} else {
mText.setText("使用SSO登录前,请检查手机上是否已经安装新浪微博客户端,"
+ "目前仅3.0.0及以上微博客户端版本支持SSO;如果未安装,将自动转为Oauth2.0进行认证");
}
}
/**
* 微博认证授权回调类。 1. SSO登陆时,需要在{@link #onActivityResult}
* 中调用mSsoHandler.authorizeCallBack后, 该回调才会被执行。 2. 非SSO登陆时,当授权后,就会被执行。
* 当授权成功后,请保存该access_token、expires_in等信息到SharedPreferences中。
*/
class AuthDialogListener implements WeiboAuthListener {
@Override
public void onComplete(Bundle values) {
String token = values.getString("access_token");
String expires_in = values.getString("expires_in");
mAccessToken = new Oauth2AccessToken(token, expires_in);
if (mAccessToken.isSessionValid()) {
String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
.format(new java.util.Date(mAccessToken
.getExpiresTime()));
mText.setText("认证成功: \r\n access_token: " + token + "\r\n"
+ "expires_in: " + expires_in + "\r\n有效期:" + date);
AccessTokenKeeper.keepAccessToken(MainActivity.this,
mAccessToken);
Toast.makeText(MainActivity.this, "认证成功", Toast.LENGTH_SHORT)
.show();
}
}
@Override
public void onError(WeiboDialogError e) {
Toast.makeText(getApplicationContext(),
"Auth error : " + e.getMessage(), Toast.LENGTH_LONG).show();
}
@Override
public void onCancel() {
Toast.makeText(getApplicationContext(), "Auth cancel",
Toast.LENGTH_LONG).show();
}
@Override
public void onWeiboException(WeiboException e) {
Toast.makeText(getApplicationContext(),
"Auth exception : " + e.getMessage(), Toast.LENGTH_LONG)
.show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// SSO 授权回调
// 重要:发起 SSO 登陆的Activity必须重写onActivityResult
if (mSsoHandler != null) {
mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
}
}
}
【ShareActivity.java】
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.sina.weibo.sdk.WeiboSDK;
import com.sina.weibo.sdk.api.BaseResponse;
import com.sina.weibo.sdk.api.IWeiboAPI;
import com.sina.weibo.sdk.api.IWeiboHandler;
import com.sina.weibo.sdk.api.ImageObject;
import com.sina.weibo.sdk.api.SendMessageToWeiboRequest;
import com.sina.weibo.sdk.api.SendMultiMessageToWeiboRequest;
import com.sina.weibo.sdk.api.TextObject;
import com.sina.weibo.sdk.api.WeiboMessage;
import com.sina.weibo.sdk.api.WeiboMultiMessage;
/**
* 该Activity演示了第三方应用如何发送请求消息给微博客户端。发送的内容包括文字、图片、视频、音乐等。 执行流程: 从本应用->微博->本应用
*/
public class ShareActivity extends Activity implements OnClickListener,
IWeiboHandler.Response {
/** 微博OpenAPI访问入口 */
IWeiboAPI mWeiboAPI = null;
// UI元素列表
/** 分享文本 */
private TextView mTitle;
/** 分享图片 */
private ImageView mImage;
/** 分享按钮 */
private Button mSharedBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.share);
initViews();
// 创建微博对外接口实例
mWeiboAPI = WeiboSDK.createWeiboAPI(this, ConstantS.APP_KEY);
mWeiboAPI.responseListener(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
mWeiboAPI.responseListener(intent, this);
}
/**
* 从本应用->微博->本应用 接收响应数据,该方法被调用。 注意:确保{@link #onCreate(Bundle)} 与
* {@link #onNewIntent(Intent)}中, 调用 mWeiboAPI.responseListener(intent,
* this)
*/
@Override
public void onResponse(BaseResponse baseResp) {
switch (baseResp.errCode) {
case com.sina.weibo.sdk.constant.Constants.ErrorCode.ERR_OK:
Toast.makeText(this, "成功!!", Toast.LENGTH_LONG).show();
break;
case com.sina.weibo.sdk.constant.Constants.ErrorCode.ERR_CANCEL:
Toast.makeText(this, "用户取消!!", Toast.LENGTH_LONG).show();
break;
case com.sina.weibo.sdk.constant.Constants.ErrorCode.ERR_FAIL:
Toast.makeText(this, baseResp.errMsg + ":失败!!", Toast.LENGTH_LONG)
.show();
break;
}
}
/**
* 用户点击分享按钮,唤起微博客户端进行分享。
*/
@Override
public void onClick(View v) {
if (R.id.sharedBtn == v.getId()) {
mWeiboAPI.registerApp();
reqMsg(true, true, false, false, false, false);
}
}
private void initViews() {
mSharedBtn = (Button) findViewById(R.id.sharedBtn);
mSharedBtn.setOnClickListener(this);
mTitle = (TextView) findViewById(R.id.titleText);
mImage = (ImageView) findViewById(R.id.image);
}
private void reqMsg(boolean hasText, boolean hasImage, boolean hasWebpage,
boolean hasMusic, boolean hasVedio, boolean hasVoice) {
if (mWeiboAPI.isWeiboAppSupportAPI()) {
Toast.makeText(this, "当前微博版本支持SDK分享", Toast.LENGTH_SHORT).show();
int supportApi = mWeiboAPI.getWeiboAppSupportAPI();
if (supportApi >= 10351) {
Toast.makeText(this, "当前微博版本支持多条消息,Voice消息分享",
Toast.LENGTH_SHORT).show();
reqMultiMsg(hasText, hasImage, hasWebpage, hasMusic, hasVedio,
hasVoice);
} else {
Toast.makeText(this, "当前微博版本只支持单条消息分享", Toast.LENGTH_SHORT)
.show();
reqSingleMsg(hasText, hasImage, hasWebpage, hasMusic, hasVedio/*
* ,
* hasVoice
*/);
}
} else {
Toast.makeText(this, "当前微博版本不支持SDK分享", Toast.LENGTH_SHORT).show();
}
}
/**
* 第三方应用发送请求消息到微博,唤起微博分享界面。 注意:当isWeiboAppSupportAPI() >= 10351
* 时,支持同时分享多条消息, 同时可以分享文本、图片以及其它媒体资源(网页、音乐、视频、声音中的一种), 并且支持Voice消息。
*
* @param hasText
* 分享的内容是否有文本
* @param hasImage
* 分享的内容是否有图片
* @param hasWebpage
* 分享的内容是否有网页
* @param hasMusic
* 分享的内容是否有音乐
* @param hasVideo
* 分享的内容是否有视频
* @param hasVoice
* 分享的内容是否有声音
*/
private void reqMultiMsg(boolean hasText, boolean hasImage,
boolean hasWebpage, boolean hasMusic, boolean hasVideo,
boolean hasVoice) {
// 1. 初始化微博的分享消息
WeiboMultiMessage weiboMessage = new WeiboMultiMessage();
if (hasText) {
weiboMessage.textObject = getTextObj();
}
if (hasImage) {
weiboMessage.imageObject = getImageObj();
}
// 2. 初始化从第三方到微博的消息请求
SendMultiMessageToWeiboRequest req = new SendMultiMessageToWeiboRequest();
// 用transaction唯一标识一个请求
req.transaction = String.valueOf(System.currentTimeMillis());
req.multiMessage = weiboMessage;
// 3. 发送请求消息到微博,唤起微博分享界面
mWeiboAPI.sendRequest(this, req);
}
/**
* 第三方应用发送请求消息到微博,唤起微博分享界面。 当isWeiboAppSupportAPI() < 10351 只支持分享单条消息,即
* 文本、图片、网页、音乐、视频中的一种,不支持Voice消息。
*
* @param hasText
* 分享的内容是否有文本
* @param hasImage
* 分享的内容是否有图片
* @param hasWebpage
* 分享的内容是否有网页
* @param hasMusic
* 分享的内容是否有音乐
* @param hasVideo
* 分享的内容是否有视频
*/
private void reqSingleMsg(boolean hasText, boolean hasImage,
boolean hasWebpage, boolean hasMusic, boolean hasVideo/*
* , boolean
* hasVoice
*/) {
// 1. 初始化微博的分享消息
// 用户可以分享文本、图片、网页、音乐、视频中的一种
WeiboMessage weiboMessage = new WeiboMessage();
if (hasText) {
weiboMessage.mediaObject = getTextObj();
}
if (hasImage) {
weiboMessage.mediaObject = getImageObj();
}
// 2. 初始化从第三方到微博的消息请求
SendMessageToWeiboRequest req = new SendMessageToWeiboRequest();
// 用transaction唯一标识一个请求
req.transaction = String.valueOf(System.currentTimeMillis());
req.message = weiboMessage;
// 3. 发送请求消息到微博,唤起微博分享界面
mWeiboAPI.sendRequest(this, req);
}
/**
* 文本消息构造方法。
*
* @return 文本消息对象。
*/
private TextObject getTextObj() {
TextObject textObject = new TextObject();
textObject.text = mTitle.getText().toString();
return textObject;
}
/**
* 图片消息构造方法。
*
* @return 图片消息对象。
*/
private ImageObject getImageObj() {
ImageObject imageObject = new ImageObject();
BitmapDrawable bitmapDrawable = (BitmapDrawable) mImage.getDrawable();
imageObject.setImageObject(bitmapDrawable.getBitmap());
return imageObject;
}
}
完整代码下载===》》》 weibo.sdk.android.demo.zip