This article describes how to build a Sina Weibo client. The following describes the source code of weibosina circulating on the Internet: http://download.csdn.net/detail/ryzhanglu/3453875.
1. Project Overview
The project file list is as follows:
The androidmanifest. xml file contains the following content:
<? XML version = "1.0" encoding = "UTF-8"?> <Manifest xmlns: Android = "http://schemas.android.com/apk/res/android" package = "cn.com. HH. view "Android: versioncode =" 1 "Android: versionname =" 1.0 "> <application Android: icon =" @ drawable/icon "Android: label = "@ string/app_name" Android: theme = "@ Android: style/theme. notitlebar. fullscreen "> <! -- Main activity --> <activity Android: Name = "cn.com. HH. view. myblogactivity "Android: Label =" @ string/app_name "> <intent-filter> <action Android: Name =" android. intent. action. main "/> <category Android: Name =" android. intent. category. launcher "/> </intent-filter> </activity> <! -- Register an authorized logon activity --> <activity Android: Name = "cn.com. HH. view. authorizeactivity "Android: launchmode =" singletask "> <intent-filter> <action Android: Name =" android. intent. action. view "/> <category Android: Name =" android. intent. category. default "/> <category Android: Name =" android. intent. category. browsable "/> <data Android: Scheme =" MyApp "Android: host =" authorizeactivity "/> </intent-filter> </activity> <! -- Register and log on to activity --> <activity Android: Name = "cn.com. HH. View. loginactivity"> <! -- <Intent-filter> --> <! -- <Action Android: Name = "android. Intent. Action. View"/> --> <! -- <Category Android: Name = "android. Intent. Category. Default"/> --> <! -- <Category Android: Name = "android. Intent. Category. browsable"/> --> <! -- <Data Android: Scheme = "MyApp" Android: host = "authorizeactivity"/> --> <! -- </Intent-filter> --> </activity> <! -- Register and log on to activity --> <activity Android: Name = "cn.com. HH. View. homeactivity"> </activity> <! -- Register and log on to activity --> <activity Android: Name = "cn.com. HH. view. viewactivity "> </activity> </Application> <uses-Permission Android: Name =" android. permission. internet "/> </manifest>
2. oau2certification
To talk about oauth authorization, Sina open API must be called on this basis, so it is necessary to talk about it in detail, as mentioned in the previous article, Sina Weibo provides oauth and base oauth authentication methods, and this project adopts the oauth authentication method, the reason why this oauth authentication is adopted instead of base oauth authentication is very simple. Since Twitter only supports the oauth authentication method, many applications have switched to the oauth authentication method, sina Weibo's open platform will also suspend the base oauth authentication method recently.
Oauth provides a secure, open, and simple standard for user resource authorization. Unlike the previous authorization method, oauth does not allow a third party to access user account information (such as user name and password ), that is, a third party can apply for authorization to the user's resources without using the user name and password. Therefore, oauth is secure. Similarly, Sina Weibo provides oauth to ensure the security of user accounts and passwords. Here, we use oauth to create common Sina Weibo users and client programs (the android client program we are developing) and Sina Weibo, so that the client program (the android client program we are developing) can browse and publish Weibo without having to know the user's account and password, this effectively protects the security of user accounts, and does not need to disclose the account and password to the client program. In addition, the client program writes Weibo to view Weibo. This is the role of oauth.
Based on the oauth authentication of Sina Weibo, let's talk about the specific function implementation. First, let's list the keyword groups. The following four sets of keywords have a great relationship with our next oauth authentication.
Group 1: (APP key and app secret). This set of parameters is the one mentioned in the first article of this series to create a new application to obtain the app key and app secret.
Second group: (request token and request Secret)
Group 3: (oauth_verifier)
Group 4: (user_id, access token, and access secret)
In the oauth authentication process of Sina Weibo, when a user uses the client software for the first time, the client program initiates a request to Sina Weibo using the first group as the parameter, after the verification, Sina Weibo returns the second set of parameters to the client software, indicating that Sina Weibo trusts the client software, when the client software obtains the second set of parameters, as a parameter, it directs the user's browser to jump to the authorization page of Sina Weibo. Then, the user enters his Weibo account and password on the Authorization page of Sina for authorization, after authorization, the third group of parameters are returned to the client software based on the callback address set by the client, indicating that the user also trusts the client software, next, the client software sends a request to Sina Weibo again using the second and third sets of parameters as parameters, and then Sina Weibo returns the fourth set of parameters to the client software, the fourth set of parameters must be properly saved. This is used to replace the user's Sina account and password. It is required for subsequent API calls. In this process, the user only entered the account and password on the Sina Weibo Certification Page, and did not enter the account and password in the client software, the client software only saves the fourth group of data and does not save the user's account and password, which effectively avoids disclosure of the account and password to third-party applications outside Sina Weibo, ensuring
Security.
This project uses the oauth-Signpost open-source project for oauth authentication development to facilitate development, and creates oauth. java files encapsulate OA in a simple way. The oauth class mainly includes three methods: requestaccesstoken, getaccesstoken, and signrequest. The first method, requestaccesstoken, is used to obtain the third set of parameters in the above process, the getaccesstoken method is used to obtain the fourth set of parameters, and the signrequest method is used to call APIs. The use of the oauth-Signpost open-source project is much simpler. The Code is as follows:
Public class oauth {private commonshttpoauthconsumer httpoauthconsumer; private oauthprovider httpoauthprovider; Public String consumerkey; Public String consumersecret; Public oauth () {// First group: (APP key and app secret) // This set of parameters is described in the first article of this series to create a new application to obtain the app key and app secret. This ("3315495489", "e2731e7grf592c0fd7fea32406f86e1b");} public oauth (string consumerkey, string consumersecret) {This. consumerkey = consumerkey; this. consumersecret = consumersecret;} public Boolean requestaccesstoken (activity, string callbackurl) {Boolean ret = false; try {httpoauthconsumer = new consume (consumerkey, consumersecret ); httpoauthprovider = new defaultoauthprovider ("http://api.t.sina.com.cn/oauth/request_token", "http://api.t.sina.com.cn/oauth/access_token", "http://api.t.sina.com.cn/oauth/authorize"); string authurl = httpoauthprovider. retrieverequesttoken (httpoauthconsumer, callbackurl); activity. startactivity (new intent (intent. action_view, Uri. parse (authurl); ret = true;} catch (exception e) {} return ret;} public userinfo getaccesstoken (intent) {userinfo user = NULL; uri uri = intent. getdata (); string verifier = Uri. getqueryparameter (oauth. signpost. oauth. oauth_verifier); try {httpoauthprovider. setoauth10a (true); httpoauthprovider. retrieveaccesstoken (httpoauthconsumer, verifier);} catch (oauthmessagesignerexception ex) {ex. printstacktrace ();} catch (oauthnotauthorizedexception ex) {ex. printstacktrace ();} catch (oauthexpectationfailedexception ex) {ex. printstacktrace ();} catch (oauthcommunicationexception ex) {ex. printstacktrace ();} sortedset <string> user_id = httpoauthprovider. getresponseparameters (). get ("user_id"); string userid = user_id.first (); string userkey = httpoauthconsumer. gettoken (); string usersecret = httpoauthconsumer. gettokensecret (); User = new userinfo (); User. setuserid (userid); User. settoken (userkey); User. settokensecret (usersecret); Return user;} public httpresponse signrequest (string token, string tokensecret, string URL, list Params) {httppost post = new httppost (URL ); // httpclient = NULL; try {post. setentity (New urlencodedformentity (Params, HTTP. utf_8);} catch (unsupportedencodingexception e) {e. printstacktrace ();} // disable the keep CT: 100-continue handshake // 100-continue handshake must be used with caution, this is because a server or proxy that does not support HTTP/1.1 may cause a problem post. getparams (). setbooleanparameter (coreprotocolpnames. token, false); Return signrequest (token, tokensecret, post);} public httpresponse signrequest (string token, string tokensecret, httppost post) {httpoauthconsumer = new token (consumerkey, token ); httpoauthconsumer. settokenwithsecret (token, tokensecret); httpresponse response = NULL; try {httpoauthconsumer. sign (post);} catch (oauthmessagesignerexception e) {e. printstacktrace ();} catch (oauthexpectationfailedexception e) {e. printstacktrace ();} catch (oauthcommunicationexception e) {e. printstacktrace ();} // get http Response try {response = new defaulthttpclient(.exe cute (post);} catch (clientprotocolexception e) {e. printstacktrace ();} catch (ioexception e) {e. printstacktrace ();} return response ;}}
2. Authentication Interface
According to the above introduction, we know that you need to obtain the user's authorization to get the operation permission on the user's Sina Weibo, which is handled in the project. The interface is as follows:
After entering the application, the user will go to the authorization interface for Sina Weibo, click "start", and start the browser to enter the Sina Weibo authorization interface, which was created by Sina, it has nothing to do with this application. After the user enters the account and password, click "authorize" to perform the authorization operation. The source code of this interface is as follows:
Public class authorizeactivity extends activity {private dialog; private oauth auth; Private Static final string callbackurl = "MyApp: // authorizeactivity"; @ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. authorize); view diaview = view. inflate (this, R. layout. dialog, null); dialog = new dialog (authorizeactivity. this, R. style. dia Log); dialog. setcontentview (diaview); dialog. show (); imagebutton stratbtn = (imagebutton) diaview. findviewbyid (R. id. btn_start); stratbtn. setonclicklistener (New onclicklistener () {public void onclick (view arg0) {auth = new oauth ("30632531", "f539cb169860ed99cf8c1861c5da34f6"); Auth. requestaccesstoken (authorizeactivity. this, callbackurl) ;}}) ;}@ overrideprotected void onnewintent (intent) {super. onne Wintent (intent); // here the oauth_verifier parameter userinfo user = Auth. getaccesstoken (intent); If (user! = NULL) {datahelper helper = new datahelper (this); string uid = user. getuserid (); If (helper. haveuserinfo (UID) {helper. updateuserinfo (User); log. E ("userinfo", "Update");} else {helper. saveuserinfo (User); log. E ("userinfo", "add ");}}}}
From the source code, we can find that on the authorizeactivity interface, the user clicks "authorize" and re-enters the authorizeactivity interface (this step corresponds to androidmanifest. in the XML file, the authorizeactivity item is configured), and The onnewintent interface is called.
Note that after successful authorization, the authorizeactivity interface is re-displayed. After the onnewintent function is executed, other interfaces are not automatically displayed. Add a new jump code.
3. onnewintent call time
This section describes the onnewintent call time.
Override the following methods in intentactivity: oncreate onstart onrestart onresume onpause onstop ondestroy onnewintent
3.1 If other applications send intent messages, perform the following methods:
I // @ philn (12410): oncreate
I // @ philn (12410): onstart
I // @ philn (12410): onresume
Intent sending method:
Uri uri = URI. parse ("philn: // blog.163.com ");
Intent it = new intent (intent. action_view, Uri );
Startactivity (it );
3.2 receive intent statement:
<activity android:name="cn.com.hh.view.AuthorizeActivity" android:launchMode="singleTask"> <intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><data android:scheme="myapp" android:host="AuthorizeActivity" /></intent-filter> </activity>
3.3 If intentactivity is at the top of the task stack (Android: launchmode = "singletask" item in androidmanifest. xml configuration), that is, the previously opened activity is currently
I // @ philn (12410): onpause
I // @ philn (12410): The onstop status
If other applications send intent messages again, the execution sequence is as follows:
I // @ philn (12410): onnewintent
I // @ philn (12410): onrestart
I // @ philn (12410): onstart
I // @ philn (12410): onresume
During Android Application Development, it is very easy to start another activity from one activity and transmit some data to the new activity, however, when you need to bring the activity running in the background back to the foreground and transmit some data, there may be a small problem.
First, by default, when you start an activity through intent, even if the same running activity already exists, A new activity instance is created and displayed. To prevent the activity from being instantiated multiple times, we need to configure the activity loading mode (launchmode) in androidmanifest. XML to implement the single task mode, as shown below:
<activity android:label="@string/app_name" android:launchmode="singleTask"android:name="Activity1"></activity>
When launchmode is singletask, an activity is started through intent. If the system already has an instance, the system sends the request to the instance, the system will no longer call the oncreate method for processing the request data, but will call the onnewintent method, as shown below:
protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent);//must store the new intent unless getIntent() will return the old one processExtraData(); }
Do not forget that the system may kill the activity running in the background at any time. If this happens, the system will call the oncreate method instead of the onnewintent method, A good solution is to call the same data processing method in the oncreate and onnewintent methods, as shown below:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); processExtraData(); } protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent);//must store the new intent unless getIntent() will return the old one processExtraData() } private void processExtraData(){ Intent intent = getIntent(); //use the data received here }
4. Obtain Weibo data
After obtaining user authentication, you can obtain the fourth set of parameters and obtain user data in sequence.
In the project, this step is completed on the homeactivity interface. The source code for obtaining some functions of Weibo data is as follows:
Private void loadlist () {If (confighelper. nowuser = NULL) {} else {user = confighelper. nowuser; // display the current user name textview showname = (textview) findviewbyid (R. id. showname); showname. settext (user. getUserName (); oauth auth = new oauth (); string url = "http://api.t.sina.com.cn/statuses/friends_timeline.json"; // string url = "http://api.t.sina.com.cn/statuses/public_timeline.json"; List <basicnamevaluepair> Params = New arraylist <basicnamevaluepair> (); Params. add (New basicnamevaluepair ("Source", Auth. consumerkey); httpresponse response = Auth. signrequest (user. gettoken (), user. gettokensecret (), URL, Params); If (200 = response. getstatusline (). getstatuscode () {try {inputstream is = response. getentity (). getcontent (); reader = new bufferedreader (New inputstreamreader (is), 4000); stringbuilder buffer = New stringbuilder (INT) response. getentity (). getcontentlength (); try {char [] TMP = new char [1024]; int L; while (L = reader. read (TMP ))! =-1) {buffer. append (TMP, 0, L) ;}} finally {reader. close ();} string = buffer. tostring (); // log. E ("JSON", "RS:" + String); (Org. apache. HTTP. httpresponse) response ). getentity (). consumecontent (); jsonarray DATA = new jsonarray (string); For (INT I = 0; I <data. length (); I ++) {jsonobject d = data. getjsonobject (I); // log. E ("JSON", "RS:" + D. getstring ("created_at"); If (D! = NULL) {jsonobject u = D. getjsonobject ("user"); If (D. has ("retweeted_status") {jsonobject r = D. getjsonobject ("retweeted_status");} // Weibo ID string id = D. getstring ("ID"); string userid = u. getstring ("ID"); string username = u. getstring ("screen_name"); string usericon = u. getstring ("profile_image_url"); // log. E ("usericon", usericon); string time = D. getstring ("created_at"); string text = D. getstring ("text"); boolea N haveimg = false; If (D. has ("thumbnail_pic") {haveimg = true; // string thumbnail_pic = D. getstring ("thumbnail_pic"); // log. E ("thumbnail_pic", thumbnail_pic);} date startdate = new date (time); Date nowdate = calendar. getinstance (). gettime (); time = new dateutilsdef (). twodatedistance (startdate, nowdate); If (wblist = NULL) {wblist = new arraylist <weiboinfo> ();} weiboinfo W = new weiboinfo (); W. setid (ID); W. setuse RID (userid); W. setusername (username); W. settime (Time + "before"); W. settext (text); W. sethaveimage (haveimg); W. setusericon (usericon); wblist. add (w) ;}} catch (illegalstateexception e) {e. printstacktrace ();} catch (ioexception e) {e. printstacktrace ();} catch (jsonexception e) {e. printstacktrace () ;}} if (wblist! = NULL) {weiboadapater adapater = new weiboadapater (); listview msglist = (listview) findviewbyid (R. id. msglist); msglist. setonitemclicklistener (New onitemclicklistener () {public void onitemclick (adapterview <?> Arg0, view, int arg2, long arg3) {object OBJ = view. gettag (); If (OBJ! = NULL) {string id = obj. tostring (); intent = new intent (homeactivity. this, viewactivity. class); bundle B = new bundle (); B. putstring ("key", ID); intent. putextras (B); startactivity (intent) ;}}); msglist. setadapter (adapater) ;}} loadinglayout. setvisibility (view. gone );}
Perform operations on user data based on APIs provided by Sina. Here, we only obtain the microblog information published by the user. Its API is http://api.t.sina.com.cn/statuses/friends_timeline.json. Here, we also need to provide the fourth set of parameters, Params. Add (New basicnamevaluepair ("Source", Auth. consumerkey ));. The returned data is in JSON format and needs to be parsed. For JSON format parsing, see my blog post "basic knowledge of Android 11: JSON parsing and simple examples".
References:
Http://www.cnblogs.com/hll2008/archive/2011/01/03/1923674.html
And a series of articles