Twitter: @ketab n - 5pdf · 2020. 5. 3. · Twitter: @ketab_n. Twitter: @ketab_n. Twitter: @ketab_n
Android Twitter and C2DM Explained
-
Upload
rohit-ghatol -
Category
Education
-
view
3.769 -
download
0
description
Transcript of Android Twitter and C2DM Explained
Android Twitter Appand C2DM
By Rohit GhatolArchitect @ QuickOffice
Speaker Introduction
Speaker Introduction
• Rohit Ghatol• Architect @ QuickOffice• Proj Mgr @ Synerzip• Founder TechNext • Author “Beginning PhoneGap”
@Apress• Technical Speaker and Corporate
Trainer
Why Twitter App and C2DM in the same talk?
Poll Vs Push
Youtube Video Demo
• http://www.youtube.com/user/rohitssghatol#p/u/13/XhCZpxWDtx0
Twitter Requirements
OAuth AuthenticationFetch Tweets
Send TweetsBackground Sync
Revisit Android Building Blocks in Short
Activity LifeCycle
onCreate()
onDestroy()
onStart()
onStop()
onResume()
onPause()
CompleteLifeCycle
VisibleLifeCycle
Foreground VisibleLifeCycle
Calling Service
Activity
Service
void onStartCommand(Intent intent,…){}
Activity
Service
startService(intent)
bindService(intent)
foo();bar();
void foo(){}int bar(){}
Broadcast ReceiversApp 1
Android OS
App 2
Your App
Custom Event 1
Custom Event 2
Battery Low
RoamingCall
Network Change
Interested in any of these Events.
Overall Architecture
OAuth Authentication
First Time Launch
Asking Service To Fetch Tweets
Triggering Service every n minutes
Phone Boot Event
Battery Low Event
OAuth
Short Introduction to OAuth
http://fotofast.com
username
password
Login Cancel
http://fotofast.comWelcome Rohit
Picasa Flickr
Print Photo
http://fotofast.com
username
password
Login Cancel
Welcome Rohit
Enter Credentials for Picasa
If I go to a restaurant, do I give my ATM Card and Pin to the waiter to pay my bills?
Then Why should I give my Picasa Credentials to fotofast.com?
Take 2, Action
http://fotofast.com
username
password
Login Cancel
http://fotofast.comWelcome Rohit
Picasa Flickr
Print Photo
http://picasa.com
username
password
Login Cancel
Welcome to Picasa
Look Ma its Picasa itself asking for password!
http://picasa.com
Choose Album to Share with FotoFast
1 2
4 5
3
6
http://fotofast.comWelcome Rohit
Picasa Albums
Choose photo to Print Photo
Look Ma! I am able to print picasa photos from FotoFast
Twitter OAuth in Android
About OAuth
• The way OAuth works for Web is Browser redirects between the 2 sites
• Browser first shows FotoFast, which redirects you to Picasa to authenticate and approve sharing data with FotoFast
• On proper Authentication and Approval, Browser takes you back to FotoFast.com
How does the same work for Android Applications?
Steps of Twitter OAuth
Step 1 : Register with Twitter for OAuth Token
Step 2: Register your Activity to handle url “DroidTwit://twitt”
<activity android:name=".OAuthLogin" android:label="@string/app_name”android:launchMode="singleTask"><intent-filter>
<action android:name="android.intent.action.VIEW"></action><category
android:name="android.intent.category.DEFAULT"></category><category
android:name="android.intent.category.BROWSABLE"></category><data android:scheme="DroidTwit" android:host="twitt"></data>
</intent-filter></activity>
Step 3: Create a OAuth URL and ask browser to show it
OAuth URL also contains CallBack URL you URL can redirect back to
your activity
public static final String CALLBACK_URL ="DroidTwitt://twitt";
public void buttonClick(){OAuthSignpostClient client = new OAuthSignpostClient
(TWITTER_KEY, TWITTER_SECRET,CALLBACK_URL);
final URI twitterUrl = client.authorizeUrl();
//Start BrowserstartActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse(twitterUrl.toString())));}
Step 4: Handle Response from Browser after OAuth
@Overrideprotected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);final Uri uri = intent.getData();if ((uri != null) && uri.toString().startsWith(CALLBACK_URL)) {verifier = uri.getQueryParameter("oauth_verifier");
client.setAuthorizationCode(verifier);
accessTokenAndSecret = client.getAccessToken();
Log.e("NewIntent", "Access token: " + accessTokenAndSecret[0]);Log.e("NewIntent", "Token secret: " + accessTokenAndSecret[1]);}
}
For more details on Oauth in Android read
http://blog.copyninja.info/2010/09/android-oauth-authentication-with.html
Fetching From Twitter API
Guidelines
• Make the fetch module SynchronousList<Tweets> getLatestTweets();
• Either call directly or through Services
• Use AsyncTask on UI to avoid ANR
ListView Showing Tweets
Lets see a some code for this.
http://code.google.com/p/droidtwit/wiki/AndroidListActivityAsyncTaskTutorial
Need for List Adapter
Entry 1
1
2
3
4
List<Tweet>
Tweets
Something else
Data that can varyList View functionality is same
Layout can vary
Adapter Layer
public class MyAdapter extends BaseAdapter{
public int getCount(){ }
public Object getItem(int position){ }
public long getItemId(int position){ }
public View getView(int position,Convert view,..){ }}
List View Explained
Entry 1
Entry 2
Entry 3
Entry 4
1
2
3
4
1 Plank No.
Plank
List View Explained
Entry 1
Entry 2
Entry 3
Entry 4
1
2
3
4
1 Plank No.
Scroll
Entry 51
Plank 1 Reused when it pops out the top while scrolling
Thumbnails in ListView
Common Problem and How to solve it
Why is thumbnail is such a problem in ListView?
Entry 1
Entry 2
Entry 3
Entry 4
Thread 1
Thread 2
Threads to fetch image asynchronously
1
2
3
4
Thread 3
Thread 4
Why is thumbnail is such a problem in ListView?
Entry 5
Entry 6
Entry 7
Entry 8
Thread 1 Now Thread 1 returns image one and sets it on Plank 1, but Plank 1 should show image from Entry 5.
Wrong images are shown for Entry 5, till Thread 5 returns.
And for each scroll, again images are fetched
1
2
3
4
Thread 5
Solution
Entry 1
Entry 2
Entry 3
Entry 4
1
2
3
4Blocking Queue
Thread 1
Local Image Cache
Thread reads from Blocking Queue, checks the Image Cache, if Image not there, fetches it dumps in Image Cache and gives it to the Image View (If position is valid)
While Scrolling, we add entries in Blocking Queue
Class Diagram<<ImageLoader>>
void queue(String url, ImageView imageView);
<<ImageCache>>
void cache(String url, Bitmap bitmap);
BitMap get(String url);
PhotoToLoad
private String url;private ImageView imageView;
Uses BlockingQueue<PhotoToLoad> and has a thread which keeps running on the
BlockingQueue, to either fetch image from cache or from internet
Complete Example
• The complete example of the QueuedImageLoader can be found http://code.google.com/p/feedreader/source/browse/trunk/FifaLatestNews/src/com/latestnews/cache/QueuedImageLoader.java
Using Services
Lets see Code Demos for this
Complete Detailed Video of this is available on http://code.google.com/p/droidtwit/wiki/AndroidServiceTutorial
Using Alarm Manager
Lets see Code Demo
Listener Battery Event
Lets see Code Demo
C2DM
What is C2DM?
Cloud To Device Messaging
What is C2DM?
• Messages send from Server to Device via Google
• Small Messages only meant to tell the client, that server has new information
• Optimized and uses same channel as Gmail, Calendar and other google apps
Why C2DM?
Drawbacks of DroidTwitt
Battery Drain
• Application launching every 5/10/15 mins
• Not sure if we will get new information, blindly trying
• Way to optimize is using AlarmManager.setInExactRepeating(), but that only helps so much
Data Usage
• Polling means more use of Data
• If Server is not optimized, then it always sends a chunk of stale data, more bandwidth
• Ways to optimize is ask server to send data on top of what the client already has (say use the timestamp), but that only helps so much
Lag
• Notification using Polling will always have a Lag
• It ends up being a balancing act between Saving Battery and Freshness of the data
Traffic (Server Side)
• Every device, Every n minutes bombarding the Server
• Businesses won’t mind traffic as long it is adding real value. But is this real value?
Load (Server Side)
• Hitting Database blindly when getting traffic
• Servers need to optimized to know whether the polling requests will repeat very n minutes and they only hit database if they have change.
C2DM Players
Google Cloud
ApplicationServer
But Remember a User can have more than one Device!
C2DM Flow of Events
Google Cloud
ApplicationServer
Step 1: App Server goes Authentication with Google C2DM Cloud and gets a security token
Security TokenAppServer123
Google Cloud
ApplicationServer
Step 2: Device 1 Registers itself to Google C2DM Cloud, gets an Registration Id
Security TokenAppServer123
Google Cloud
ApplicationServer
Step 3: Device 1 tells App Server that its C2DM Reg Id is XYZ
Device Info Reg IdRohit’s Phone XYZ
XYZ
Security Token
AppServer123
Google Cloud
ApplicationServer
Device Info Reg IdRohit’s Phone XYZ
Step 4: App Server sends message to C2DM intended for Device with Reg Id XYZ
Security TokenAppServer123
Google Cloud
ApplicationServer
Device Info Reg IdRohit’s Phone XYZ
Step 6: Google C2DM Cloud Service sends Intent to Device with Reg id XYZ
Security TokenAppServer123
Google Cloud
ApplicationServer
Device Info Reg IdRohit’s Phone XYZ
Step 7: Device fetches data from App Server to process
Security TokenAppServer123
C2DM Demo
Lets see the Demo
Steps for C2DM
Step 1: Create AVD for Emulator
• Create a AVD With Google API 8 (not Android API 8)
Step 1: Create AVD for Emulator
• Go to Settings and Add a Google Account
Step 2: Server Side Authentication//Create URL for Google Authentication for C2DMStringBuilder builder = new StringBuilder();//Has to be C2DM Registered Email Addressbuilder.append("Email=").append(email);builder.append("&Passwd=").append(password);builder.append("&accountType=GOOGLE");builder.append("&source=MyLittleExample");builder.append("&service=ac2dm");
byte[] data = builder.toString().getBytes();
Server Side Code
One Time
Step 2: Server Side Authentication// Setup the Http PostURL url = new URL("https://www.google.com/accounts/ClientLogin");HttpURLConnection con = (HttpURLConnection) url.openConnection();……con.setRequestMethod("POST");con.setRequestProperty("Content-Type”, "application/x-www-form-urlencoded");
con.setRequestProperty("Content-Length", Integer.toString(data.length));
Server Side Code
One Time
Step 2: Server Side Authentication// Issue the HTTP POST requestOutputStream output = con.getOutputStream();output.write(data);output.close();
//Read Auth Token ResponseBufferedReader reader = new BufferedReader(new InputStreamReader(
con.getInputStream()));String line = null, auth_key = null;while ((line = reader.readLine()) != null) {
if (line.startsWith("Auth=")) {auth_key = line.substring(5);
}}
Server Side Code
One Time
Step 3: Android Manifest<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sparklytix.factoreal" android:versionCode="1"android:versionName="1.0"><uses-sdk android:minSdkVersion="8" /><permission
android:name="com.sparklytix.factoreal.permission.C2D_MESSAGE"android:protectionLevel="signature" />
<uses-permissionandroid:name="com.sparklytix.factoreal.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
Android Code
Step 3: Android Manifest<receiver android:name=".receivers.C2DMBroadCastReceiver”
android:permission="com.google.android.c2dm.permission.SEND"> <!-- Receive the actual message -->
<intent-filter><action
android:name="com.google.android.c2dm.intent.RECEIVE" /><category android:name="com.sparklytix.factoreal" />
</intent-filter><!-- Receive the registration id --><intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.sparklytix.factoreal" /></intent-filter>
</receiver>
Android Code
Step 4: Send C2DM Device Reg Reqpublic void register(Context context, String sender) {
Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER"); //app is this application itself
intent.putExtra("app",PendingIntent.getBroadcast(context, 0, new
Intent(), 0)); //sender is typical gmail account on the device
intent.putExtra("sender”,sender);context.startService(intent);
}
Android Code
Step 5: Get Device Reg Idpublic void onReceive(Context context, Intent intent) { if(“com.google.android.c2dm.intent.REGISTRATION”.equals(intent.getAction()){
final String registrationId = intent.getStringExtra("registration_id");String error = intent.getStringExtra("error");if (intent.getStringExtra("error") != null) {
// Registration failed, should try again later.} else if (intent.getStringExtra("unregistered") != null) {
//Remove Reg Id from Our Application Server} else if (registrationId != null) {
//Send Reg Id to Our Application Server}
}}
Android Code
Broadcast Receiver
Step 6: Send Message from ServerStringBuilder postDataBuilder = new StringBuilder();postDataBuilder.append(“registration_id”).append("=”).append
(registrationId);postDataBuilder.append("&").append(“collapse_key”).append("=")
.append("0");postDataBuilder.append("&").append("data.payload").append("=")
.append(URLEncoder.encode(message, UTF8));byte[] postData = postDataBuilder.toString().getBytes(UTF8);
Server Side Code
Step 6: Send Message from ServerURL url = new URL("https://android.clients.google.com/c2dm/send");HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();....conn.setRequestMethod("POST");conn.setRequestProperty("Content-Type“,"application/x-www-form-urlencoded;charset=UTF-8");conn.setRequestProperty("Content-Length",Integer.toString(postData.length));conn.setRequestProperty("Authorization", "GoogleLogin auth="
+ auth_token);OutputStream out = conn.getOutputStream();out.write(postData);out.close();
Server Side Code
Step 7: Receive Message at Android
public void onReceive(Context context, Intent intent) { if(“com.google.android.c2dm.intent.RECEIVE”.equals(intent.getAction()){
String payload = intent.getStringExtra("payload");//Create a Notification and fire it
}}
Android Code
Broadcast Receiver
Conclusion
• C2DM is an excellent way to– Reduce Data Usage and Save Battery on the
Device– And also reduce load and network contingency on
the Server– Also when device goes offline, Our App Server
does not have to queue, Google C2DM queues itself
• Definitely a better option than Polling
Detailed Tutorial
• http://www.vogella.de/articles/AndroidCloudToDeviceMessaging/article.html
• http://code.google.com/p/android-c2dm-reference-impl/
Code Projects referred
• Droid Twitt Project - http://code.google.com/p/droidtwitt
• Android Code Examples – http://code.google.com/p/droidtwitt
• Listing Thumbnails in ListView - http://code.google.com/p/feedreader/
• C2DM Server and Android App - http://code.google.com/p/android-c2dm-reference-impl/
Q & A
More about Me• Twitter - http://twitter.com/#!/rohitghatol • TechGig - http://www.techgig.com/rohitghatol • LinkedIn - http://www.linkedin.com/in/
rohitghatol• Presentations - www.slideshare.net/rohits
ghatol/ • YouTube Tutorials -
http://www.youtube.com/user/rohitssghatol