也学微博开发(四)-----保存认证信息、菜单栏和微博首页
前言
好些天没更新博客,这些天一直忙着研究教程和然后被一些知识点困住了,今天总算继欢迎界面,认证登录之后实现了,底部菜单栏和微博首页简单效果,并且保存认证后的accesstoken信息,避免每次都重复认证。
个人觉得要完成这节的内容,以下知识点学认真学习一下:
1.菜单栏用哪种方式,tabhost是怎么回事?
2.layout布局,包括组件摆放和使用xml实现“切换效果”如单击“按钮”前后的样式变化等
3.sina SDK的版本,使用那个直接影响那些文件需要自己新建,各种对象的使用。
4.理解微博里面的一些对象,如weibo,user,status,accesstoken,等等,
5.listview和Adapter问题
6.理清思路和流程,包括何时认证登录、在哪里保存信息,对象是创建还是获得实例引用。
先看效果图:
实现操作
在研究和网上众多版本的新浪微博和svn得来的源码后,把自己的微博开发都搞昏了,一度不知道下一步到底怎么弄,实践告诉我,没有事先理清楚框架是多么可怕的事情。
虽然现在简单实现了一些功能,但是结构不是很好,很多地方可以在此优化;
一、初次认证后保存AccessToken
关于保存认证信息很简单,我用的是SharedPreferences把认证得到的AccessToken对象里的token和secret保存起来,下面的getAccessTokenFirst() 方法是我自定义的,用来产生AccessToken(取得requesttoken在前面已经实现,不再此函数)并且保存起来:
private void getAccessTokenFirst() throws Throwable
{
Uri uri = this.getIntent().getData();
String oauth_verifier = uri.getQueryParameter("oauth_verifier");
MainService.mWeibo.addOauthverifier(oauth_verifier);
// 得到AccessToken的同时在generateAccessToken()函数内部已经赋值给weibo了
MainService.mWeibo.generateAccessToken(this, null);
SharedPreferences preferences = getSharedPreferences("UserAuthInfor", Context.MODE_PRIVATE);
Editor editor = preferences.edit();
// 通过Editor 的方法向参数文件写入内容
editor.putString("access_token_token", MainService.mWeibo.getAccessToken().getToken());
editor.putString("access_token_secret", MainService.mWeibo.getAccessToken().getSecret());
// 插入后一定要提交,才能完成保存
editor.commit();
}
既然第一次认证了,以后使用客户端就可以免登录(有效期内免登录),可以在之前取得requesttoken时先判断有无必要,具体思路是,从本地取出SharedPreferences保存的内容,如果已经认证过,那么一定可以取到不为空的token和secret,否者说明第一次使用,就去认证:
if (CheckAccessToken() != null)
{
Log.i(TAG, "---------CheckAccessToken() != null");
MainService.mWeibo.setAccessToken(CheckAccessToken());
Log.i(TAG, "token:" + MainService.mWeibo.getAccessToken().getToken() + "-------secret:"
+ MainService.mWeibo.getAccessToken().getSecret());
Intent it = new Intent(AuthorizeActivity.this, MainActivity.class);
startActivity(it);
finish();
} else
{
Log.i(TAG, "---------AuthorizeNow()");
setContentView(R.layout.main);
AuthorizeNow();
}
这段代码里面CheckAccessToken() 就是检查有无认证信息的,返回值是AccessToken或null:
// 检查SharedPreferences里是否有授权信息
public AccessToken CheckAccessToken()
{
AccessToken accessToken = null;
SharedPreferences preferences = getSharedPreferences("UserAuthInfor", Context.MODE_PRIVATE);
String token = preferences.getString("access_token_token", null);
String secret = preferences.getString("access_token_secret", null);
if (token == null || secret == null)
{
accessToken = null;
} else
{
accessToken = new AccessToken(token, secret);
}
return accessToken;
}
AuthorizeNow()当然就是去认证了,跳转到sina的认证页面共用户输入密码和用户名:
public void AuthorizeNow()
{
this.oauthNote = (TextView) this.findViewById(R.id.tvToken);
this.oauthBtn = (Button) this.findViewById(R.id.loginButton);
this.oauthBtn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if (v == oauthBtn)
{
MainService.mWeibo = Weibo.getInstance();
MainService.mWeibo.setupConsumerConfig(CONSUMER_KEY, CONSUMER_SECRET);
try
{
RequestToken requestToken = MainService.mWeibo.getRequestToken(
AuthorizeActivity.this, Weibo.APP_KEY, Weibo.APP_SECRET,
AuthorizeActivity.URL_ACTIVITY_CALLBACK);
oauthNote.setText(requestToken.getToken());
Uri uri = Uri.parse(Weibo.URL_AUTHENTICATION
+ "?display=wap2.0&oauth_token=" + requestToken.getToken()
+ "&from=" + AuthorizeActivity.FROM);
Log.i(TAG, "---------jump to browser for AUTHENTICATION");
startActivity(new Intent(Intent.ACTION_VIEW, uri));
finish();
} catch (WeiboException e)
{
e.printStackTrace();
}
}
}
});
}
二、实现菜单栏
这个还是比较繁复的,本人也叫不清楚,最好先看看api文档里的TabHost那些内容,它自带的案例比较清楚,我这的实现就是从那改过来的。先上代码:
Resources res = getResources();
TabHost tabHost = getTabHost();
TabHost.TabSpec spec;
Intent intent;
// 主页
intent = new Intent().setClass(this, HomePageActivity.class);
spec = tabHost.newTabSpec("homepage")
.setIndicator("主页", res.getDrawable(R.drawable.icon_1)).setContent(intent);
tabHost.addTab(spec);
// 信息
intent = new Intent().setClass(this, MSGActivity.class);
spec = tabHost.newTabSpec("msg").setIndicator("信息", res.getDrawable(R.drawable.icon_2))
.setContent(intent);
tabHost.addTab(spec);
// 我的资料
intent = new Intent().setClass(this, UserInfoActivity.class);
spec = tabHost.newTabSpec("2").setIndicator("我的资料", res.getDrawable(R.drawable.icon_3))
.setContent(intent);
tabHost.addTab(spec);
// 搜索
intent = new Intent().setClass(this, SearchActivity.class);
spec = tabHost.newTabSpec("3").setIndicator("搜索", res.getDrawable(R.drawable.icon_4))
.setContent(intent);
tabHost.addTab(spec);
// 更多
intent = new Intent().setClass(this, MoreItemsActivity.class);
spec = tabHost.newTabSpec("3").setIndicator("更多", res.getDrawable(R.drawable.icon_5))
.setContent(intent);
tabHost.addTab(spec);
// 显示主页
tabHost.setCurrentTab(0);
上面简单的就是为菜单的每个条目都设置了一个Activity,他们需要新建出来,比如第一个HomePageActivity就是我的微博主页Activity,这里Activity的跳转没有使用button。需要布局文件就不提了,官方案例直接拿来用修改一下。
三、首页显示好友说说
头像功能还没完善,现在只简单显示关注对象的“昵称”+“内容”。这里是在首页HomePageActivity里的代码,用到了listview绑定adapter。
public ListView allStatus;
//MyAdapter 是自定义的adapter继承父类BaseAdapter
MyAdapter ma = new MyAdapter(this, status);
Log.i(TAG, "---------new MyAdapter(this, status);");
allStatus.setAdapter(ma);
Log.i(TAG, "---------allStatus.setAdapter(ma);");
关键不再与这里的绑定,MyAdapter 类的实现才是重点,本人代码出错调试基本上都是这里的问题,重写一下getView()方法,在里面绑定用作listview每个item的样式文件。
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View statusView = null;
if ((convertView != null) && (convertView.findViewById(R.id.ivItemPortrait) != null))
{
Log.d("listview", "do getView " + position + " getOldTextView");
// 获取原来内存中保存的条目信息
statusView = convertView;
} else
{
Log.d("listview", "do getView " + position + " newTextView");
statusView = LayoutInflater.from(context).inflate(R.layout.itemview, null);
Log.d("listview", "after do getView " + position + " newTextView");
}
// 设定这个条目显示的内容
ViewHolder holder = null;
holder = new ViewHolder();
// holder.ivItemPortrait = (ImageView)
// statusView.findViewById(R.id.ivItemPortrait);
holder.tvItemName = (TextView) statusView.findViewById(R.id.tvItemName);
holder.tvItemContent = (TextView) statusView.findViewById(R.id.tvItemContent);
// 设定昵称
holder.tvItemName.setText(alls.get(position).getUser().getName());
// 设定内容
com.aven.util.TextAutoLink.addURLSpan(alls.get(position).getText(),
holder.tvItemContent);
// 更新头像
return statusView;
}
四、注意点
我的代码主要框架呢大概就是这样,这里面关于设定昵称要注意,从服务器获得json数据后解析出来,封装到status对相集合里面,这个status有的SDK里面已经定义好了比如weibo4j和weibo4jAndroid,但是weibo_sdk_source_code_0713却没有,甚至连很多基本的类都没有,所以说选SDk也是很重要的(对于没什么经验的初学者而言),本人就是开始的时候用了weibo_sdk_source_code_0713,现在搞的很麻烦,因为教程啊,资料啊都不是这个版本的。
还有就是关于菜单栏丢失的问题,在切换不同Activity时,有时候下面的菜单会不见了,这个经过百度,在两个地方有可以参考,一个是sina博客里面,有个人总结两种方法,我是看了她博文才解决的,还有就是博客园的“农民伯伯”这位大牛的文章有园友问过,我看了下有点类似,也向他请教了,但是不知道现在回复了没有。
小结
做到这sina微博客户端的模子已经出来啦,剩下的是完善其他页面,以及图片显示,代码优化了。文章里面又不对的地方还请各位园友指出,不吝赐教,欢迎交流。