新浪微博客户端开发之授权登录+获取微博列表

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

新浪微博客户端开发之授权登录+获取微博列表


闲篇:
最近实在是乱得不行,至于怎么乱我也不知该怎么说,那么久没发博客就证明了这点,一般如果小巫有做详尽的计划,并把时间投入到上面的话,我是可以用最短的时间里把新浪微博客户端给整出来的,但现在进度很慢,我越来越不像个称职的程序猿,因为现在的生活已经不再是代码,更多的是想多享受跟朋友们在一起的快乐。这些话也不多说了,关于这个项目,其实我也头痛了一整子,我很久之前就买了一本李宁的Android应用开发实战,里面很大篇幅就是介绍这个客户端的开发,因为一开始我是比较迷惑的,迷惑他到底有没有使用新浪开发平台提供的SDK,然而整个授权过程到获取微博的各种数据又是怎样的?我还在考虑我要做成一个怎样的,是否只是单纯的模仿呢?反正种种疑虑,一阵子找不到北了。后来我花时间研究了他的代码,慢慢的也找了了一些门道,明白了他从是怎么把整个客户端搭建起来的,他没有使用新浪给我们提供的SDK,而似乎是把SDK的实现给翻出来了,因为SDK仅仅提供了获取微博数据的封装,开发者就只需调用API,知道怎么传参数就行了,所以很多高手是不会直接使用新浪提供的Android SDK。要我从头到尾开发,把所有业务逻辑实现,我实在不行,所以会直接参考Android应用开发实战所提供的代码,把整个新浪微博客户端开发出来给大家看看,这也算是小巫的一个提升,与大家共同进步。


正篇:
本篇博客呢,主要介绍如何进行授权认证,如何获取微博列表,因为代码比较多,我不会全部都能贴出来,整个客户端也没有开发完毕,我也是实现一个功能,然后整理博客发表出来,如果想要项目源码的,可以直接找我,我的QQ:659982592, 如果我在的话,我会尽快答复你的。
先来看看本篇博客想要实现的效果图:



看到以上的效果,我想很多人都想知道是如何实现的,不急,我们慢慢来看,这个可不是能一口吃掉的螃蟹。

我先简单介绍一下以上效果图的业务流程,启动程序后,首先需要获取用户授权,假如已经授权过了,就不会出现提示用户输入登录的界面,授权成功后,直接获取微博数据,显示到微博列表当中。整个流程其实也蛮简单的,现在我们来看看代码。

/Wwj_sina_weibo/src/com/wwj/sina/weibo/WeiboMain.java
这个类用来切换底部标签的,比较高的版本已经不推荐用这种方法实现,不过没关系,反正高版本兼容低版本。
package com.wwj.sina.weibo;import android.app.TabActivity;import android.content.Intent;import android.os.Bundle;import android.widget.RadioButton;import android.widget.RadioGroup;import android.widget.RadioGroup.OnCheckedChangeListener;import android.widget.TabHost;import android.widget.TabHost.TabSpec;/** * 主Activity * @author wwj * 通过点击RadioGroup下的RadioButton来切换不同界面 */@SuppressWarnings("deprecation")public class WeiboMain extends TabActivity public TabHost mTabhost; public static final String TAB_HOME = "TabHome"public static final String TAB_MSG = "TabMsg"public static final String TAB_SELF = "TabSelfInfo"public static final String TAB_DISCOVE = "TabDiscove"public static final String TAB_MORE = "TabMore"; RadioButton radio_button0; public static RadioGroup indexGroup; @SuppressWarnings("static-access"@Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  // 设置无标题  requestWindowFeature(getWindow().FEATURE_NO_TITLE);  this.setContentView(R.layout.tabbar);  radio_button0 = (RadioButton) this.findViewById(R.id.tabbar_home);  radio_button0.setChecked(true); // 设置首页按钮默认是按下状态  mTabhost = (TabHost) findViewById(android.R.id.tabhost); // 获取TabHost      // 设定标签、制定一个标签作为选项卡指示符  TabSpec tabSpec1 = mTabhost.newTabSpec(TAB_HOME).setIndicator(TAB_HOME);  // 指定一个加载activity的Intent对象作为选项卡内容  tabSpec1.setContent(new Intent(WeiboMain.this, HomeActivity.class));  mTabhost.addTab(tabSpec1); // 添加第一个子页  TabSpec tabSpec2 = mTabhost.newTabSpec(TAB_MSG).setIndicator(TAB_MSG);  tabSpec2.setContent(new Intent(WeiboMain.this, MessageActivity.class));  mTabhost.addTab(tabSpec2); // 添加第二个子页  TabSpec tabSpec3 = mTabhost.newTabSpec(TAB_SELF).setIndicator(TAB_SELF);  tabSpec3.setContent(new Intent(WeiboMain.this, SelfInfoActivity.class));  mTabhost.addTab(tabSpec3); // 添加第三个子页  TabSpec tabSpec4 = mTabhost.newTabSpec(TAB_DISCOVE).setIndicator(    TAB_DISCOVE);  tabSpec4.setContent(new Intent(WeiboMain.this, DiscoveActivity.class));  mTabhost.addTab(tabSpec4); // 添加第四个子页  TabSpec tabSpec5 = mTabhost.newTabSpec(TAB_MORE).setIndicator(TAB_MORE);  tabSpec5.setContent(new Intent(WeiboMain.this, MoreActivity.class));  mTabhost.addTab(tabSpec5); // 添加第一个子页  this.indexGroup = (RadioGroup) this.findViewById(R.id.main_radio);  // 实现RadioGroup的子选项点击监听  indexGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {   @Override   public void onCheckedChanged(RadioGroup group, int checkedId) {    switch (checkedId) {    case R.id.tabbar_home: // 首页     mTabhost.setCurrentTabByTag(TAB_HOME);     break;    case R.id.tabbar_message:// 信息     mTabhost.setCurrentTabByTag(TAB_MSG);     break;    case R.id.tabbar_me: // 个人资料     mTabhost.setCurrentTabByTag(TAB_SELF);     break;    case R.id.tabbar_discove: // 发现     mTabhost.setCurrentTabByTag(TAB_DISCOVE);     break;    case R.id.tabbar_more: // 更多     mTabhost.setCurrentTabByTag(TAB_MORE);    }   }  }); }}





/Wwj_sina_weibo/src/com/wwj/sina/weibo/HomeActivity.java
这个Activity就是显示微博列表的界面,代码还不完善,这里只看关键点。
package com.wwj.sina.weibo;import java.util.List;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.MenuItem;import android.view.MenuItem.OnMenuItemClickListener;import android.view.View;import android.view.View.OnClickListener;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.AdapterView.OnItemLongClickListener;import android.widget.Button;import android.widget.LinearLayout;import android.widget.TextView;import com.weibo.net.Weibo;import com.wwj.sina.weibo.adapter.WeiboListAdapter;import com.wwj.sina.weibo.interfaces.Const;import com.wwj.sina.weibo.library.StorageManager;import com.wwj.sina.weibo.library.WeiboData;import com.wwj.sina.weibo.library.WeiboManager;import com.wwj.sina.weibo.listener.impl.StatusRequestListenerImpl;import com.wwj.sina.weibo.object.Status;import com.wwj.sina.weibo.object.User;import com.wwj.sina.weibo.util.Tools;import com.wwj.sina.weibo.view.PullToRefreshListView;import com.wwj.sina.weibo.view.PullToRefreshListView.OnRefreshListener;import com.wwj.sina.weibo.workqueue.DoneAndProcess;import com.wwj.sina.weibo.workqueue.WorkQueueMonitor;import com.wwj.sina.weibo.workqueue.task.ParentTask;import com.wwj.sina.weibo.workqueue.task.PullFileTask;/** * 主界面 *  * @author wwj 用于显示公共微博 */public class HomeActivity extends Activity implements Const, OnClickListener,  OnItemClickListener, OnItemLongClickListener, OnMenuItemClickListener,  DoneAndProcess public PullToRefreshListView weiboListView; // 自定义ListView private Weibo weibo; // 微博对象 public HomeData homeData; // 主界面数据 public TextView username; // 用户名,显示在标题栏 public Button btn_post_weibo; // 发布微博 public Button btn_reload; // 加载新微博 private LinearLayout linearLayoutHome; private Handler handler = new Handler() {  public void handleMessage(android.os.Message msg) {  }; }; // 微博列表主界面的数据 public static class HomeData {  public WeiboListAdapter weiboListAdapter;  public WorkQueueMonitor imageWorkQueueMonitor;  public WorkQueueMonitor taskWorkQueueMonitor;  public User user; } @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.home);  getWindow().setSoftInputMode(    WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);  loadView();  getWindow().setBackgroundDrawable(null);  weibo = Tools.getWeibo(this);  // 获取微博对象  homeData = (HomeData) getLastNonConfigurationInstance();  if (homeData == null) {   homeData = new HomeData();   if (!(weibo == null || !weibo.isSessionValid())) {    @SuppressWarnings("unchecked")    List<Status> statuses = StorageManager.loadList(this,      Const.HOME);    if (statuses == null) {     statuses = WeiboManager.getHomeTimeline(this);    }    homeData.weiboListAdapter = WeiboData.loadWeiboListData(this,      Const.HOME, weiboListView, statuses);   }  } } @Override protected void onResume() {  super.onResume(); } @Override public Object onRetainNonConfigurationInstance() {  return homeData; } // 加载视图 private void loadView() {  weiboListView = (PullToRefreshListView) findViewById(R.id.weibolist);  linearLayoutHome = (LinearLayout) findViewById(R.id.ll_home_layout);  username = (TextView) this.findViewById(R.id.tv_home_name);  btn_post_weibo = (Button) this.findViewById(R.id.btn_home_post_weibo);  btn_reload = (Button) this.findViewById(R.id.btn_home_reload);  weiboListView.setOnItemClickListener(this);  btn_post_weibo.setOnClickListener(this);  btn_reload.setOnClickListener(this); } @Override public void onClick(View v) {  Intent intent = null;  GlobalObject globalObject = Tools.getGlobalObject(this);  switch (v.getId()) {  case R.id.btn_home_post_weibo: // 发布微博   intent = new Intent(HomeActivity.this, PostWeibo.class);   startActivity(intent);   break;  case R.id.btn_home_reload: // 刷新列表   long sinceId = homeData.weiboListAdapter.getMaxId() + 1;   WeiboManager.getHomeTimeline(this, sinceId, 0,     DEFAULT_STATUS_COUNT, true, new StatusRequestListenerImpl(       this, linearLayoutHome, HOME));   View homeReloadAnim = findViewById(R.id.pb_home_reload);   View homeReload = findViewById(R.id.btn_home_reload);   homeReloadAnim.setVisibility(View.VISIBLE);   homeReload.setVisibility(View.GONE);   break;  } } @Override public void doneProcess(ParentTask task) {  Message msg = new Message();  msg.obj = task;  if (task instanceof PullFileTask) {   msg.what = HANDLER_TYPE_LOAD_PROFILE_IMAGE;   msg.obj = ((PullFileTask) task).fileUrl;  }  handler.sendMessage(msg); } @Override public boolean onMenuItemClick(MenuItem item) {  return false; } @Override public boolean onItemLongClick(AdapterView<?> parent, View view,   int position, long id) {  return false; } @Override public void onItemClick(AdapterView<?> parent, View view, int position,   long id) {  Intent intent = null;  switch (parent.getId()) {  case R.id.weibolist:   // 按更多项   // 注意:更多点击的位置   if (position == homeData.weiboListAdapter.getCount()) {    long maxId = homeData.weiboListAdapter.getMinId() - 1;    WeiboManager.getHomeTimeline(this, 0, maxId,      DEFAULT_STATUS_COUNT, true,      new StatusRequestListenerImpl(this, linearLayoutHome,        HOME));    homeData.weiboListAdapter.showMoreAnim();   } else// 点击列表项    Status status = homeData.weiboListAdapter.getStatus(position);    if (status != null) {     intent = new Intent(this, WeiboViewer.class);     WeiboViewer.status = status;     startActivity(intent);    }   }   break;  } }}


上面使用到一个Tools类,这是一个工具类,用来获取微博对象和一些转换操作,稍微看一下
/Wwj_sina_weibo/src/com/wwj/sina/weibo/util/Tools.java
package com.wwj.sina.weibo.util;import java.io.InputStream;import java.io.OutputStream;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale;import java.util.regex.Matcher;import java.util.regex.Pattern;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Color;import android.text.Spannable;import android.text.SpannableString;import android.text.Spanned;import android.text.style.ImageSpan;import android.view.View;import android.widget.ImageView;import com.weibo.net.Weibo;import com.wwj.sina.weibo.GlobalObject;import com.wwj.sina.weibo.interfaces.Const;import com.wwj.sina.weibo.library.FaceMan;public class Tools implements Const /**  * 获取微博对象  * @param activity  * @return  */ public static Weibo getWeibo(Activity activity) {  GlobalObject globalObject = (GlobalObject) activity    .getApplicationContext();  return globalObject.getWeibo(activity); } /**  * 判断当前是否有微博对象  * @param activity  * @return  */ public static boolean hasWeibo(Activity activity) {  GlobalObject globalObject = (GlobalObject) activity    .getApplicationContext();  return globalObject.getWeibo() == null ? false : true; } public static GlobalObject getGlobalObject(Activity activity) {  GlobalObject globalObject = (GlobalObject) activity    .getApplicationContext();  return globalObject; } // 将微博的日期字符串转换为Date对象 public static Date strToDate(String str) {  // sample:Tue May 31 17:46:55 +0800 2011  // E:周 MMM:字符串形式的月,如果只有两个M,表示数值形式的月 Z表示时区(+0800)  SimpleDateFormat sdf = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy",    Locale.US);  Date result = null;  try {   result = sdf.parse(str);  } catch (Exception e) {   // TODO: handle exception  }  return result; }  public static void dataTransfer(InputStream is, OutputStream os) {  byte[] buffer = new byte[8192];  int count = 0;  try {   while((count = is.read(buffer)) > -1) {    os.write(buffer, 0, count);   }  } catch (Exception e) {     } } public static void userVerified(ImageView imageView, int verifiedType) {  if (verifiedType >= 0) {   imageView.setVisibility(View.VISIBLE);   switch (verifiedType) {   case 0:   case 220:    imageView.setImageLevel(verifiedType);    break;   default:    imageView.setImageLevel(1);    break;   }  } } public static SpannableString changeTextToFace(Context context,   Spanned spanned) {  String text = spanned.toString();  SpannableString spannableString = new SpannableString(spanned);  Pattern pattern = Pattern.compile("\\[[^\\]]+\\]");  Matcher matcher = pattern.matcher(text);  boolean b = true;  while (b = matcher.find()) {   String faceText = text.substring(matcher.start(), matcher.end());   int resourceId = FaceMan.getResourceId(faceText);   if (resourceId > 0) {    Bitmap bitmap = BitmapFactory.decodeResource(      context.getResources(), resourceId);    ImageSpan imageSpan = new ImageSpan(bitmap);    spannableString.setSpan(imageSpan, matcher.start(),      matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);   }  }  return spannableString; } public static String atBlue(String s) {  StringBuilder sb = new StringBuilder();  int commonTextColor = Color.BLACK;  int signColor = Color.BLUE;  int state = 1;  String str = "";  for (int i = 0; i < s.length(); i++) {   switch (state) {   case 1: // 普通字符状态    // 遇到@    if (s.charAt(i) == '@') {     state = 2;     str += s.charAt(i);    }    // 遇到#    else if (s.charAt(i) == '#') {     str += s.charAt(i);     state = 3;    }    // 添加普通字符    else {     if (commonTextColor == Color.BLACK)      sb.append(s.charAt(i));     else      sb.append("<font color='" + commonTextColor + "'>"        + s.charAt(i) + "</font>");    }    break;   case 2: // 处理遇到@的情况    // 处理@后面的普通字符    if (Character.isJavaIdentifierPart(s.charAt(i))) {     str += s.charAt(i);    }    else {     // 如果只有一个@,作为普通字符处理     if ("@".equals(str)) {      sb.append(str);     }     // 将@及后面的普通字符变成蓝色     else {      sb.append(setTextColor(str, String.valueOf(signColor)));     }     // @后面有#的情况,首先应将#添加到str里,这个值可能会变成蓝色,也可以作为普通字符,要看后面还有没有#了     if (s.charAt(i) == '#') {      str = String.valueOf(s.charAt(i));      state = 3;     }     // @后面还有个@的情况,和#类似     else if (s.charAt(i) == '@') {      str = String.valueOf(s.charAt(i));      state = 2;     }     // @后面有除了@、#的其他特殊字符。需要将这个字符作为普通字符处理     else {      if (commonTextColor == Color.BLACK)       sb.append(s.charAt(i));      else       sb.append("<font color='" + commonTextColor + "'>"         + s.charAt(i) + "</font>");      state = 1;      str = "";     }    }    break;   case 3: // 处理遇到#的情况    // 前面已经遇到一个#了,这里处理结束的#    if (s.charAt(i) == '#') {     str += s.charAt(i);     sb.append(setTextColor(str, String.valueOf(signColor)));     str = "";     state = 1;    }    // 如果#后面有@,那么看一下后面是否还有#,如果没有#,前面的#作废,按遇到@处理    else if (s.charAt(i) == '@') {     if (s.substring(i).indexOf("#") < 0) {      sb.append(str);      str = String.valueOf(s.charAt(i));      state = 2;     } else {      str += s.charAt(i);     }    }    // 处理#...#之间的普通字符    else {     str += s.charAt(i);    }    break;   }  }  if (state == 1 || state == 3) {   sb.append(str);  } else if (state == 2) {   if ("@".equals(str)) {    sb.append(str);   } else {    sb.append(setTextColor(str, String.valueOf(signColor)));   }  }  return sb.toString(); } public static String setTextColor(String s, String color) {  String result = "<font color='" + color + "'>" + s + "</font>";  return result; } public static String getTimeStr(Date oldTime, Date currentDate) {  long time1 = currentDate.getTime();  long time2 = oldTime.getTime();  long time = (time1 - time2) / 1000;  if (time >= 0 && time < 60) {   return "刚才";  } else if (time >= 60 && time < 3600) {   return time / 60 + "分钟前";  } else if (time >= 3600 && time < 3600 * 24) {   return time / 3600 + "小时前";  } else {   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");   return sdf.format(oldTime);  } }}

上面定义了一个getWeibo()的方法,可以看到它是通过GlobalObject来获取微博对象的,那在看看这个类
/Wwj_sina_weibo/src/com/wwj/sina/weibo/GlobalObject.java
package com.wwj.sina.weibo;import android.app.Activity;import android.app.Application;import com.weibo.net.Weibo;import com.wwj.sina.weibo.interfaces.Const;import com.wwj.sina.weibo.listener.AuthDialogListener;import com.wwj.sina.weibo.net.PullFile;import com.wwj.sina.weibo.object.Consumer;import com.wwj.sina.weibo.workqueue.WorkQueueMonitor;import com.wwj.sina.weibo.workqueue.WorkQueueStorage;public class GlobalObject extends Application implements Constprivate Weibo weibo;  private WorkQueueStorage workQueueStorage; private WorkQueueMonitor imageWorkQueueMonitor; private WorkQueueMonitor taskWorkQueueMonitor;  public Weibo getWeibo(Activity activity) {  if (weibo == null || !weibo.isSessionValid()) {   weibo = Weibo.getInstance();  // 获取Weibo对象   weibo.setupConsumerConfig(Consumer.consumerKey, Consumer.consumerSecret);   weibo.setRedirectUrl(Consumer.redirectUrl);   weibo.authorize(activity, new AuthDialogListener(activity));  }  return weibo; }  public Weibo getWeibo() {  return weibo; } public WorkQueueStorage getWorkQueueStorage() {  if (workQueueStorage == null){   workQueueStorage = new WorkQueueStorage();  }  return workQueueStorage; }  public WorkQueueMonitor getWorkQueueMonitor(Activity activity) {  if (imageWorkQueueMonitor == null) {   imageWorkQueueMonitor = new WorkQueueMonitor(activity, getWorkQueueStorage(), new PullFile(), MONITOR_TYPE_IMAGE);   imageWorkQueueMonitor.start();  }  return imageWorkQueueMonitor; } }

可以看到这个类是Application级别的,说明最先加载的是这个类,来看这个类定义的getWeibo()方法,现在很直观啦,这里就是获取授权认证的地方。设置好consumerKey和consumerSecret后,就可以调用authorize()方法进行授权了。这个方法在Weibo这个类当中,这个类很重要,能不能使用微博功能就看它了。

/Wwj_sina_weibo/src/com/weibo/net/Weibo.java
/* * Copyright 2011 Sina. * * Licensed under the Apache License and Weibo 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.open.weibo.com *    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. */package com.weibo.net;import java.io.IOException;import java.net.MalformedURLException;import android.Manifest;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.os.Bundle;import android.text.TextUtils;import android.util.Log;import android.webkit.CookieSyncManager;/** * Encapsulation main Weibo APIs, Include: 1. getRquestToken , 2. * getAccessToken, 3. url request. Used as a single instance class. Implements a * weibo api as a synchronized way. *  * @author ZhangJie ([email protected]) */public class Weibo {    // public static String SERVER = "http://api.t.sina.com.cn/";    public static String SERVER = "https://api.weibo.com/2/";    public static String URL_OAUTH_TOKEN = "http://api.t.sina.com.cn/oauth/request_token";    public static String URL_AUTHORIZE = "http://api.t.sina.com.cn/oauth/authorize";    public static String URL_ACCESS_TOKEN = "http://api.t.sina.com.cn/oauth/access_token";    public static String URL_AUTHENTICATION = "http://api.t.sina.com.cn/oauth/authenticate";    public static String URL_OAUTH2_ACCESS_TOKEN = "https://api.weibo.com/oauth2/access_token";    // public static String URL_OAUTH2_ACCESS_AUTHORIZE =    // "http://t.weibo.com:8093/oauth2/authorize";    public static String URL_OAUTH2_ACCESS_AUTHORIZE = "https://api.weibo.com/oauth2/authorize";    private static String APP_KEY = "";    private static String APP_SECRET = "";    private static Weibo mWeiboInstance = null;    private Token mAccessToken = null;    private RequestToken mRequestToken = null;    private WeiboDialogListener mAuthDialogListener;    private static final int DEFAULT_AUTH_ACTIVITY_CODE = 32973;    public static final String TOKEN = "access_token";    public static final String EXPIRES = "expires_in";    public static final String DEFAULT_REDIRECT_URI = "wbconnect://success";// 暂不支持    public static final String DEFAULT_CANCEL_URI = "wbconnect://cancel";// 暂不支持    private String mRedirectUrl;    private Weibo() {        Utility.setRequestHeader("Accept-Encoding", "gzip");        Utility.setTokenObject(this.mRequestToken);        mRedirectUrl = DEFAULT_REDIRECT_URI;    }    /**     * 获取单例     * @return     */    public synchronized static Weibo getInstance() {        if (mWeiboInstance == null) {            mWeiboInstance = new Weibo();        }        return mWeiboInstance;    }    // 设置accessToken    public void setAccessToken(AccessToken token) {        mAccessToken = token;    }    public Token getAccessToken() {        return this.mAccessToken;    }    /**     * 设置第三方key和secret     * @param consumer_key     * @param consumer_secret     */    public void setupConsumerConfig(String consumer_key, String consumer_secret) {        Weibo.APP_KEY = consumer_key;        Weibo.APP_SECRET = consumer_secret;    }    public static String getAppKey() {        return Weibo.APP_KEY;    }    public static String getAppSecret() {        return Weibo.APP_SECRET;    }    public void setRequestToken(RequestToken token) {        this.mRequestToken = token;    }    public static String getSERVER() {        return SERVER;    }    public static void setSERVER(String sERVER) {        SERVER = sERVER;    }    // 设置oauth_verifier    public void addOauthverifier(String verifier) {        mRequestToken.setVerifier(verifier);    }    public String getRedirectUrl() {        return mRedirectUrl;    }    /**     * 设置第三方回调页     * @param mRedirectUrl     */    public void setRedirectUrl(String mRedirectUrl) {        this.mRedirectUrl = mRedirectUrl;    }    /**     * Requst sina weibo open api by get or post     *      * @param url     *            Openapi request URL.     * @param params     *            http get or post parameters . e.g.     *            gettimeling?max=max_id&min=min_id max and max_id is a pair of     *            key and value for params, also the min and min_id     * @param httpMethod     *            http verb: e.g. "GET", "POST", "DELETE"     * @throws IOException     * @throws MalformedURLException     * @throws WeiboException     */    public String request(Context context, String url, WeiboParameters params, String httpMethod,            Token token) throws WeiboException {        String rlt = Utility.openUrl(context, url, httpMethod, params, this.mAccessToken);        return rlt;    }    /**/    public RequestToken getRequestToken(Context context, String key, String secret,            String callback_url) throws WeiboException {        Utility.setAuthorization(new RequestTokenHeader());        WeiboParameters postParams = new WeiboParameters();        postParams.add("oauth_callback", callback_url);        String rlt;        rlt = Utility.openUrl(context, Weibo.URL_OAUTH_TOKEN, "POST", postParams, null);        RequestToken request = new RequestToken(rlt);        this.mRequestToken = request;        return request;    }    public AccessToken generateAccessToken(Context context, RequestToken requestToken)            throws WeiboException {        Utility.setAuthorization(new AccessTokenHeader());        WeiboParameters authParam = new WeiboParameters();        authParam.add("oauth_verifier", this.mRequestToken.getVerifier()/* "605835" */);        authParam.add("source", APP_KEY);        String rlt = Utility.openUrl(context, Weibo.URL_ACCESS_TOKEN, "POST", authParam,                this.mRequestToken);        AccessToken accessToken = new AccessToken(rlt);        this.mAccessToken = accessToken;        return accessToken;    }    public AccessToken getXauthAccessToken(Context context, String app_key, String app_secret,            String usrname, String password) throws WeiboException {        Utility.setAuthorization(new XAuthHeader());        WeiboParameters postParams = new WeiboParameters();        postParams.add("x_auth_username", usrname);        postParams.add("x_auth_password", password);        postParams.add("oauth_consumer_key", APP_KEY);        String rlt = Utility.openUrl(context, Weibo.URL_ACCESS_TOKEN, "POST", postParams, null);        AccessToken accessToken = new AccessToken(rlt);        this.mAccessToken = accessToken;        return accessToken;    }    /**     * 获取Oauth2.0的accesstoken     *      * https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&     * client_secret=YOUR_CLIENT_SECRET&grant_type=password&redirect_uri=     * YOUR_REGISTERED_REDIRECT_URI&username=USER_NAME&pasword=PASSWORD     *      * @param context     * @param app_key     * @param app_secret     * @param usrname     * @param password     * @return     * @throws WeiboException     */    public Oauth2AccessToken getOauth2AccessToken(Context context, String app_key,            String app_secret, String usrname, String password) throws WeiboException {        Utility.setAuthorization(new Oauth2AccessTokenHeader());        WeiboParameters postParams = new WeiboParameters();        postParams.add("username", usrname);        postParams.add("password", password);        postParams.add("client_id", app_key);        postParams.add("client_secret", app_secret);        postParams.add("grant_type", "password");        String rlt = Utility.openUrl(context, Weibo.URL_OAUTH2_ACCESS_TOKEN, "POST", postParams,                null);        Oauth2AccessToken accessToken = new Oauth2AccessToken(rlt);        this.mAccessToken = accessToken;        return accessToken;    }    /**     * Share text content or image to weibo .     *      */    public boolean share2weibo(Activity activity, String accessToken, String tokenSecret,            String content, String picPath) throws WeiboException {        if (TextUtils.isEmpty(accessToken)) {            throw new WeiboException("token can not be null!");        }        // else if (TextUtils.isEmpty(tokenSecret)) {        // throw new WeiboException("secret can not be null!");        // }        if (TextUtils.isEmpty(content) && TextUtils.isEmpty(picPath)) {            throw new WeiboException("weibo content can not be null!");        }        Intent i = new Intent(activity, ShareActivity.class);        i.putExtra(ShareActivity.EXTRA_ACCESS_TOKEN, accessToken);        i.putExtra(ShareActivity.EXTRA_TOKEN_SECRET, tokenSecret);        i.putExtra(ShareActivity.EXTRA_WEIBO_CONTENT, content);        i.putExtra(ShareActivity.EXTRA_PIC_URI, picPath);        activity.startActivity(i);        return true;    }    private boolean startSingleSignOn(Activity activity, String applicationId,            String[] permissions, int activityCode) {        return false;    }    public static boolean flag = false;    private void startDialogAuth(Activity activity, String[] permissions) {        if(flag == true) return;     WeiboParameters params = new WeiboParameters();        if (permissions.length > 0) {            params.add("scope", TextUtils.join(",", permissions));        }        CookieSyncManager.createInstance(activity);               dialog(activity, params, new WeiboDialogListener() {            public void onComplete(Bundle values) {             flag = false;                // ensure any cookies set by the dialog are saved                CookieSyncManager.getInstance().sync();                if (null == mAccessToken) {                    mAccessToken = new Token();                }                mAccessToken.setToken(values.getString(TOKEN));                mAccessToken.setExpiresIn(values.getString(EXPIRES));                if (isSessionValid()) {                    Log.d("Weibo-authorize",                            "Login Success! access_token=" + mAccessToken.getToken() + " expires="                                    + mAccessToken.getExpiresIn());                    mAuthDialogListener.onComplete(values);                } else {                    Log.d("Weibo-authorize", "Failed to receive access token");                    mAuthDialogListener.onWeiboException(new WeiboException(                            "Failed to receive access token."));                }            }            public void onError(DialogError error) {             flag = false;                Log.d("Weibo-authorize", "Login failed: " + error);                mAuthDialogListener.onError(error);            }            public void onWeiboException(WeiboException error) {             flag = false;                Log.d("Weibo-authorize", "Login failed: " + error);                mAuthDialogListener.onWeiboException(error);            }            public void onCancel() {             flag = false;                Log.d("Weibo-authorize", "Login canceled");                mAuthDialogListener.onCancel();            }        });        flag = true;    }    /**     * User-Agent Flow     *      * @param activity     *      * @param listener     *            授权结果监听器     */    public void authorize(Activity activity, final WeiboDialogListener listener) {        authorize(activity, new String[] {}, DEFAULT_AUTH_ACTIVITY_CODE, listener);    }    @SuppressWarnings("unused"private void authorize(Activity activity, String[] permissions,            final WeiboDialogListener listener) {        authorize(activity, permissions, DEFAULT_AUTH_ACTIVITY_CODE, listener);    }    private void authorize(Activity activity, String[] permissions, int activityCode,            final WeiboDialogListener listener) {        Utility.setAuthorization(new Oauth2AccessTokenHeader());        boolean singleSignOnStarted = false;        mAuthDialogListener = listener;        // Prefer single sign-on, where available.        if (activityCode >= 0) {            singleSignOnStarted = startSingleSignOn(activity, APP_KEY, permissions, activityCode);        }        // Otherwise fall back to traditional dialog.        if (!singleSignOnStarted) {            startDialogAuth(activity, permissions);        }    } @SuppressWarnings("unused"private void authorizeCallBack(int requestCode, int resultCode, Intent data) { }       public void dialog(Context context, WeiboParameters parameters,            final WeiboDialogListener listener) {        parameters.add("client_id", APP_KEY);        parameters.add("response_type", "token");        parameters.add("redirect_uri", mRedirectUrl);        parameters.add("display", "mobile");        if (isSessionValid()) {            parameters.add(TOKEN, mAccessToken.getToken());        }        String url = URL_OAUTH2_ACCESS_AUTHORIZE + "?" + Utility.encodeUrl(parameters);        if (context.checkCallingOrSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {            Utility.showAlert(context, "Error",                    "Application requires permission to access the Internet");        } else {            new WeiboDialog(this, context, url, listener).show();        }    }    public boolean isSessionValid() {        if (mAccessToken != null) {            return (!TextUtils.isEmpty(mAccessToken.getToken()) && (mAccessToken.getExpiresIn() == 0 || (System                    .currentTimeMillis() < mAccessToken.getExpiresIn())));        }        return false;    }}

你们自己找到authorize()看看呗,怎么弹出那个登录界面的自己研究去,这个方法需要传入一个listener,
就是这个类了AuthDialogListener
/Wwj_sina_weibo/src/com/wwj/sina/weibo/listener/AuthDialogListener.java
授权完成后,回调这个类的onComplete方法,然后就可以获取微博数据了。
package com.wwj.sina.weibo.listener;import android.app.Activity;import android.os.Bundle;import android.widget.Toast;import com.weibo.net.DialogError;import com.weibo.net.WeiboDialogListener;import com.weibo.net.WeiboException;import com.wwj.sina.weibo.HomeActivity;import com.wwj.sina.weibo.adapter.WeiboListAdapter;import com.wwj.sina.weibo.interfaces.Const;import com.wwj.sina.weibo.library.StorageManager;import com.wwj.sina.weibo.library.WeiboData;import com.wwj.sina.weibo.library.WeiboManager;import com.wwj.sina.weibo.object.User;import com.wwj.sina.weibo.util.SettingUtil;public class AuthDialogListener implements WeiboDialogListener private Activity activity; public AuthDialogListener(Activity activity) {  super();  this.activity = activity; } public void onComplete(Bundle values) {  // 保存access_token 和 expires_in  String token = values.getString("access_token");  String expires_in = values.getString("expires_in");  SettingUtil.set(activity, SettingUtil.ACCESS_TOKEN, token);  SettingUtil.set(activity, SettingUtil.EXPIRES_IN, expires_in);  Toast.makeText(activity, "认证成功", Toast.LENGTH_SHORT).show();  HomeActivity homeActivity = (HomeActivity) activity;  WeiboListAdapter weiboListAdapter = null;  long uid = Long.parseLong(values.getString("uid"));  User user = WeiboManager.getUser(activity, uid);  if (user != null) {   homeActivity.username.setText(user.name);   StorageManager.setValue(activity, "uid", uid); // 保存用户UID  }  weiboListAdapter = WeiboData.loadWeiboListData(activity, Const.HOME,    homeActivity.weiboListView);  homeActivity.homeData.weiboListAdapter = weiboListAdapter; } public void onWeiboException(WeiboException e) {  // 当认证过程中捕获到WeiboException时调用  Toast.makeText(activity, "Auth exception:" + e.getMessage(),    Toast.LENGTH_LONG).show(); } public void onError(DialogError e) {  // Oauth2.0认证过程中,当认证对话框中的webView接收数据出现错误时调用此方法  Toast.makeText(activity, "Auth error:" + e.getMessage(),    Toast.LENGTH_LONG).show(); } public void onCancel() {  // Oauth2.0认证过程中,如果认证窗口被关闭或认证取消时调用  Toast.makeText(activity, "Auth cancel", Toast.LENGTH_LONG).show(); }}

执行完这个就已经把数据显示出来了
 WeiboData.loadWeiboListData(activity, Const.HOME,homeActivity.weiboListView);

这里又有一个WeiboData这个类,看看就明白了
package com.wwj.sina.weibo.library;import java.util.List;import android.app.Activity;import android.widget.ListView;import com.wwj.sina.weibo.adapter.WeiboListAdapter;import com.wwj.sina.weibo.interfaces.Const;import com.wwj.sina.weibo.object.Status;import com.wwj.sina.weibo.util.Tools;public class WeiboData implements Const public static WeiboListAdapter loadWeiboListData(Activity activity,   int type, ListView listView) {  return loadWeiboListData(activity, type, listView, null); } public static WeiboListAdapter loadWeiboListData(Activity activity,   int type, ListView listView, List<Status> statuses) {  WeiboListAdapter adapter = null;  if (Tools.hasWeibo(activity)) {   switch (type) {   case HOME:    if (statuses == null)     statuses = WeiboManager.getHomeTimeline(activity);    adapter = new WeiboListAdapter(activity, statuses, type);    break;   default:    break;   }      listView.setAdapter(adapter);  }    return adapter; }}

可以看到,这里ListView就直接setAdapter了。来看到第二个loadWeiboListData方法,有一个List<Status> statuses参数,这个就是保存微博数据的参数了,是怎么得到的?我们又可以看到一个类WeiboManager里有一个getHomeTimeline的方法,这个就是返回微博数据的方法。

等不及了,进去看看。
/Wwj_sina_weibo/src/com/wwj/sina/weibo/library/WeiboManager.java
package com.wwj.sina.weibo.library;import java.io.File;import java.util.List;import android.app.Activity;import com.weibo.net.AsyncWeiboRunner;import com.weibo.net.AsyncWeiboRunner.RequestListener;import com.weibo.net.Weibo;import com.weibo.net.WeiboParameters;import com.wwj.sina.weibo.interfaces.Const;import com.wwj.sina.weibo.object.Consumer;import com.wwj.sina.weibo.object.Status;import com.wwj.sina.weibo.object.User;import com.wwj.sina.weibo.util.Tools;import com.wwj.sina.weibo.workqueue.DoneAndProcess;import com.wwj.sina.weibo.workqueue.WorkQueueStorage;import com.wwj.sina.weibo.workqueue.task.PullFileTask;/** * 微博管理类,提供方法获取微博数据 *  * @author Administrator *  */public class WeiboManager implements Const public static List<Status> getHomeTimeline(Activity activity) {  return getHomeTimeline(activity, 0, 0, DEFAULT_STATUS_COUNT); } private static List<Status> getHomeTimeline(Activity activity,   long sinceId, long maxId, int count) {  return getHomeTimeline(activity, sinceId, maxId, count, false, null); } /**  * 获取当前登录用户及其所关注用户的最新微博  *   * @param activity  * @param sinceId  * @param maxId  * @param count  * @param async  *            是否同步  * @param listener  * @return  */ @SuppressWarnings("unchecked"public static List<Status> getHomeTimeline(Activity activity,   long sinceId, long maxId, int count, boolean async,   RequestListener listener) {  // 访问接口url  String url = Weibo.SERVER + "statuses/home_timeline.json";  // 获取微博对象  Weibo weibo = Tools.getWeibo(activity);  if (weibo == null || !weibo.isSessionValid()) {   return null;  }  WeiboParameters bundle = new WeiboParameters();  bundle.add("source", Consumer.consumerKey);  if (sinceId != 0)   bundle.add("since_id", String.valueOf(sinceId));  if (maxId != 0)   bundle.add("max_id", String.valueOf(maxId));  if (count != 0)   bundle.add("count", String.valueOf(count));  List<Status> statuses = null;  try {   if (!async) {    // 请求获取JSON数据    String json = weibo.request(activity, url, bundle, "GET",      weibo.getAccessToken());    statuses = JSONAndObject      .convert(Status.class, json, "statuses");   } else {    AsyncWeiboRunner asyncWeiboRunner = new AsyncWeiboRunner(weibo);    asyncWeiboRunner      .request(activity, url, bundle, "GET", listener);   }  } catch (Exception e) {  }  return statuses; } public static String getImageurl(Activity activity, String url) {  return getImageurl(activity, url, null); } public static String getImageurl(Activity activity, String url,   DoneAndProcess doneAndProcess) {  String result = null;  if (url == null || "".equals(url))   return result;  result = PATH_FILE_CACHE + "/" + url.hashCode();  File file = new File(PATH_FILE_CACHE + "/" + url.hashCode());  if (file.exists()) {   return result;  } else {   WorkQueueStorage workQueueStorage = Tools.getGlobalObject(activity)     .getWorkQueueStorage();   if (workQueueStorage != null) {    if (doneAndProcess == null) {     workQueueStorage.addDoneWebFileUrl(url);    } else {     PullFileTask pullFileTask = new PullFileTask();     pullFileTask.doneAndProcess = doneAndProcess;     pullFileTask.fileUrl = url;     workQueueStorage.addTask(pullFileTask);    }   }   result = null;  }  return result; } public static boolean hasPicture(Status status) {  if (status.thumbnail_pic != null && !"".equals(status.thumbnail_pic))   return true;  if (status.retweeted_status != null) {   if (status.retweeted_status.thumbnail_pic != null     && !"".equals(status.retweeted_status.thumbnail_pic)) {    return true;   }  }  return false; } public static User getUser(Activity activity, long uid) {  return getUser(activity, uid, null, false, null); } public static User getUser(Activity activity, String screen_name) {  return getUser(activity, 0, screen_name, false, null); } public static User getUser(Activity activity, long uid, String screen_name,   boolean async, RequestListener listener) {  String url = Weibo.SERVER + "users/show.json";  Weibo weibo = Tools.getWeibo(activity);  if (weibo == null || !weibo.isSessionValid()) {   return null;  }  User user = null;  WeiboParameters bundle = new WeiboParameters();  bundle.add("source", Consumer.consumerKey);  if (uid > 0) {   bundle.add("uid", String.valueOf(uid));  } else if (screen_name != null) {   bundle.add("screen_name", screen_name);  } else {   return user;  }  try {   if (!async) {    String json = weibo.request(activity, url, bundle, "GET",      weibo.getAccessToken());    user = new User();    JSONAndObject.convertSingleObject((Object) user, json);   } else {    AsyncWeiboRunner asyncWeiboRunner = new AsyncWeiboRunner(weibo);    asyncWeiboRunner      .request(activity, url, bundle, "GET", listener);   }  } catch (Exception e) {  }  return user; }}

只看 getHomeTimeline()这个方法,一直追踪,很快就可以知道这个微博数据是怎么得到的了。
 public static List<Status> getHomeTimeline(Activity activity,   long sinceId, long maxId, int count, boolean async,   RequestListener listener) {  // 访问接口url  String url = Weibo.SERVER + "statuses/home_timeline.json";  // 获取微博对象  Weibo weibo = Tools.getWeibo(activity);  if (weibo == null || !weibo.isSessionValid()) {   return null;  }  WeiboParameters bundle = new WeiboParameters();  bundle.add("source", Consumer.consumerKey);  if (sinceId != 0)   bundle.add("since_id", String.valueOf(sinceId));  if (maxId != 0)   bundle.add("max_id", String.valueOf(maxId));  if (count != 0)   bundle.add("count", String.valueOf(count));  List<Status> statuses = null;  try {   if (!async) {    // 请求获取JSON数据    String json = weibo.request(activity, url, bundle, "GET",      weibo.getAccessToken());    statuses = JSONAndObject      .convert(Status.class, json, "statuses");   } else {    AsyncWeiboRunner asyncWeiboRunner = new AsyncWeiboRunner(weibo);    asyncWeiboRunner      .request(activity, url, bundle, "GET", listener);   }  } catch (Exception e) {  }  return statuses; }

就是这个方法了,通过调用weibo对象的request()方法,返回Json字符串,通过解析得到的JSON字符串得到statuses数组。这里需要进行的转换,全靠JSONAndObject这个类
package com.wwj.sina.weibo.library;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;import org.json.JSONArray;import org.json.JSONObject;import android.util.Log;import com.wwj.sina.weibo.interfaces.WeiboObject;public class JSONAndObject /**  * 将一个对象转换为JSON格式的字符串,只转换public类型的变量  *   * @param obj  * @return  */ public static String convertSingleObjectToJson(Object obj) {  String json = null;  if (obj == null) {   return json;  }  Field[] fields = obj.getClass().getFields();  json = "{";  // 开始转换每一个public类型的变量  for (int i = 0; i < fields.length; i++) {   try {    Field field = fields[i];    if (field.getType() == String.class) {     // 属性值为null, 用空字符串取代     String temp = ((field.get(obj) == null) ? "" : String       .valueOf(field.get(obj)));     // 处理字符串中的双引号     // JSON字符串中不能直接使用双引号     temp = temp.replaceAll("\"", "\\\\\"");     json += "\"" + field.getName() + "\":\"" + temp + "\"";    }    // long类型    else if (field.getType() == long.class) {     json += "\"" + field.getName() + "\":" + field.getLong(obj);    }    // int类型    else if (field.getType() == int.class) {     json += "\"" + field.getName() + "\":" + field.getInt(obj);    }    // boolean类型    else if (field.getType() == boolean.class) {     json += "\"" + field.getName() + "\":"       + field.getBoolean(obj);    }    // Object类型(WeiboObject类型)    else {     Object fieldObject = field.get(obj);     if (fieldObject instanceof WeiboObject) {      // 如果对象中含有对象类型的变量      // 递归生成JSON字符串      json += "\"" + field.getName() + "\":"        + convertSingleObjectToJson(fieldObject);     } else {      continue;     }    }    if (i < fields.length - 1) {     json += ",";    }   } catch (Exception e) {   }  }  json += "}";  return json; } /**  * 将obj转换为JSON字符串,该字符串必须是一个对象 其中obj必须是一个List,而且JSON字符串必须包含一个propertyName  * 制定的属性,属性值是JSON数组,该数组与obj指定的List对应 类似于hometimeline.json返回的JSON字符串的逆过程  *   * @param obj  * @param propertyName  * @return  */ public static String covertObjectToJson(Object obj, String propertyName) {  String json = null;  if (obj == null

猜你喜欢

转载自blog.csdn.net/gfjggtf/article/details/83857765