tag:blogger.com,1999:blog-63725372975602663492024-03-28T21:46:22.499-07:00Android DevelopmentAnonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-6372537297560266349.post-38786995207698102572016-04-25T04:09:00.000-07:002016-04-25T04:10:06.436-07:00LinkedIn Integration - Andorid <div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<h3 style="text-align: left;">
<b>Introduction</b></h3>
LinkedIn is one of the most popular social networking platforms available today. LinkedIn users can share status updates, respond to topics of interest, read the latest updates from contacts and companies, and participate in group discussions about topics that interest them. <br />
<br />
The popularity of social networking platforms like Facebook, LinkedIn, and Twitter means that mobile app developers are tightly integrating these services with their applications to allow users to share content on these sites without ever leaving an application. <br />
<br />
<h3 style="text-align: left;">
<b>Overview of SDK</b></h3>
<ul style="text-align: left;">
<li>The mobile SDK for <a href="http://www.solutionanalysts.com/services/mobile-app-development/" target="_blank">Android</a> increases your app's time to market by providing out-of-box support for LinkedIn natively inside your Android applications. </li>
</ul>
<ul style="text-align: left;">
<li>The Mobile SDK for Android requires the official LinkedIn Android application is also installed to support the SDK's capabilities. </li>
<li>The minimum supported version is Android 4.4.2 (API 19). </li>
</ul>
<h3 style="text-align: left;">
<b> </b></h3>
<h3 style="text-align: left;">
<b>SDK Features</b></h3>
<ul style="text-align: left;">
<li>Single sign-on (SSO) authentication, in conjunction with the LinkedIn mobile app. </li>
<li>A convenient wrapper for making authenticated calls to LinkedIn's REST APIs.</li>
<li>"Deep linking" to additional member data in the LinkedIn mobile app.</li>
<li>Sample application that demonstrate best-practice implementations of all of the SDK's features.</li>
</ul>
<br />
<h3 style="text-align: left;">
Please find steps below for LinkedIn integration in Android.</h3>
<h3 style="text-align: left;">
</h3>
<ul style="text-align: left;">
</ul>
<b>Step - 1 Create Application </b><br />
<ul style="text-align: left;">
<li>To Integrate LinkedIn in your <a href="http://www.solutionanalysts.com/services/mobile-app-development/" target="_blank">mobile</a> application, you need to create a new application using LinkedIn Developer’s Account. </li>
</ul>
<ul style="text-align: left;">
<li>Create application from LinkedIn developer account. <br />https://www.linkedin.com/developer/apps </li>
</ul>
<br />
<ul style="text-align: left;">
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4jH7i6l-ny7eJzSQYy2PmuGQ_Ph2zvv9C1rqM9Ht3_2v3Ke92wjN-UmgEfq-lPAe_69MBGnEx1s34T0dP_QLCLn1lVYgxc7Kmzpib32NWaKks3amYWX-d8QfH1a5xfFRXZbYdU8Ey68-K/s1600/Screen+Shot+2016-04-05+at+9.33.49+am.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4jH7i6l-ny7eJzSQYy2PmuGQ_Ph2zvv9C1rqM9Ht3_2v3Ke92wjN-UmgEfq-lPAe_69MBGnEx1s34T0dP_QLCLn1lVYgxc7Kmzpib32NWaKks3amYWX-d8QfH1a5xfFRXZbYdU8Ey68-K/s640/Screen+Shot+2016-04-05+at+9.33.49+am.png" width="640" /></a></div>
<br />
<br />
<b>Step - 2 Set the Application Permission</b><br />
<ul style="text-align: left;">
<li>Now, you need to set the Default Application Permissions.<br />And to do that, you have to select check box “r_basicprofile” and “r_emailaddress” and click on the “update” button to set the permission.</li>
</ul>
<br />
<ul style="text-align: left;">
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1sXD6ZO-vnaL5JetiGxRXaQYC1s9AUNJE8hLU1IL3rygw300DH9mqaxbxNph5m4PTZOZvLrYSI1hCVskt0NtkWR7xVJ_-G-gsK0Y-CreGituhtodBfAMbdaWvADTrhKZZJeZ0rMrubQFz/s1600/Screen+Shot+2016-04-05+at+9.34.18+am.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1sXD6ZO-vnaL5JetiGxRXaQYC1s9AUNJE8hLU1IL3rygw300DH9mqaxbxNph5m4PTZOZvLrYSI1hCVskt0NtkWR7xVJ_-G-gsK0Y-CreGituhtodBfAMbdaWvADTrhKZZJeZ0rMrubQFz/s320/Screen+Shot+2016-04-05+at+9.34.18+am.png" width="320" /></a></div>
<br />
<br />
<b>Step - 3 Download Mobile LinkedIn SDK</b><br />
<br />
Go to https://developer.linkedin.com/docs/android-sdk and download a Mobile SDK for Android.<br />
<br />
<br />
<b>Step - 4 Generate Hash Key</b><br />
<ul style="text-align: left;">
<li>We need to generate a hash key. This generated Hash key will integrate your app with Linkedin account.</li>
<li>Go to https://www.linkedin.com/developer/apps </li>
<li>Select your application name and click the Mobile tab. </li>
<li>Add the package name and generated hash key in your LinkedIn Application.</li>
<li>This hash key will authenticate your mobile application. </li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVs49cATAF4lUkwAb4CYKLY1T9WrbHjtuQ23WSd8ECqwnkIGNzfsEqbLdNNkT5APOnq1wxoJ-1MrFnsflWa8kF_sH_6zb7lsmnfPkPAlUggFbaCgzawvmV6CpkDAk1BzTdZhqSvWOOp2XO/s1600/Screen+Shot+2016-04-05+at+9.34.49+am.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="159" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVs49cATAF4lUkwAb4CYKLY1T9WrbHjtuQ23WSd8ECqwnkIGNzfsEqbLdNNkT5APOnq1wxoJ-1MrFnsflWa8kF_sH_6zb7lsmnfPkPAlUggFbaCgzawvmV6CpkDAk1BzTdZhqSvWOOp2XO/s320/Screen+Shot+2016-04-05+at+9.34.49+am.png" width="320" /></a></div>
<br />
<br />
<br />
<div style="text-align: left;">
<b>
Login</b></div>
<br />
<pre class="codestyle"><pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;">private static final </span>String <span style="color: #660e7a; font-style: italic; font-weight: bold;">topCardUrl </span>= <span style="color: green; font-weight: bold;">"https://" </span>+ <span style="color: #660e7a; font-style: italic; font-weight: bold;">host </span>+ <span style="color: green; font-weight: bold;">"/v1/people/~:(first-name,last-name,email-address,formatted-name,phone-numbers,public-profile-url,picture-url,picture-urls::(original))"</span>; </pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;">private static </span>Scope buildScope() {
<span style="color: navy; font-weight: bold;">return </span>Scope.<span style="font-style: italic;">build</span>(Scope.<span style="color: #660e7a; font-style: italic; font-weight: bold;">R_BASICPROFILE</span>, Scope.<span style="color: #660e7a; font-style: italic; font-weight: bold;">R_EMAILADDRESS</span>, Scope.<span style="color: #660e7a; font-style: italic; font-weight: bold;">W_SHARE</span>);
}</pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;">public void </span>loginLinkedin() {
LISessionManager.<span style="font-style: italic;">getInstance</span>(getApplicationContext()).init(<span style="color: navy; font-weight: bold;">this</span>,
<span style="font-style: italic;">buildScope</span>(), <span style="color: navy; font-weight: bold;">new </span>AuthListener() {
<span style="color: olive;">@Override</span><span style="color: olive;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;">public void </span>onAuthSuccess() {
APIHelper apiHelper = APIHelper.<span style="font-style: italic;">getInstance</span>(getApplicationContext());
apiHelper.getRequest(MainActivity.<span style="color: navy; font-weight: bold;">this</span>, <span style="color: #660e7a; font-style: italic; font-weight: bold;">topCardUrl</span>, <span style="color: navy; font-weight: bold;">new </span>ApiListener() {
<span style="color: olive;">@Override</span><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;"> public void </span>onApiSuccess(ApiResponse s) {
Log.<span style="font-style: italic;">e</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">TAG</span>, <span style="color: green; font-weight: bold;">"Profile json" </span>+ s.getResponseDataAsJson());
Log.<span style="font-style: italic;">e</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">TAG</span>, <span style="color: green; font-weight: bold;">"Profile String" </span>+ s.getResponseDataAsString());
<span style="color: navy; font-weight: bold;">try </span>{
Log.<span style="font-style: italic;">e</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">TAG</span>, <span style="color: green; font-weight: bold;">"Profile emailAddress" </span>+ s.getResponseDataAsJson().get(<span style="color: green; font-weight: bold;">"emailAddress"</span>).toString());
Log.<span style="font-style: italic;">e</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">TAG</span>, <span style="color: green; font-weight: bold;">"Profile formattedName" </span>+ s.getResponseDataAsJson().get(<span style="color: green; font-weight: bold;">"formattedName"</span>).toString());
<span style="color: #660e7a; font-weight: bold;">txtFirstName</span>.setText(s.getResponseDataAsJson().get(<span style="color: green; font-weight: bold;">"emailAddress"</span>).toString());
<span style="color: #660e7a; font-weight: bold;">txtLastName</span>.setText(s.getResponseDataAsJson().get(<span style="color: green; font-weight: bold;">"formattedName"</span>).toString()); </pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"> Picasso.<span style="font-style: italic;">with</span>(MainActivity.<span style="color: navy; font-weight: bold;">this</span>).load(s.getResponseDataAsJson().getString(<span style="color: green; font-weight: bold;">"pictureUrl"</span>))
.into(<span style="color: #660e7a; font-weight: bold;">imgProfilePic</span>);
}<span style="color: navy; font-weight: bold;">catch </span>(Exception e){
}
}
<span style="color: olive;">@Override</span><span style="color: olive;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;">public void </span>onApiError(LIApiError error) {
<span style="color: grey; font-style: italic;">//((TextView) findViewById(R.id.response)).setText(error.toString());</span><span style="color: grey; font-style: italic;"> </span>Toast.<span style="font-style: italic;">makeText</span>(getApplicationContext(), <span style="color: green; font-weight: bold;">"Profile failed " </span>+ error.toString(),
Toast.<span style="color: #660e7a; font-style: italic; font-weight: bold;">LENGTH_LONG</span>).show();
}
});
}
<span style="color: olive;">@Override</span><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;"> public void </span>onAuthError(LIAuthError error) {
Toast.<span style="font-style: italic;">makeText</span>(getApplicationContext(), <span style="color: green; font-weight: bold;">"failed " </span>+ error.toString(),
Toast.<span style="color: #660e7a; font-style: italic; font-weight: bold;">LENGTH_LONG</span>).show();
}
}, <span style="color: navy; font-weight: bold;">true</span>);</pre>
</pre>
<h4 style="text-align: left;">
Logout</h4>
</div>
<pre class="codestyle"><pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;">LISessionManager.<span style="font-style: italic;">getInstance</span>(getApplicationContext()).clearSession();</pre>
</pre>
<h4 style="text-align: left;">
Check Login
</h4>
<pre class="codestyle"><pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;">private boolean </span>isLogin(){
LISessionManager sessionManager = LISessionManager.<span style="font-style: italic;">getInstance</span>(getApplicationContext());
LISession session = sessionManager.getSession();
<span style="color: navy; font-weight: bold;">boolean </span>accessTokenValid = session.isValid();
<span style="color: navy; font-weight: bold;">return </span>accessTokenValid;
}</pre>
</pre>
<b>Share Message</b>
<br />
<pre class="codestyle"><pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;">private static final </span>String <span style="color: #660e7a; font-style: italic; font-weight: bold;">shareUrl </span>= <span style="color: green; font-weight: bold;">"https://" </span>+ <span style="color: #660e7a; font-style: italic; font-weight: bold;">host </span>+ <span style="color: green; font-weight: bold;">"/v1/people/~/shares"</span>;
</pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;">public void </span>shareMessage() {
APIHelper apiHelper = APIHelper.<span style="font-style: italic;">getInstance</span>(getApplicationContext());
apiHelper.postRequest(MainActivity.<span style="color: navy; font-weight: bold;">this</span>, <span style="color: #660e7a; font-style: italic; font-weight: bold;">shareUrl</span>, buildShareMessage(<span style="color: green; font-weight: bold;">"Hello World"</span>, <span style="color: green; font-weight: bold;">"Hello Title"</span>, <span style="color: green; font-weight: bold;">"Hello Descriptions"</span>, <span style="color: green; font-weight: bold;">"http://ankitthakkar90.blogspot.in/"</span>, <span style="color: green; font-weight: bold;">"https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ7yxE4LwG4HieBIXz35yzPKqdF5RZCqY_35Dq-YvjbPTUt74y8Yv7HFCew0E3TIascumbykrTa__0pdzFuKb0al3xYxc2Jzj1DIiO14oRHbm51IL7FMnYFSFVKervlri41xOo-mo6ir_9/s320/10333099_1408666882743423_2079696723_n.png"</span>), <span style="color: navy; font-weight: bold;">new </span>ApiListener() {
<span style="color: olive;">@Override</span><span style="color: olive;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;">public void </span>onApiSuccess(ApiResponse apiResponse) {
<span style="color: grey; font-style: italic;">// ((TextView) findViewById(R.id.response)).setText(apiResponse.toString());</span><span style="color: grey; font-style: italic;"> </span>Toast.<span style="font-style: italic;">makeText</span>(getApplicationContext(), <span style="color: green; font-weight: bold;">"Share success: " </span>+ apiResponse.toString(),
Toast.<span style="color: #660e7a; font-style: italic; font-weight: bold;">LENGTH_LONG</span>).show();
Log.<span style="font-style: italic;">e</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">TAG</span>, <span style="color: green; font-weight: bold;">"share success" </span>+ apiResponse.toString());
}
<span style="color: olive;">@Override</span><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;"> public void </span>onApiError(LIApiError error) {
<span style="color: grey; font-style: italic;">// ((TextView) findViewById(R.id.response)).setText(error.toString());</span><span style="color: grey; font-style: italic;"> </span>Toast.<span style="font-style: italic;">makeText</span>(getApplicationContext(), <span style="color: green; font-weight: bold;">"Share failed " </span>+ error.toString(),
Toast.<span style="color: #660e7a; font-style: italic; font-weight: bold;">LENGTH_LONG</span>).show();
}
});
} </pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;">public </span>String buildShareMessage(String comment,String title,String descriptions,String linkUrl,String imageUrl ){
String shareJsonText = <span style="color: green; font-weight: bold;">"{ </span><span style="color: navy; font-weight: bold;">\n</span><span style="color: green; font-weight: bold;">" </span>+
<span style="color: green; font-weight: bold;">" </span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">comment</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">:</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">" </span>+ comment + <span style="color: green; font-weight: bold;">"</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">," </span>+
<span style="color: green; font-weight: bold;">" </span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">visibility</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">:{ " </span>+
<span style="color: green; font-weight: bold;">" </span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">code</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">:</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">anyone</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">" </span>+
<span style="color: green; font-weight: bold;">" }," </span>+
<span style="color: green; font-weight: bold;">" </span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">content</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">:{ " </span>+
<span style="color: green; font-weight: bold;">" </span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">title</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">:</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">"</span>+title+<span style="color: green; font-weight: bold;">"</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">," </span>+
<span style="color: green; font-weight: bold;">" </span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">description</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">:</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">"</span>+descriptions+<span style="color: green; font-weight: bold;">"</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">," </span>+
<span style="color: green; font-weight: bold;">" </span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">submitted-url</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">:</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">"</span>+linkUrl+<span style="color: green; font-weight: bold;">"</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">," </span>+
<span style="color: green; font-weight: bold;">" </span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">submitted-image-url</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">:</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">"</span>+imageUrl+<span style="color: green; font-weight: bold;">"</span><span style="color: navy; font-weight: bold;">\"</span><span style="color: green; font-weight: bold;">" </span>+
<span style="color: green; font-weight: bold;">" }" </span>+
<span style="color: green; font-weight: bold;">"}"</span>;
<span style="color: navy; font-weight: bold;">return </span>shareJsonText;
}</pre>
</pre>
<div style="text-align: left;">
<b>Open Current User Profile
</b></div>
<pre class="codestyle"><pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;">public void </span>openUserProfile(){
DeepLinkHelper deepLinkHelper = DeepLinkHelper.<span style="font-style: italic;">getInstance</span>();
deepLinkHelper.openCurrentProfile(MainActivity.<span style="color: navy; font-weight: bold;">this</span>, <span style="color: navy; font-weight: bold;">new </span>DeepLinkListener() {
<span style="color: olive;">@Override</span><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: navy; font-weight: bold;"> public void </span>onDeepLinkSuccess() {
Log.<span style="font-style: italic;">e</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">TAG</span>, <span style="color: green; font-weight: bold;">"openUserProfile success"</span>);
}
<span style="color: olive;">@Override</span><span style="color: olive;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'Menlo'; font-size: 12.0pt;"><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;">public void </span>onDeepLinkError(LIDeepLinkError error) {
Log.<span style="font-style: italic;">e</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">TAG</span>, <span style="color: green; font-weight: bold;">"openUserProfile error" </span>+ error.toString());
}
});
}</pre>
<h3 style="text-align: left;">
</h3>
</pre>
<h3 style="text-align: left;">
<b>Best Practices </b>
</h3>
<b>Posting on member's behalf</b><br />
<ul style="text-align: left;">
<li> <span style="font-size: small;">Members assume that they will have control on what content is posted and shared on their behalf. You should assure users that you will not post or send mail on their behalf without their consent, and give them the option to edit content before it is posted or not share content if they choose.</span></li>
</ul>
<div style="text-align: left;">
<br /></div>
<b>Permission Request</b><br />
<ul style="text-align: left;">
<li>You should educate users on which permissions you are requesting and how this data will be used. LinkedIn does not support incremental permission request, so all permissions must be granted during the authorization step. </li>
</ul>
<ul style="text-align: left;">
<li> Requesting too many permissions may cause users not to authorize your application, so you should only ask for the permissions that you need. </li>
</ul>
<b>Authentication</b><br />
<ul style="text-align: justify;">
<li>Whenever possible, remind the user that they are logged into your application by displaying their name, portrait, and/or account settings. </li>
</ul>
<ul style="text-align: justify;">
<li>You should also avoid multiple log in prompts. </li>
</ul>
<ul style="text-align: justify;">
<li>Cache the user's access token after they grant your application and do not bring the user through the authentication flow again unless they log out or the access token expires or is otherwise invalid. </li>
</ul>
<ul style="text-align: justify;">
<li>You should allow the user to log out, and when they do log out you should destroy the access token you had been granted. </li>
</ul>
<h3 style="text-align: left;">
<b> </b></h3>
<h3 style="text-align: left;">
<b>Cancelling in-progress requests</b></h3>
During your application's workflow, you may wish to cancel any in-progress API requests. This is done by calling APIHelper.cancelCalls() method.<br />
<br />
<h3 style="text-align: left;">
<b>Using ProGaurd with your application </b></h3>
If you intend to use ProGuard on the release build of your mobile application, you will need to add the following lines to your project's proguard-project.txt file to preserve information required for the SDK to function properly:<br />
<br />
<b>proguard configuration</b><br />
<br />
-keep class com.linkedin.** { *; }<br />
-keepattributes Signature<br />
<br />
<h3 style="text-align: left;">
<b>Mobile vs. server-side access tokens </b></h3>
It is important to note that access tokens that are acquired via the Mobile SDK are only useable with the Mobile SDK, and cannot be used to make server-side REST API calls.<br />
<br />
Similarly, access tokens that you already have stored from your users that authenticated using a server-side REST API call will not work with the Mobile SDK.<br />
<br />
<h3 style="text-align: left;">
<b>Partnership Program</b></h3>
<ul style="text-align: left;">
<li>All other APIs (e.g. Connections, Groups, People Search, Invitation, Job Search, etc.) will require developers to become a member of one of our partnership programs. </li>
<li>Partnering with LinkedIn provides you with additional API functionality & data access, increased call limits & dedicated support.</li>
<li>Applications are only accepted when we feel that they're providing value to members, developers and LinkedIn.</li>
</ul>
<div style="text-align: left;">
https://developer.linkedin.com/partner-programs </div>
<br />
<h3 style="text-align: left;">
<b>References</b></h3>
<b></b>https://developer.linkedin.com/docs/android-sdk<br />
https://developer.linkedin.com/docs/android-sdk-auth<br />
https://developer.linkedin.com/downloads#androidsdk<br />
https://www.numetriclabz.com/android-linkedin-integration-login-tutorial/<br />
https://developer.linkedin.com/docs/oauth2<br />
https://developer.linkedin.com/partner-programs/apply<br />
https://developer.linkedin.com/support/developer-program-transition<br />
http://www.solutionanalysts.com/blog/step-by-step-developers-guide-to-integrate-linkedin-with-an-android-application/ <br />
<br />
<h4 style="text-align: left;">
You can <a href="https://github.com/ankitthakkar/LinkedinIntegration" target="_blank">Download source code</a> of this example from Github. </h4>
<br />
<b><br /></b>
</div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com144tag:blogger.com,1999:blog-6372537297560266349.post-60640016160458665642015-11-10T01:54:00.000-08:002015-11-16T04:29:18.018-08:00Facebook App Deep Linking - Andoid<div dir="ltr" style="text-align: left;" trbidi="on">
<span data-click-area="main">One of the most interesting aspects of
sharing to Facebook from your app is that when people engage with the feed stories posted from your app, those stories can send people to
your app or your app's Google Play listing, driving traffic and app
installs. You can implement this behavior using App Links.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ7yxE4LwG4HieBIXz35yzPKqdF5RZCqY_35Dq-YvjbPTUt74y8Yv7HFCew0E3TIascumbykrTa__0pdzFuKb0al3xYxc2Jzj1DIiO14oRHbm51IL7FMnYFSFVKervlri41xOo-mo6ir_9/s1600/10333099_1408666882743423_2079696723_n.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ7yxE4LwG4HieBIXz35yzPKqdF5RZCqY_35Dq-YvjbPTUt74y8Yv7HFCew0E3TIascumbykrTa__0pdzFuKb0al3xYxc2Jzj1DIiO14oRHbm51IL7FMnYFSFVKervlri41xOo-mo6ir_9/s320/10333099_1408666882743423_2079696723_n.png" width="295" /></a></div>
<div style="text-align: center;">
<b><span data-click-area="main"> App link Flow</span></b></div>
<span data-click-area="main"><br /></span>
<span data-click-area="main"><br /></span>
<b>Facebook's Mobile Hosting API for App Links:</b><br />
<br />
<span data-click-area="main"></span><br />
If your application doesn't have a
website for content you want to share to Facebook, you don't have public
web URLs which you can annotate to support App Links.<br />
<br />
For these types of apps, Facebook provides an App Links Hosting API
that will host App Links for you. With the Hosting API you can create
and manage your App Links for all the mobile environments you support.<br />
<br />
This is the typical flow to configure an App Link for a piece of content:<br />
<ol>
<li>Create a new App Link object. You can set up an object for one platform or several at the same time.</li>
<li>Save the App Link object ID that's returned.</li>
<li>Use that ID to get the URL you can use to share the content.</li>
<li>Configure additional platforms that you support.</li>
<li>If supporting Android, configure your app's manifest file for the configured URLs.</li>
</ol>
<br />
<span data-click-area="main"></span><b><span data-click-area="main"></span></b><span data-click-area="main">Please follow below steps for generate app linking.</span><b><span data-click-area="main"><br /></span></b><br />
<span data-click-area="main"><br /></span>
<span data-click-area="main">
<style type="text/css">P { margin-bottom: 0.21cm; }A:link { </style></span>For web service, In request Params we need to send below parameters.<br />
<br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<i><b>iOS: url, name<br />Android:
url, name</b></i><b></b></blockquote>
<br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<b>Step #1: </b>Generate App Access Token
(Ref.
<span style="color: navy;"><span lang="zxx"><u><a href="https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens" target="_blank">https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens</a></u></span></span>)</blockquote>
<br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<i>GET
/oauth/access_token?</i>
<i>client_id={app-id}</i>
<i>&client_secret={app-secret}</i>
<i>&grant_type=client_credentials</i></blockquote>
<br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<i></i><br />
<b>Step #2:</b>
Generate App Link using generated App Access Token (Ref.
<span style="color: navy;"><span lang="zxx"><u><a href="https://developers.facebook.com/docs/applinks/hosting-api" target="_blank">https://developers.facebook.com/docs/applinks/hosting-api</a></u></span></span>)</blockquote>
<br />
<span data-click-area="main"></span><br />
You create a new App Link object for a content targeted to iOS & Android like this<br />
<br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<i>curl
</i><span style="color: navy;"><span lang="zxx"><u><a href="https://graph.facebook.com/app/app_link_hosts" target="_blank"><i>https://graph.facebook.com/app/app_link_hosts</i></a></u></span></span><i>
\</i>
<style type="text/css">P { margin-bottom: 0.21cm; }</style>
<br />
<div style="margin-bottom: 0cm;">
-F access_token="APP_ACCESS_TOKEN"
\<br />
-F name="iOS App Link Object Example" \<br />
-F ios='
[<br />
{<br />
"url"
: "applinkFB://showApp/54eee6292658c7df25000004",<br />
"app_store_id" : 570281083,<br />
"app_name" : “appName”,<br />
},<br />
]' \<br />
-F android=' [<br />
{<br />
"url" :
"applinkFB://showApp/54eee6292658c7df25000004",<br />
"package" : "com.packagename”,<br />
"app_name" : “appName”,<br />
},<br />
]' \<br />
<br />
-F web=' {<br />
"should_fallback"
: false,<br />
}'</div>
<i><br /></i></blockquote>
<span data-click-area="main"></span><br />
A successful call returns an ID that represents the App Link object hosted on Facebook,<br />
for example:<br />
<br />
<i>Return
: {"id":"643402985734254"}</i><br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<i></i><br />
<b>Step #3:
</b>Using generated ID(YOUR_APP_LINK_HOST_ID) which represents the
App Link, you need to call another API which will return
"canonical_url"</blockquote>
<br />
<span data-click-area="main"></span><br />
You can retrieve the canonical URL that points to your new App Link object through this API call:<br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<br />
<i>curl -G
</i><span style="color: navy;"><span lang="zxx"><u><a href="https://graph.facebook.com/YOUR_APP_LINK_HOST_ID" target="_blank"><i>https://graph.facebook.com/YOUR_APP_LINK_HOST_ID</i></a></u></span></span><i>
\<br />-d access_token="APP_ACCESS_TOKEN" \<br />-d
fields=canonical_url \<br />-d pretty=true</i></blockquote>
<br />
<span data-click-area="main">Where <code>YOUR_APP_LINK_HOST_ID</code> represents the id returned from creating your App Link object. Your response will look like this:</span> <br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<i><br />Return:<br />{</i>
<i>"canonical_url": </i><span style="color: navy;"><span lang="zxx"><u><a href="https://fb.me/643402985734254" target="_blank"><i>"https://fb.me/643402985734254"</i></a></u></span></span><i>,</i>
<i>"id": "643402985734254"<br />}</i></blockquote>
<br />
<span data-click-area="main">
<style type="text/css">P { margin-bottom: 0.21cm; }</style>
</span><br />
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
</blockquote>
<h3 id="intent-filter" style="text-align: left;">
Support sharesample URLs in Android</h3>
When a shared link is tapped your Android app is launched through the
URL specified in the App Link object you just created (if you didn't
specify a url, then it will use the canonical URL - i.e. the
https://fb.me/xxxxx URL). To set up your app to respond to this URL, you
need to add an intent filter in your app's manifest file.<br />
<br />
The filter
should respond to the <code><span class="pln">applinkFB</span></code> scheme (if you didn't specify a URL, then your filter should respond to the <i>fb.me</i> host and <i>https</i> scheme), handle implicit intents, and accept the <code>ACTION_VIEW</code> action. The example below adds an intent filter to the MainActivity that handles this:<br />
<br />
<span data-click-area="main"></span><br />
<pre class="brush:java;"><activity android:label="@string/app_name" android:name=".MainActivity">
...
<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="applinkFB">
</data></category></category></action></intent-filter>
</activity>
</pre>
<div style="text-align: left;">
<div class="prettyprint prettyprinted">
<span data-click-area="main">Once you've set up your web pages based App Links, </span></div>
<div class="prettyprint prettyprinted">
<span data-click-area="main">you're ready to <a href="https://developers.facebook.com/docs/applinks/android">handle incoming links</a> to your app.</span></div>
</div>
<br />
<h3 id="incoming">
Handling incoming links</h3>
<span data-click-area="main">To ensure an engaging user experience, you
should process the incoming intent information when your app is
activated and direct the person to the object featured in the story
they're coming from. </span><br />
<br />
<span data-click-area="main">For example, if I see a story on my Facebook feed
about one of my friends completing this share tutorial and I tap on it, I
will expect to be redirected to a view in your app that features this
tutorial and not to your app's main activity.</span><br />
<span data-click-area="main"><span data-click-area="main"></span></span><br />
If you use the App Links Hosting API, the <code>Intent</code> data will look like this:<br />
<br />
<span data-click-area="main"><span data-click-area="main"></span></span><br />
<div>
<pre class="prettyprint prettyprinted"><code><span class="pln">data</span><span class="pun">:</span><span class="pln"> </span><span class="str">"</span></code><code><span class="str">applinkFB://showApp/54eee6292658c7df25000004?target_url=https%3A%2F%2Ffb.me%2F643402985734299"</span><span class="pln">
extras</span><span class="pun">:</span><span class="pln">
al_applink_data</span><span class="pun">:</span><span class="pln"> </span><span class="pun"><</span><span class="typ">Bundle</span><span class="pln"> containing </span><span class="typ">App</span><span class="pln"> </span><span class="typ">Link</span><span class="pln"> data</span><span class="pun">></span></code></pre>
</div>
<br />
<span data-click-area="main"><span data-click-area="main">In the code sample below, we're simply
logging the target URL, but you should direct people through the
appropriated flow for your app:</span> </span><br />
<br />
<br />
<pre class="brush:java;">@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(this);
...
Uri targetUrl =
AppLinks.getTargetUrlFromInboundIntent(this, getIntent());
if (targetUrl != null) {
Log.i("Activity", "App Link Target URL: " + targetUrl.toString());
}
}
</pre>
<div>
<h3 class="prettyprint prettyprinted" style="text-align: left;">
<b><code><span class="pun">References:</span></code></b><code><span class="pun">
<style type="text/css">P { margin-bottom: 0.21cm; }A:link { }</style>
</span></code></h3>
<div style="margin-bottom: 0cm;">
You can get more details about overall
implementation
at</div>
<div style="margin-bottom: 0cm;">
<br />
<span style="color: navy;"><span lang="zxx"><u><a href="https://developers.facebook.com/docs/applinks/android" target="_blank">https://developers.facebook.com/docs/applinks/android</a></u></span></span><br />
<span style="color: navy;"><span lang="zxx"><u><a href="https://developers.facebook.com/docs/applinks/add-to-content" target="_blank">https://developers.facebook.com/docs/applinks/add-to-content</a></u></span></span><br />
<span style="color: navy;"><span lang="zxx"><u><a href="https://developers.facebook.com/docs/applinks/hosting-api">https://developers.facebook.com/docs/applinks/hosting-api</a></u></span></span></div>
<blockquote style="margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm;">
<br /></blockquote>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com67tag:blogger.com,1999:blog-6372537297560266349.post-67416121932097111032015-11-04T03:35:00.001-08:002015-11-10T01:54:24.253-08:00Twitter- Deep Linking with Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="margin-bottom: 0cm;">
<style type="text/css"></style><b>Twitter - Deep Linking for Mobile Developers</b><br />
<br />
The App Card provides the ability for users to download your app (if the
user doesn’t already have it installed), or deep-link into your own app
(if the app is already installed on the user’s mobile device).</div>
<div style="margin-bottom: 0cm;">
We can achieve this things with Twitter Card.<br />
<br />
<a href="https://dev.twitter.com/cards/mobile" target="_blank">https://dev.twitter.com/cards/mobile </a></div>
<br />
<div style="margin-bottom: 0cm;">
We need to make dynamic Web page and
host this page on any server which will be use for Sharing using Twitter from app. </div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
For
demonstration purpose, we have implemented the same functionality in
PHP with some hard-coded data but you need to convert in your
back-end technology with dynamic data.<br />
<br />
Please find PHP source code which we used for testing purpose.<br />
<br />
<b>Web Page Part </b></div>
<pre id="line1"><span class="error" title="Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”."><<span class="start-tag">html</span>></span>
<<span class="start-tag">head</span>>
<<span class="start-tag">title</span>>App Name</<span class="end-tag">title</span>>
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:card</a>" <span class="attribute-name">content</span>="<a class="attribute-value" href="https://www.blogger.com/null">summary</a>">
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:site</a>" <span class="attribute-name">content</span>="App Name">
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:title</a>" <span class="attribute-name">content</span>="App Name">
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:description</a>" <span class="attribute-name">content</span>="<a class="attribute-value" href="https://www.blogger.com/null">App Name is a 100% free social sharing app that allows sharing of video, photo, audio and text all in one network.</a>">
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:image</a>" <span class="attribute-name">content</span>="<a class="attribute-value" href="https://www.blogger.com/null">http://</a><a class="attribute-value" href="https://www.blogger.com/null">app_name.vm39.sa92.info/ico.png</a>">
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:url</a>" <span class="attribute-name">content</span>="<a class="attribute-value" href="https://www.blogger.com/null">http://appname.com/</a>">
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:app:name:iphone</a>" <span class="attribute-name">content</span>="appname"/>
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:app:id:iphone</a>" <span class="attribute-name">content</span>="<a class="attribute-value" href="https://www.blogger.com/null">570281083</a>"/>
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:app:name:googleplay</a>" <span class="attribute-name">content</span>="appname"/>
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:app:id:googleplay</a>" <span class="attribute-name">content</span>="<a class="attribute-value" href="https://www.blogger.com/null">com.</a><a class="attribute-value" href="https://www.blogger.com/null">appname</a>"/>
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:app:url:iphone</a>" <span class="attribute-name">content</span>="<a class="attribute-value" href="https://www.blogger.com/null">appname://show?bid=54e58b4360afd71a53001f5e</a>" />
<<span class="start-tag">meta</span> <span class="attribute-name">name</span>="<a class="attribute-value" href="https://www.blogger.com/null">twitter:app:url:googleplay</a>" <span class="attribute-name">content</span>="appname<a class="attribute-value" href="https://www.blogger.com/null">://show?bid=54e58b4360afd71a53001f5e</a>" />
</<span class="end-tag">head</span>>
<<span class="start-tag">body</span>>
<<span class="start-tag">h1</span>>Have something interesting here for particular Post, becasue when user click on link from Twitter it he/she will come to this page.</<span class="end-tag">h1</span>>
</<span class="end-tag">body</span>>
</pre>
<span id="line25"></span></<span class="end-tag">html</span>>
<br />
<br />
We have used summary card here. <br />
<a href="https://dev.twitter.com/cards/types/summary">https://dev.twitter.com/cards/types/summary</a><br />
<a href="https://dev.twitter.com/cards/types/app">https://dev.twitter.com/cards/types/app</a><br />
<br />
After making card, you have to validate your card with below URL.<br />
<a href="https://cards-dev.twitter.com/validator" target="_blank">https://cards-dev.twitter.com/validator</a><br />
<br />
<b>Android Part</b><br />
<br />
At Android side, we need to do below things.<br />
We need to add host and scheme in activity tag of Manifest file based on url defined in twitter app link url above.<b></b><br />
<b><br /></b>Please find below code snippets below for reference.<br />
<br />
AndroidManifest.xml<br />
<br />
<pre class="brush:java;"> <activity
android:name=".ui.activities.SplashActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:screenOrientation="sensorPortrait"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:label="@string/app_name" >
<action android:name="android.intent.action.VIEW" >
</action>
<category android:name="android.intent.category.DEFAULT" >
</category>
<category android:name="android.intent.category.BROWSABLE" >
</category>
<!-- Accepts URIs that begin with "example://action" -->
<data
android:host="show"
android:scheme="appname" >
</data>
</intent-filter>
</activity>
</pre>
<br />
In Activity, You can retrieve app link url in oncreate() method.<br />
With url, you can redirect user to our app's screen based on data retrieved from URL.<br />
<b><br /></b>Please find below code snippets below for reference.<br />
<br />
<b>onCreate() </b> <br />
<pre class="brush:java;">if (getIntent().getData() != null
&& getIntent().getData().toString().length() > 0) {
Logs.e(TAG, "Data:" + getIntent().getData());
if (getIntent().getData().toString().startsWith("appname")) {
twitterCallbackUrl = getIntent().getData().toString()
.substring(getIntent().getData().toString().lastIndexOf("?bid=") + 5,
getIntent().getData().toString().length());
Logs.e(TAG, "twitterCallbackUrl:" + twitterCallbackUrl);
}
}
</pre>
<div style="margin-bottom: 0cm;">
You can get additional information
about complete implementation at<br />
<a href="https://www.blogger.com/goog_1247686884"><br /></a>
<a href="https://dev.twitter.com/cards/getting-started">https://dev.twitter.com/cards/getting-started</a><br />
<span style="color: navy;"><span lang="zxx"><u><a href="https://dev.twitter.com/cards/mobile">https://dev.twitter.com/cards/mobile</a></u></span></span><br />
<span style="color: navy;"><span lang="zxx"><u><a href="https://dev.twitter.com/cards/mobile/url-schemes">https://dev.twitter.com/cards/mobile/url-schemes</a></u></span></span></div>
<pre id="line1"></pre>
<br />
<pre id="line1"></pre>
<pre id="line1"> </pre>
<pre id="line1"> </pre>
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com48tag:blogger.com,1999:blog-6372537297560266349.post-6120518045327474492015-08-16T07:18:00.002-07:002015-08-17T09:46:57.560-07:00Material design for Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"> Material design is a comprehensive guide for visual, motion, and interaction design across platforms and devices. Android now includes support for material design apps. To use material design in your Android apps, follow the guidelines defined in the <a href="http://www.google.com/design/spec/material-design/introduction.html" target="_blank">material design specification</a> and use the new components and functionality available in Android 5.0 (API level 21) and above.</span><br />
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br /></span>
<h4>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Android provides the following elements for you to build material design apps:</span></h4>
<h4>
<ul>
<li><span style="font-weight: normal;"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">A new theme</span></span></li>
<li><span style="font-weight: normal;"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">New widgets for complex views</span></span></li>
<li><span style="font-weight: normal;"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">New APIs for custom shadows and animations</span></span></li>
</ul>
</h4>
<h3>
</h3>
<h4>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: small;"><span style="font-weight: normal;">For more information about implementing material design on Android, see </span><a href="https://developer.android.com/training/material/index.html" style="color: #039be5; font-weight: normal; text-decoration: none;">Creating Apps with Material Design</a><span style="font-weight: normal;">.</span></span><br />
</h4>
<h3>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;">Material Theme</span></h3>
<h4>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: normal;">The material theme provides a new style for your app, system widgets that let you set their color palette, and default animations for touch feedback and activity transitions.</span><br />
</h4>
<div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2zLixQmcPQoUOm4hnwhkZJTZe5JDleABUMuEb3-5neqEAPBjPS1LsThBnY5x7eiXp9duUr5VK2c54OSGfxl9R9Ut-R6dmXV-9npv5Vb9mQ9nvMKCzIWGXo4tkdXI1zPMESG5czPEJECjY/s1600/MaterialLight.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2zLixQmcPQoUOm4hnwhkZJTZe5JDleABUMuEb3-5neqEAPBjPS1LsThBnY5x7eiXp9duUr5VK2c54OSGfxl9R9Ut-R6dmXV-9npv5Vb9mQ9nvMKCzIWGXo4tkdXI1zPMESG5czPEJECjY/s200/MaterialLight.png" width="200" /></span></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXgoMahEojJVkD-EV7QOixU56r8dXNWOlYNkqpFVoc9w1lpCIvoo-f781Ktgor05BIR3nzJIDKw30B9EsPKm7zdnSDVeugPDdXcrOcPEWrzASe7aY5X5UsF8XIwx3Oe5nUfR43PW6IkJmC/s1600/MaterialDark.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXgoMahEojJVkD-EV7QOixU56r8dXNWOlYNkqpFVoc9w1lpCIvoo-f781Ktgor05BIR3nzJIDKw30B9EsPKm7zdnSDVeugPDdXcrOcPEWrzASe7aY5X5UsF8XIwx3Oe5nUfR43PW6IkJmC/s200/MaterialDark.png" width="200" /></span></a><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span></div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;"> Dark material theme </span><span arial="" elvetica="" font-family:="" helvetica="" neue="" sans-serif="">Light material theme</span><span style="line-height: 24px;"> </span></span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<h3>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;">Lists and Cards</span></h3>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; line-height: 24px;">Android provides two new widgets for displaying cards and lists with material design styles and animations:</span><br />
<div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><span style="line-height: 24px;"><br /></span></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhSeNL1unIKv6GlyXMBTN0GIpNmFGvRCoa8c43jTkdXixNcS9GUXSUy2GBLuQHREF5jDCUEQunMWxbXsQPtKrcGR9nfI_Qak9Z7U-oqfjNfVxFmHlsZlcDleEmyCNaju2LCL_FC7v6wgzD/s1600/list_mail.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhSeNL1unIKv6GlyXMBTN0GIpNmFGvRCoa8c43jTkdXixNcS9GUXSUy2GBLuQHREF5jDCUEQunMWxbXsQPtKrcGR9nfI_Qak9Z7U-oqfjNfVxFmHlsZlcDleEmyCNaju2LCL_FC7v6wgzD/s320/list_mail.png" width="187" /></a></div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><span style="line-height: 24px;"><br /></span><span style="line-height: 24px;">The new RecyclerView widget is a more pluggable version of ListViewthat supports different layout types and provides performance improvements.</span></span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><span style="line-height: 24px;"><br /></span></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiINVqATOkcCCkvi3zEvMbeFWq4HOpnmu1FPKc4epXqof7rIIbX1ktmi-jq_bLwe23RJpqj6BxhpfmfWQkXtS5z_wA_HFlL6HDn7XpmhUS486WKMkGUDm5VKDzEj2Byaea7xm98ApZw1_I-/s1600/card_travel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiINVqATOkcCCkvi3zEvMbeFWq4HOpnmu1FPKc4epXqof7rIIbX1ktmi-jq_bLwe23RJpqj6BxhpfmfWQkXtS5z_wA_HFlL6HDn7XpmhUS486WKMkGUDm5VKDzEj2Byaea7xm98ApZw1_I-/s320/card_travel.png" width="187" /></a></div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; line-height: 24px;"><br /></span>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; line-height: 24px;">The new CardView widget lets you display important pieces of information inside cards that have a consistent look and feel.</span><br />
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; line-height: 24px;">For more information, see </span><a href="https://developer.android.com/training/material/index.html" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; line-height: 24px;" target="_blank">Creating Lists and Cards.</a><br />
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; font-size: large;"><br /></span>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span style="font-size: large;">View Shadows</span></span><br />
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">In addition to the X and Y properties, views in Android now have a Z property. This new property represents the elevation of a view, which determines:</span><br />
<ul>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">The size of the shadow: views with higher Z values cast bigger shadows.</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">The drawing order: views with higher Z values appear on top of other views.</span></li>
</ul>
<div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">For more information, see <a href="https://developer.android.com/training/material/shadows-clipping.html" target="_blank">Defining Shadows and Clipping Views.</a></span></div>
<div>
<br /></div>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span style="font-size: large;">Animations</span></span></div>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">The new animation APIs let you create custom animations for touch feedback in UI controls, changes in view state, and activity transitions.</span></div>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">These APIs let you:</span></div>
<div>
<ul>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Respond to touch events in your views with touch feedbackanimations.</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Hide and show views with circular reveal animations.</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Switch between activities with custom activity transitionanimations.</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Create more natural animations with curved motion.</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Animate changes in one or more view properties with view state change animations.</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Show animations in state list drawables between view state changes.</span></li>
</ul>
</div>
<div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Touch feedback animations are built into several standard views, such as buttons. The new APIs let you customize these animations and add them to your custom views.</span></div>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">For more information, see</span><a href="https://developer.android.com/training/material/animations.html" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;" target="_blank"> Defining Custom Animations</a><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">.</span></div>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br /></span></div>
<h3>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span style="font-size: large;">Drawables</span></span></h3>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">These new capabilities for drawables help you implement material design apps:</span></div>
<div>
<ul>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Vector drawables are scalable without losing definition and are perfect for single-color in-app icons.</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Drawable tinting lets you define bitmaps as an alpha mask and tint them with a color at runtime.</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Color extraction lets you automatically extract prominent colors from a bitmap image</span></li>
</ul>
<div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">For more information, see<a href="https://developer.android.com/training/material/drawables.html" target="_blank"> Working with Drawables.</a></span></div>
</div>
<div>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br /></span></div>
<h3>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: normal;"><span style="font-size: large;">References:</span></span></h3>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><a href="https://developer.android.com/design/get-started/principles.html">https://developer.android.com/design/get-started/principles.html</a></span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><a href="http://www.google.com/design/spec/material-design/introduction.html">http://www.google.com/design/spec/material-design/introduction.html</a></span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><a href="https://developer.android.com/design/get-started/principles.html" target="_blank">https://developer.android.com/design/material/index.html </a></span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><a href="https://www.youtube.com/watch?v=p4gmvHyuZzw">https://www.youtube.com/watch?v=p4gmvHyuZzw</a></span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><a href="https://www.youtube.com/watch?v=XOcCOBe8PTc">https://www.youtube.com/watch?v=XOcCOBe8PTc</a></span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><a href="https://www.youtube.com/watch?v=YaG_ljfzeUw">https://www.youtube.com/watch?v=YaG_ljfzeUw</a></span></div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com146tag:blogger.com,1999:blog-6372537297560266349.post-60217136824142383072014-10-17T06:38:00.000-07:002014-10-18T04:51:50.177-07:00Publish status on user's fan page/friend page using Facebook SDK<div dir="ltr" style="text-align: left;" trbidi="on">
This blog useful when we have to update status on user's fan page/friend page instead of user's wall using Facebook sdk.<br />
<br />
This kind of functionality implemented in Instagram. <br />
After a lots of search I have find some useful things which is useful to me. <br />
I would like to share this thing with you. This might be useful to u also.<br />
<br />
<b>Parameter list Used in Request:</b><br />
<ul style="text-align: left;">
<li>name </li>
<li>caption</li>
<li>description </li>
<li>picture</li>
<li>link </li>
<li>to</li>
<li>message </li>
</ul>
This is parameter required when we want to post on user's fan page. You can add or remove more parameter as per requirement.<br />
<br />
We have to pass bundle in parameter so bundle created for parameter. <br />
<pre class="brush:java;">Bundle requestParams =new Bundle ();
requestParams.putString(
"picture", filePath);
requestParams.putString("name",
TheApplication.getInstance().getString(R.string.app_name));
requestParams.putString("link",
"http://url");</pre>
<b>Permission:</b> <br />
<pre class="brush:java;"> <string-array name="fb_advance_permissions">
<item>manage_pages</item>
</string-array>
<code></code>
</pre>
<b>
1.) Retrieve login user's page list</b><br />
<br />
This method retrieve page list created by login user.<b>
</b>
<b>manage_page </b>permission required to fetch user's page list.
<br />
<pre class="brush:java;">/**
* retrieve facebook user page list and ask for permission
*
* @param pageListener
* - call success, error
*/
public static void getUserPageList(
final IFacebookCommonListener<String> pageListener) {
Session session = Session.getActiveSession();
sFBRedirectionState = FbRedirectionState.GET_PAGE_LIST;
getPagesCallback = pageListener;
if (getPagesCallback == null) {
return;
}
if (session != null) {
// if (!session.isOpened()) {
// openSession();
// }
if (!session.isOpened()) {
Logs.d(DEBUG_FACEBOOK_PUBLISH,
"Page error: !session.isOpened()");
closeSession();
openSession();
return;
}
if (!canRetrievePages() && !isPagePermissionCalled) {
getPagesPermissions(mStatusCallback);
isPagePermissionCalled = true;
return;
}
if (!canRetrievePages() && isPagePermissionCalled) {
if (pageListener != null) {
pageListener.onError("Facebook can't retrieve pages");
}
session.removeCallback(statusCallback);
sFBRedirectionState = FbRedirectionState.NONE;
isPagePermissionCalled = false;
return;
}
try {
/* make the API call */
Request request = new Request(session, "/me/accounts", null,
HttpMethod.GET, new Request.Callback() {
public void onCompleted(Response response) {
/* handle the result */
Logs.e(TAG, "Response:" + response);
if (response.getError() == null) {
Logs.d("Pages",
"Page success"
+ response.getRawResponse());
if (pageListener != null) {
pageListener.onSuccess(response
.getRawResponse());
}
} else {
Logs.d("Pages", "Page error: "
+ response.getError()
.getErrorMessage());
if (pageListener != null) {
pageListener
.onError("Facebook can't retrieve pages");
}
}
}
});
Bundle requestParams = request.getParameters();
requestParams.putString("access_token",
session.getAccessToken());
request.setParameters(requestParams);
request.executeAsync();
} catch (Exception e) {
// TODO: handle exception
if (pageListener != null)
pageListener.onError("Facebook can't retrieve pages");
}
sFBRedirectionState = FbRedirectionState.NONE;
getPagesCallback = null;
isPagePermissionCalled = false;
} else {
startLogin();
}
}
</pre>
<b>2.) This method check for permission.</b><br />
Check user has authorize permission or not.<br />
<pre class="brush:java;">/**
* check for user's has taken manage_pages permission
*
* @return
*/
private static boolean canRetrievePages() {
Session session = FacebookHelper.getSession();
if (session != null) {
try {
if (!session.isOpened()) {
openSession();
} else {
List<String> grantedPermissions = session.getPermissions();
String[] publishPermissions = mActivity.getResources()
.getStringArray(R.array.fb_advance_permissions);
return grantedPermissions.containsAll(Arrays
.asList(publishPermissions));
}
} catch (FacebookException e) {
Logs.d(TAG, e);
} catch (Exception e) {
Logs.d(TAG, e);
}
}
return false;
}
</pre>
<b>3.) Ask user for permission</b><br />
If user has not authorize permission. we have to authorize user for manage_page permission.
We can use below method to ask for permission from user.<br />
<pre class="brush:java;"> /**
* ask user for page permission.
*
* @param callback
*/
public static synchronized void getPagesPermissions(StatusCallback callback) {
Session session = FacebookHelper.getSession();
if (session != null) {
try {
if (!session.isOpened()) {
openSession();
}
List<String> grantedPermissions = session.getPermissions();
List<String> neededPermissions = new ArrayList<String>();
String[] publishPermissions = mActivity.getResources()
.getStringArray(R.array.fb_advance_permissions);
for (String p : publishPermissions) {
if (!grantedPermissions.contains(p)) {
neededPermissions.add(p);
}
}
if (!neededPermissions.isEmpty()) {
if (callback != null) {
session.removeCallback(callback);
session.addCallback(callback);
}
Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(
mActivity, neededPermissions);
session.requestNewPublishPermissions(newPermissionsRequest);
}
} catch (FacebookException e) {
Logs.e(TAG, e);
} catch (Exception e) {
Logs.e(TAG, e);
}
}
}
</pre>
<b>
</b>
<b>4.) Post on Fan page in background.</b><br />
We require page token which is we got from page list data. we get this token from page related data.
This token used for publish status on user's page.
Page id required on which we want to post data.<br />
<pre class="brush:java;">/**
* This method publish status on fan page
* @param requestParams - requested param
* @param uploadListener - for success, failure callback
*/
public static void postOnFanPage(Bundle requestParams,
final IFacebookCommonListener<Void> uploadListener) {
requestParams.putString("access_token",
Preferences.getFaceBookPageToken());
Request request = new Request(Session.getActiveSession(),
Preferences.getFacebookPageId() + "/feed", requestParams,
HttpMethod.POST, new Request.Callback() {
public void onCompleted(Response response) {
/* handle the result */
if (response != null) {
Logs.d(TAG,
"Page: publish reponse:"
+ response.toString());
FacebookRequestError error = response.getError();
if (error != null) {
Logs.d(TAG,
"Page: publish Errror:"
+ error.getErrorMessage());
if (uploadListener != null) {
uploadListener
.onError("Facebook can't publish your content");
}
} else {
if (uploadListener != null) {
uploadListener.onSuccess(null);
}
}
}
}
});
requestParams.remove("message");
request.setParameters(requestParams);
request.executeAsync();
}
</pre>
<b>5.) Post on Fan page using feed dialog.</b><br />
Some time we need to post on user's fan page using feed dialog.
for that we can use below method.<br />
<br />
<pre class="brush:java;">requestParams.putString("access_token",
Preferences.getFaceBookPageToken());
private static void publishPageFeedDialog(Bundle params) {
WebDialog feedDialog = (new WebDialog.FeedDialogBuilder(mActivity,
Session.getActiveSession(), params)).setOnCompleteListener(
new WebDialog.OnCompleteListener() {
@Override
public void onComplete(Bundle values,
FacebookException error) {
if (error != null) {
if (!(error instanceof FacebookOperationCanceledException)) {
mActivity.informUser(mActivity
.getString(R.string.bback_shared_facebook_failed));
}
Logs.e("FACEBOOK_ANDROID", "error", error);
} else if (values != null
&& values.containsKey("post_id")) {
mActivity.informUser(mActivity
.getString(R.string.bback_shared_facebook_success));
}
}
}).setFrom(String.valueOf(Preferences.getFacebookPageId())).build();
feedDialog.show();
}
</pre>
I have put method here from project.
So might be some reference class or not there.
<b><br /></b>You can get basic idea how we can integrate.<b><br /></b><br />
<br />
<b>Screen with FanPage list. </b><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYJ0P_zM_1x5pW6RbB04EzAkK9bVzfsGbJwOKs6nC8q82Mwcyt62XoYJmDXGw-Zyx2lR2i3JjDsNoupFi0Fl-PPES7in21gXYlkf75sMiZnE2Dj5OoLEa55Asu0ru-DGAXR-R0wq3BfPr9/s1600/fan_page_list.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYJ0P_zM_1x5pW6RbB04EzAkK9bVzfsGbJwOKs6nC8q82Mwcyt62XoYJmDXGw-Zyx2lR2i3JjDsNoupFi0Fl-PPES7in21gXYlkf75sMiZnE2Dj5OoLEa55Asu0ru-DGAXR-R0wq3BfPr9/s1600/fan_page_list.png" height="308" width="320" /></a></div>
<br />
<br />
<b>References:</b><br />
<a href="https://www.blogger.com/goog_461988133"><br /></a>
<a href="https://www.blogger.com/goog_461988133">https://developers.facebook.com/docs/graph-api/reference/v2.1/page</a><br />
<a href="https://www.blogger.com/goog_461988133">https://developers.facebook.com/docs/facebook-login/access-tokens#pagetokens
https://developers.facebook.com/docs/graph-api/reference/v2.0/user/accounts
https://developers.facebook.com/docs/sharing/reference/feed-dialog/v2.1
</a><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="156">
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
</style>
<![endif]-->
<br />
<div class="MsoNormal">
<a href="https://www.blogger.com/goog_461988133">https://developers.facebook.com/docs/android/share</a></div>
<div class="MsoNormal">
<a href="http://stackoverflow.com/questions/17039629/post-a-link-to-wall-of-facebook-page-using-facebook-sdk-3-1?rq=1">http://stackoverflow.com/questions/17039629/post-a-link-to-wall-of-facebook-page-using-facebook-sdk-3-1?rq=1</a><br />
<br /></div>
Please share in comment if you are facing any problem.<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com10tag:blogger.com,1999:blog-6372537297560266349.post-57171257593928350512014-10-16T00:27:00.000-07:002015-01-29T04:25:58.599-08:00Album wise image and video display like gallery in Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
This blog useful for display album list for image and video <br />
<br />
Some times we need to display album wise image and video in android application. <br />
I have made one sample example for this functionality.<br />
I would like to share this example.This might be useful too you.<br />
<br />
Below Android api used for display album wise images and videos.<br />
<br />
<b>Image API:</b><br />
<br />
<pre class="codestyle">MediaStore.Images.Media.EXTERNAL_CONTENT_URI;</pre>
<br />
<b>Video API:</b><br />
<pre class="codestyle">MediaStore.Video.Media.EXTERNAL_CONTENT_URI;</pre>
<br />
<b><br /></b>
<b>Features included in example:</b><br />
<ul style="text-align: left;">
<li>Album list fetch and display with count<b> </b></li>
<li>Video thumbnail display with duration</li>
<li>Image and Video thumbnail display for selected album </li>
<li>Get selected image/video path</li>
</ul>
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0a1f1IGsvPf56MdkZBOG76_46ag4K7wUgtCsEFpUxY-tKQdIqSzS-mb1BsEbPzuPxURfpilh4H-vYtdcaa34e-2jz_daCz0GFnKZFQlpq2M1J0uvpsmTiphak6up0EUoHO5V6p2EozD8E/s1600/screen1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0a1f1IGsvPf56MdkZBOG76_46ag4K7wUgtCsEFpUxY-tKQdIqSzS-mb1BsEbPzuPxURfpilh4H-vYtdcaa34e-2jz_daCz0GFnKZFQlpq2M1J0uvpsmTiphak6up0EUoHO5V6p2EozD8E/s1600/screen1.png" height="320" width="179" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOZ0ZnLNjOz4N_NPX7dw4IzXeLDvDBjUztW-bbjxVnqp960YeWpbEV2HyjwIv12UUkmHoVhtdSEnTEthHHvgFuoZaJ23gKeCIM9_xoYjD4bK9KIHgW-48PIGvPWOgicmcCWpe6HXaxOMdP/s1600/screen3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOZ0ZnLNjOz4N_NPX7dw4IzXeLDvDBjUztW-bbjxVnqp960YeWpbEV2HyjwIv12UUkmHoVhtdSEnTEthHHvgFuoZaJ23gKeCIM9_xoYjD4bK9KIHgW-48PIGvPWOgicmcCWpe6HXaxOMdP/s1600/screen3.png" height="320" width="180" /></a></div>
<br />
<br />
<b>Code Snippets:</b><br />
<br />
<b>1.) This method used for fetch image album list.</b><br />
<br />
<pre class="brush:java;"> private void getPhotoList() {
String[] PROJECTION_BUCKET = { ImageColumns.BUCKET_ID,
ImageColumns.BUCKET_DISPLAY_NAME, ImageColumns.DATE_TAKEN,
ImageColumns.DATA };
String BUCKET_GROUP_BY = "1) GROUP BY 1,(2";
String BUCKET_ORDER_BY = "MAX(datetaken) DESC";
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Cursor cur = getContentResolver().query(images, PROJECTION_BUCKET,
BUCKET_GROUP_BY, null, BUCKET_ORDER_BY);
GalleryPhotoAlbum album;
if (cur.moveToFirst()) {
String bucket;
String date;
String data;
long bucketId;
int bucketColumn = cur
.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
int dateColumn = cur
.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN);
int dataColumn = cur.getColumnIndex(MediaStore.Images.Media.DATA);
int bucketIdColumn = cur
.getColumnIndex(MediaStore.Images.Media.BUCKET_ID);
do {
// Get the field values
bucket = cur.getString(bucketColumn);
date = cur.getString(dateColumn);
data = cur.getString(dataColumn);
bucketId = cur.getInt(bucketIdColumn);
if (bucket != null && bucket.length() > 0) {
album = new GalleryPhotoAlbum();
album.setBucketId(bucketId);
album.setBucketName(bucket);
album.setDateTaken(date);
album.setData(data);
album.setTotalCount(photoCountByAlbum(bucket));
arrayListAlbums.add(album);
// Do something with the values.
Log.v("ListingImages", " bucket=" + bucket
+ " date_taken=" + date + " _data=" + data
+ " bucket_id=" + bucketId);
}
} while (cur.moveToNext());
}
cur.close();
}
</pre>
<b>
2.) This method used for retrieve image count album wise.</b><br />
<br />
<pre class="brush:java;"> private int photoCountByAlbum(String bucketName) {
try {
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
String searchParams = null;
String bucket = bucketName;
searchParams = "bucket_display_name = \"" + bucket + "\"";
// final String[] columns = { MediaStore.Images.Media.DATA,
// MediaStore.Images.Media._ID };
Cursor mPhotoCursor = getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null,
searchParams, null, orderBy + " DESC");
if (mPhotoCursor.getCount() > 0) {
return mPhotoCursor.getCount();
}
mPhotoCursor.close();
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}</pre>
<pre class="brush:java;"> </pre>
<b>3.)</b> <b>This method used for retrieve albumwise image list.</b></div>
<pre class="brush:java;">private void initPhotoImages(String bucketName) {
try {
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
String searchParams = null;
String bucket = bucketName;
searchParams = "bucket_display_name = \"" + bucket + "\"";
// final String[] columns = { MediaStore.Images.Media.DATA,
// MediaStore.Images.Media._ID };
mPhotoCursor = getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null,
searchParams, null, orderBy + " DESC");
if (mPhotoCursor.getCount() > 0) {
cursorData = new ArrayList<MediaObject>();
cursorData.addAll(Utils.extractMediaList(mPhotoCursor,
MediaType.PHOTO));
}
// setAdapter(mImageCursor);
} catch (Exception e) {
e.printStackTrace();
}
}</pre>
<pre class="brush:java;"> </pre>
<b>For Video you have to change only video uri in above queries.</b><br />
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
You can download source code from <a href="https://github.com/ankitthakkar/AlbumwiseGallery" target="_blank">Github</a>.<br />
<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com68tag:blogger.com,1999:blog-6372537297560266349.post-47358748346710969872013-08-05T04:48:00.001-07:002013-08-06T22:07:43.222-07:00Customn DropDown Spinner in Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Hello everyone!<br />
<br />
Here’s another cool Android tutorial that talks about creating your
own DropDown Spinner widget in Android. From the Android developers
page, a Spinner is a view that displays one child at a time and lets the
user pick among them.Our Default Spinner provide Drop Down above 4.0 version. In this tutorial you will create a customized Spinner like Gmail
app using library project. This is also work in 4.0 below version. You can create spinner like this:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8O11sqdXO_r1dv3O83MYBpT2UNMCJTt-_mxlGoJ6eMK_XhlHc6-lHlN5gL6cGCU3wpx5UrMTyZf-xNl3_T7NAtEdgWJEHoGwtauusuvlxJ6XS5ajXcNyfoARBty0m4RL0o_1d1X98u8pF/s1600/device-2013-08-03-171730.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8O11sqdXO_r1dv3O83MYBpT2UNMCJTt-_mxlGoJ6eMK_XhlHc6-lHlN5gL6cGCU3wpx5UrMTyZf-xNl3_T7NAtEdgWJEHoGwtauusuvlxJ6XS5ajXcNyfoARBty0m4RL0o_1d1X98u8pF/s320/device-2013-08-03-171730.png" width="192" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<b>Using this Library you can set following features:</b><br />
<br />
<h2 style="text-align: left;">
<b>Methods:</b></h2>
<ul><b>
</b>
<li><b>setItemTextColor(int color) </b>- Set the item text font color in drop down. </li>
</ul>
<ul>
<li><b>setItemBackgroundColor(int color) </b> - Set the item background color in drop down.</li>
</ul>
<ul>
<li><b>setItemTextSize (int size) </b>- Set the item text size</li>
</ul>
<ul>
<li><b>setVisibleItemNo (int no)</b> - Set the height of DropDown spinner equal to number of visible rows</li>
</ul>
<ul>
<li><b>addItem(String item)</b> - Add the single string item in spinner</li>
</ul>
<ul>
<li><b>addItem(String item, int resId)</b> - Add the single string item and image in spinner</li>
</ul>
<ul>
<li><b>setItems(String[] arr) </b>- Set the string array in spinner</li>
</ul>
<ul>
<li><b>setItems(String[] arr, int[] ico)</b> - Set the string array &
image array in list. size of string array and image array required
equal.</li>
</ul>
<ul>
<li><b>getSelectedPosition()</b> - Return the position of currently selected item within the adapter's data set.</li>
</ul>
<ul>
<li><b>setSelectedPosition(int selectedPosition)</b>- Set the currently selected item.</li>
</ul>
<br />
<h2 style="text-align: left;">
<b>Listener : </b></h2>
<b>
setOnItemClickListener</b><br />
<b><br /></b>
<b> setOnItemSelectedListener</b><br />
<br />
<br />
<b> You can set custom spinner control in xml like this:</b><br />
<br />
<pre class="brush: java "><com.anky.dropdownspinner.DropdownSpinner
android:id="@+id/my_spinner1"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/standard_menu_button_bg"
android:text="" /></pre>
<b>You can set property like this:</b><br />
<br />
<pre class="brush: java ">private DropdownSpinner spinner1 = (DropdownSpinner) findViewById(R.id.my_spinner1);
private String[] strings = { "Inter Milan", "AC Mila", "Manchesterb",
"Barcelona", "Valencia", "Juventus" };
spinner1.setItems(strings);
spinner1.addItem("Test1");
spinner1.addItem("Test2");
spinner1.addItem("Test3",R.drawable.ic_menu_moreoverflow_normal_holo_light);
spinner1.addItem("", R.drawable.ic_menu_moreoverflow_normal_holo_light);
spinner1.addItem("Test4", -1);
spinner1.setVisibleItemNo(5);
spinner1.setItemTextColor(Color.BLACK);
spinner1.setItemPadding(18, 15, 18, 15);
spinner1.setItemTextSize(20);
spinner1.setItemBackgroundColor(Color.WHITE);
spinner1.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView paramAdapterView, View paramView, int paramInt, long paramLong)
{ // TODO Auto-generated method stub
clickItem = "Center: Click item:" + paramInt; txtClick.setText(clickItem);
}
});
</pre>
<b> You can download <a href="https://github.com/ankitthakkar/DropDownSpinner" target="_blank">source code</a> from here.
</b></div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com24tag:blogger.com,1999:blog-6372537297560266349.post-66980632880499175962013-05-05T22:25:00.005-07:002013-05-06T03:43:05.123-07:00Google Plus Integration in Android<div dir="ltr" style="text-align: left;" trbidi="on">
<h2 id="Getting-Started-with-the-Google-Integration-for-Android" style="text-align: left;">
</h2>
<br />
Before you can start integrating Google+ features in your own app,
you must create a Google APIs Console project and initialize the
PlusClient within your app.<br />
<br />
The Google+ platform for Android has the following requirements:<br />
<ul>
<li>A physical device to use for developing and testing because Google Play services cannot be installed on an emulator.</li>
<li>The latest version of the Android SDK, including the SDK Tools component. The SDK is available from the Android SDK Manager.</li>
<li>Your project to compile against Android 2.2 (Froyo) or higher.</li>
<li>Eclipse configured to use Java 1.6</li>
<li>The Google Play services SDK:</li>
<ol>
<li>Launch Eclipse and select Window > Android SDK Manager or run android from the command line.</li>
<li>Scroll to the bottom of the package list and select Extras >
Google Play services. The package is downloaded to your computer and
installed in your SDK environment at
<android-sdk-folder>/extras/google/google_play_services.</li>
</ol>
</ul>
<h3 id="Step-1-Enable-the-Google-API">
Step 1: Enable the Google+ API</h3>
To authenticate and communicate with the Google+ APIs, you must
first register your digitally signed .apk file's public certificate in
the Google APIs Console:<br />
<br />
<h3 id="Step-2-Add-Google-play-service-library-project-in-your-project">
Step 2: Add Google play service library project in your project</h3>
Location of library project is here... <android-sdk-folder>/extras/google/google_play_services/libproject<br />
<br />
<h3 id="Step-3-How-do-I-check-to-see-if-the-Google-app-is-installed-on-the-device">
Step 3: How do I check to see if the Google+ app is installed on the device?</h3>
<div id="Step-3-How-do-I-check-to-see-if-the-Google-app-is-installed-on-the-device" style="text-align: left;">
</div>
<pre class="brush: java ">int errorCode = GooglePlusUtil.checkGooglePlusApp(this);
if (errorCode != GooglePlusUtil.SUCCESS) {
GooglePlusUtil.getErrorDialog(errorCode, this, 0).show();
} </pre>
<h3 id="Step-4-Initialize-the-PlusClient">
Step 4: Initialize the PlusClient</h3>
The PlusClient object is used to communicate with the Google+
service and becomes functional after an asynchronous connection has been
established with the service. Because the client makes a connection to a
service, you want to make sure the PlusClient.disconnect method is
called when appropriate to ensure robustness.<br />
<br />
Your activity will listen for when the connection has established or
failed by implementing the ConnectionCallbacks and
OnConnectionFailedListener interfaces.<br />
<br />
You have to create PlusClient object in Activity's onCreate() method.<br />
<br />
<pre class="brush: java">mPlusClient = new PlusClient(this, this, this, Scopes.PLUS_PROFILE);</pre>
<br />
You can handle google plus sign in & sign out in your app like this. <br />
<br />
<pre class="brush: java ">if (v.getId() == R.id.sign_in_button) {
if (!mPlusClient.isConnected()
&& btnSignIn.getText().equals(
getString(R.string.btn_signin))) {
mPlusClient.connect();
} else if (mPlusClient.isConnected()
&& btnSignIn.getText().equals(
getString(R.string.btn_signout))) {
{
mPlusClient.clearDefaultAccount();
mPlusClient.disconnect();
btnSignIn.setText(getString(R.string.btn_signin));
textUserName.setText("");
txtlogin.setVisibility(View.GONE);
}
}
}</pre>
<div class="brush: java " style="text-align: left;">
When the PlusClient object is unable to establish a connection, your implementation has an opportunity to recover inside your implementation
of onConnectionFailed, where you are passed a connection status that can be used to resolve any connection failures.</div>
<pre class="brush: java ">@Override
public void onConnectionFailed(ConnectionResult result) {
// TODO Auto-generated method stub
if (result.hasResolution()) {
// The user clicked the sign-in button already. Start to resolve
// connection errors. Wait until onConnected() to dismiss the
// connection dialog.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLVE_ERR);
} catch (SendIntentException e) {
mPlusClient.disconnect();
mPlusClient.connect();
}
}
}
@Override
public void onConnected() {
// TODO Auto-generated method stub
String accountName = mPlusClient.getAccountName();
Toast.makeText(this, accountName + " is connected.", Toast.LENGTH_LONG)
.show();
btnSignIn.setText(getString(R.string.btn_signout));
textUserName.setText(accountName);
txtlogin.setVisibility(View.VISIBLE);
}</pre>
<div class="brush: java " style="text-align: left;">
<br /></div>
<div class="brush: java " style="text-align: left;">
Because the resolution for the connection failure was started with startActivityForResult and the code REQUEST_CODE_RESOLVE_ERR, we can
capture the result inside Activity.onActivityResult. </div>
<div class="brush: java " style="text-align: left;">
<br /></div>
<pre class="brush: java ">@Override
protected void onActivityResult(int requestCode, int responseCode,
Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, responseCode, data);
if (requestCode == REQUEST_CODE_RESOLVE_ERR
&& responseCode == RESULT_OK) {
mPlusClient.disconnect();
mPlusClient.connect();
}
}</pre>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho8FC3ZF_Lhtfp0rKPt5a7oB9KViK8XPg-y2tTAJOiOlpYZKfv9vWAY_XlkZd30Oq6qe8Lo6XX5swLpIROkZNuu7kREbJaO18RragPHTFPxL6-I1lD5QAugaXQWF3oU5jnvOfzVYKUwWt5/s1600/Login_Screen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho8FC3ZF_Lhtfp0rKPt5a7oB9KViK8XPg-y2tTAJOiOlpYZKfv9vWAY_XlkZd30Oq6qe8Lo6XX5swLpIROkZNuu7kREbJaO18RragPHTFPxL6-I1lD5QAugaXQWF3oU5jnvOfzVYKUwWt5/s320/Login_Screen.png" width="200" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyWisYG2sLcsGMj8T92X7oRe8O99AfNwn17n-oa6dG_OkyEMM4VO9MPA7RrXUJl4E1aa-CbiRctPLcFe07LM8-UTt8SaExAGLaQ8moj-eu4IQq7xV_e_QhRV2O-0n6QaCuq9jGdsb95pyQ/s1600/Main_Screen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyWisYG2sLcsGMj8T92X7oRe8O99AfNwn17n-oa6dG_OkyEMM4VO9MPA7RrXUJl4E1aa-CbiRctPLcFe07LM8-UTt8SaExAGLaQ8moj-eu4IQq7xV_e_QhRV2O-0n6QaCuq9jGdsb95pyQ/s320/Main_Screen.png" width="200" /></a>
<br />
<h3 id="Features" style="text-align: left;">
</h3>
<h3 id="Features" style="text-align: left;">
Features:</h3>
<h3 id="Sharing-to-Google-from-your-Android-app">
Sharing to Google+ from your Android app</h3>
The Share dialog provides a means for users to share rich content
from your app into the Google+ stream, including text, photos, URL
attachments and location. In addition, your app can use two advanced
sharing options: interactive posts and deep linking.<br />
<br />
you can share on google plus like this<br />
<pre></pre>
<h3 id="Sharing-to-Google-from-your-Android-app">
</h3>
<pre class="brush: java ">if (v.getId() == R.id.share_button) {
if (mPlusClient.isConnected()) {
Intent shareIntent = PlusShare.Builder
.from(this)
.setText(
"Check out: http://example.com/cheesecake/lemon")
.setType("text/plain")
.setContent(
Uri.parse("http://example.com/cheesecake/lemon"))
.getIntent();
startActivity(shareIntent);
} else {
Toast.makeText(this, "Please Sign-in with google Account", Toast.LENGTH_LONG)
.show();
}
}</pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpK1TcJrPn8cekO40NFfYE5MYKaVPxbhTD5OBGeERv4wZobHLzgg-QrK-7zXvF5vzr7LTelEZ9sOK2gHCfafiT8310-kzidXouQU5xUl3hJAm8NnBdB0lVTZ-djFRRX458VNUq4kQcfSRo/s1600/Sharing_screen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpK1TcJrPn8cekO40NFfYE5MYKaVPxbhTD5OBGeERv4wZobHLzgg-QrK-7zXvF5vzr7LTelEZ9sOK2gHCfafiT8310-kzidXouQU5xUl3hJAm8NnBdB0lVTZ-djFRRX458VNUq4kQcfSRo/s320/Sharing_screen.png" width="200" /></a></div>
<h3 id="Getting-people-and-profile-information">
</h3>
<h3 id="Getting-people-and-profile-information">
Getting people and profile information</h3>
After you have signed in a user with Google, you can access the
user's age range, language, public profile information, and people that
they have circled.<br />
<br />
Please find attached demo for Google plus integration.<br />
<br />
<b>Demo Example:</b><br />
<br />You can download source code from here. <a href="https://github.com/ankitthakkar/GooglePlusIntegration" target="_blank">Source Code Download</a><br />
<br />
<br />
<b>Refrences:</b><br />
<br />
<a class="external" href="https://developers.google.com/+/mobile/android/getting-started#step_1_enable_the_google_api">https://developers.google.com/+/mobile/android/getting-started#step_1_enable_the_google_api</a><br />
<br />
<a class="external" href="http://developer.android.com/google/play-services/plus.html">http://developer.android.com/google/play-services/plus.html</a><br />
<br />
<h3 id="Getting-people-and-profile-information">
</h3>
<h3 id="Getting-people-and-profile-information">
</h3>
</div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com452tag:blogger.com,1999:blog-6372537297560266349.post-50901612996531493102013-01-10T03:28:00.000-08:002013-02-25T23:39:18.165-08:00APK Expansion Files in Android with Example<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<h3 id="Introduction">
Introduction</h3>
Google Play currently requires that your APK file be no more than
50MB. For most applications, this is plenty of space for all the
application's code and assets. However, some apps need more space for
high-fidelity graphics, media files, or other large assets. Previously,
if your app exceeded 50MB, you had to host and download the additional
resources yourself when the user opens the app. Hosting and serving the
extra files can be costly, and the user experience is often less than
ideal. To make this process easier for you and more pleasant for users,
Google Play allows you to attach two large expansion files that
supplement your APK.<br />
<br />
Google Play hosts the expansion files for your application and
serves them to the device at no cost to you. The expansion files are
saved to the device's shared storage location (the SD card or
USB-mountable partition; also known as the "external" storage) where
your app can access them. On most devices, Google Play downloads the
expansion file(s) at the same time it downloads the APK, so your
application has everything it needs when the user opens it for the first
time. In some cases, however, your application must download the files
from Google Play when your application starts.<br />
<br />
<h3 id="Overview">
Overview</h3>
Each time you upload an APK using the Google Play Android Developer
Console, you have the option to add one or two expansion files to the
APK. Each file can be up to 2GB and it can be any format you choose, but
we recommend you use a compressed file to conserve bandwidth during the
download. Conceptually, each expansion file plays a different role:<br />
<ul>
<li>The <b>main</b> expansion file is the primary expansion file for additional resources required by your application.</li>
<li>The <b>patch</b> expansion file is optional and intended for small updates to the main expansion file.</li>
</ul>
<br />
<b>Screen: </b><br />
Please see below screen for how apk expansion work. <br />
<div id="Testing-Your-Expansion-Files" style="text-align: left;">
<br /></div>
<div id="Testing-Your-Expansion-Files" style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCkwsjjVQlZG7otDkQI3wZYJKuAcfqF-wq0fJ28QKdBwlmu17ItMS-V9S3L4w4w4B9427D0H6ZLkXqI3Xtq0wfHeIa_LX11lBJwKZEcnLPXwhsYm98aAYj1Zs9JfvK4l3Y0_YYF8jamqFX/s1600/device1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCkwsjjVQlZG7otDkQI3wZYJKuAcfqF-wq0fJ28QKdBwlmu17ItMS-V9S3L4w4w4B9427D0H6ZLkXqI3Xtq0wfHeIa_LX11lBJwKZEcnLPXwhsYm98aAYj1Zs9JfvK4l3Y0_YYF8jamqFX/s320/device1.png" width="180" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyMRCgKLUk1IE3XKWz-FnPa-q0lP5Twv8UhFylWgmvnGcOUBqxmSRqaZN5C80hXdae6J764RoBZ6r_sNpte27pJT6Ol6SR0tzzp5Zn-YJVBUAAyFlv5YGHUrlWSI0vCfQgNKIWIVK2NwkB/s1600/device2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyMRCgKLUk1IE3XKWz-FnPa-q0lP5Twv8UhFylWgmvnGcOUBqxmSRqaZN5C80hXdae6J764RoBZ6r_sNpte27pJT6Ol6SR0tzzp5Zn-YJVBUAAyFlv5YGHUrlWSI0vCfQgNKIWIVK2NwkB/s320/device2.png" width="180" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUyOcR6X7JgSObtrvTJNwDUdQaPi1iCLNBrwKuz7oxs6WSelCaJVsEmuWGziTF_x-nqOwpOAAcBlXBYbxnPchDIr0akdg2jkbstcsu4hBOrXLPGXj6yIw1Ng6OaYgGfN3vlEIqKsJcuCYq/s1600/device3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUyOcR6X7JgSObtrvTJNwDUdQaPi1iCLNBrwKuz7oxs6WSelCaJVsEmuWGziTF_x-nqOwpOAAcBlXBYbxnPchDIr0akdg2jkbstcsu4hBOrXLPGXj6yIw1Ng6OaYgGfN3vlEIqKsJcuCYq/s320/device3.png" width="180" /></a></div>
<br /></div>
<h3 id="File-name-format">
File name format</h3>
Each expansion file you upload can be any format you choose (ZIP, PDF, MP4, etc.).<br />
<br />
<pre class="brush: java ">[main|patch].<expansion-version>.<package-name>.obb
</package-name></expansion-version></pre>
<pre>There are three components to this scheme:</pre>
<pre> </pre>
<b> main or patch</b><br />
Specifies whether the file is the main or patch expansion file. There can be only one main file and one patch file for each APK.<br />
<br />
<b><expansion-version></b><br />
This is an integer that matches the version code of the APK with which the expansion is first associated.<br />
Developer Console allows you to re-use an uploaded expansion file with a new APK,<br />
<br />
<b><package-name></b><br />
Your application's Java-style package name.<br />
<br />
For example, suppose your APK version is 314159 and your package
name is com.example.app. If you upload a main expansion file, the file
is renamed to:<br />
<br />
main.314159.com.example.app.obb<br />
<br />
Ex. main.1.packagename.obb.zip name used in my project.<br />
<br />
<h3 id="Storage-location">
Storage location</h3>
When Google Play downloads your expansion files to a device, it saves
them to the system's shared storage location. To ensure proper
behavior, you must not delete, move, or rename the expansion files. In
the event that your application must perform the download from Google
Play itself, you must save the files to the exact same location.<br />
<br />
The specific location for your expansion files is:<br />
<br />
<shared-storage>/Android/obb/<package-name>/<br />
<br />
<b><shared-storage></b> is the path to the shared storage space, available from getExternalStorageDirectory().<br />
<br />
<b><package-name></b> is your application's Java-style package name, available from getPackageName().<br />
<br />
Ex: sdcard/Android/obb/packagename/main.1.packagename.obb<br />
<br />
If you must unpack the contents of your expansion files, do not
delete the .obb expansion files afterwards and do not save the unpacked
data in the same directory<br />
For example, we've provided a library
project called the APK Expansion Zip Library that reads your data
directly from the ZIP file.<br />
<br />
<b>Note:</b> Unlike APK files, any files saved on the shared storage can be read by the user and other applications.<br />
<br />
<h3 id="Download-process">
Download process</h3>
Most of the time, Google Play downloads and saves your expansion
files at the same time it downloads the APK to the device. However, in
some cases Google Play cannot download the expansion files or the user
might have deleted previously downloaded expansion files. To handle
these situations, your app must be able to download the files itself
when the main activity starts, using a URL provided by Google Play.<br />
<br />
The download process from a high level looks like this:<br />
<ol>
<li>User selects to install your app from Google Play.</li>
<li>If Google Play is able to download the expansion files (which is
the case for most devices), it downloads them along with the APK.<br />If Google Play is unable to download the expansion files, it downloads the APK only.</li>
<li>When the user launches your application, your app must check whether the expansion files are already saved on the device. <br /> 1. If yes, your app is ready to go.<br />
2. If no, your app must download the expansion files over HTTP from
Google Play. Your app must send a request to the Google Play
client using the Google Play's Application Licensing service, which
responds with the name, file size, and URL for each expansion file. With
this information, you then download the files and save them to the
proper storage location.</li>
</ol>
<b>Caution:</b> It is critical that you include the
necessary code to download the expansion files from Google Play in the
event that the files are not already on the device when your application
starts. As discussed in the following section about Downloading the
Expansion Files, we've made a library available to you that greatly
simplifies this process and performs the download from a service with a
minimal amount of code from you.<br />
<br />
Use Download Library to implement your download behavior. Its Very Easy to use & Implement Downloading behavior using Download Library. you can also take reference from Sample Demo App.<br />
<br />
<h3 id="Downloading-the-Expansion-files">
Downloading the Expansion files</h3>
<div id="Downloading-the-Expansion-files" style="text-align: left;">
<span style="font-weight: normal;">In most cases, Google Play downloads and saves your expansion files to
the device at the same time it installs or updates the APK. This way,
the expansion files are available when your application launches for the
first time. However, in some cases your app must download the expansion
files itself by requesting them from a URL provided to you in a
response from Google Play's Application Licensing service. </span></div>
<div id="Downloading-the-Expansion-files" style="text-align: left;">
<br /></div>
The basic logic you need to download your expansion files is the following:<br />
<br />
1. When your application starts, look for the expansion files on the
shared storage location (in the Android/obb/<package-name>/
directory).<br />
<br />
a. If the expansion files are there, you're all set and your application can continue.<br />
<br />
b. If the expansion files are not there: <br />
<br />
1.) Perform a request using Google Play's Application Licensing to get your app's expansion file names, sizes, and URLs.<br />
<br />
2.) Use the URLs provided by Google Play to download the
expansion files and save the expansion files. You must save the files to
the shared storage location (Android/obb/<package-name>/) and use
the exact file name provided by Google Play's response.<br />
<br />
<b>Note:</b> <br />
The URL that Google Play provides for your
expansion files is unique for every download and each one expires
shortly after it is given to your application.<br />
<br />
<b>Note:</b> Whether your application is free or not,
Google Play returns the expansion file URLs only if the user acquired
your application from Google Play.<br />
<br />
<h3 style="text-align: left;">
<b>Sample Demo App: </b></h3>
You can Download Sample App from SDK Manager. And Take Reference from it.<br />
You have to download below Library from SDK Manager in Eclipse. <br />
<br />
<b>Google Play Licensing Library</b><br />
<b><br /></b>
<b>Google Play APK Expansion Library</b><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt51Jy0C9ask5JDDM7mF6O7gzWWC3KbgDA_HgSazXqWw_InGRfGdSjBzJaOqwNHyUgZK3nFA_fifnTpYeTkygBtj3_9Z9wowuTwUGUDWeiSQ9DLiHUMJ_lv7SufbpDZ6a-j2zhel35kMJy/s1600/screen1.png" style="margin-left: auto; margin-right: auto;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt51Jy0C9ask5JDDM7mF6O7gzWWC3KbgDA_HgSazXqWw_InGRfGdSjBzJaOqwNHyUgZK3nFA_fifnTpYeTkygBtj3_9Z9wowuTwUGUDWeiSQ9DLiHUMJ_lv7SufbpDZ6a-j2zhel35kMJy/s320/screen1.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Download from SDK Manager</td></tr>
</tbody></table>
<br />
<br />
You have to add total three Library in your Project for APK Expansion<br />
<br />
<div style="text-align: justify;">
<span style="color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif;"><span style="font-size: 12px; line-height: 16px;"><br /></span></span></div>
<br />
<div style="text-align: left;">
1) APK Expansion Zip Library (<span style="background-color: #f9f9f9; color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 12px; line-height: 16px; text-align: justify;">SDK/extras/google/play_apk_expansion/zip_file</span>)</div>
2) Application Licensing (<span style="background-color: #f9f9f9; color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 12px; line-height: 16px; text-align: justify;">SDK/extras/google/market_licensing</span>)<br />
3) Downloader Library (<span style="background-color: #f9f9f9; color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 12px; line-height: 16px; text-align: justify;">SDK/extras/google/play_apk_expansion/downloader_library</span>)<br />
<br />
<b>APK Expansion Zip Library </b><br />
This is an optional library that
helps you read your expansion
files when they're saved as ZIP files. Using this library allows you to easily read resources from
your ZIP expansion files as a virtual file system. <br />
<b><br /></b>
<b> Downloader Library</b><br />
To use APK expansion files with your application and provide the best user experience with
minimal effort on your behalf, we recommend you use the Downloader Library that's included in the
Google Play APK Expansion Library package. This library downloads your expansion files in a
background service, shows a user notification with the download status, handles network
connectivity loss, resumes the download when possible, and more.<br />
<br />
<b>Application Licensing </b><br />
If the files are not on the device, use Google Play's <a href="http://developer.android.com/google/play/licensing/index.html">Application Licensing</a> service to request URLs
for the expansion files, then download and save them.
<br />
<br />
<br />
Downloaded Sample Demo Available at below paths in your system.<br />
<br />
ex. /Android SDK / extras/ google / play_apk_expansion/ <br />
<br />
<br />
<b>Declaring user permissions</b><br />
<br />
<pre class="brush: java "><manifest ...="...">
<!-- Required to access Google Play Licensing -->
<uses-permission android:name="com.android.vending.CHECK_LICENSE">
<!-- Required to download files from Google Play -->
<uses-permission android:name="android.permission.INTERNET">
<!-- Required to keep CPU alive while downloading files (NOT to keep screen awake) -->
<uses-permission android:name="android.permission.WAKE_LOCK">
<!-- Required to poll the state of the network connection and respond to changes -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">
<!-- Required to check whether Wi-Fi is enabled -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE">
<!-- Required to read and write the expansion files on shared storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
</uses-permission></uses-permission></uses-permission></uses-permission></uses-permission></uses-permission></manifest>
</pre>
<pre><b>Note:</b> By default, the Downloader Library requires API level 4, but the APK Expansion Zip Library requires API level 5. </pre>
<br />
<h3 id="Implementing-the-downloader-service">
Implementing the downloader service</h3>
In order to perform downloads in the background, the Downloader
Library provides its own Service subclass called DownloaderService that
you should extend. In addition to downloading the expansion files for
you, the DownloaderService also:<br />
<br />
All you need to do is create a class in your application that
extends the DownloaderService class and override three methods to
provide specific application details:<br />
<br />
<b>getPublicKey()</b><br />
<b> </b>
<br />
This must return a string that is the Base64-encoded RSA public
key for your publisher account, available from the profile page on the
Developer Console (see Setting Up for Licensing).<br />
<br />
<b>getSALT()</b><br />
<b> </b>
<br />
This must return an array of random bytes that the licensing
Policy uses to create an Obfuscator. The salt ensures that your
obfuscated SharedPreferences file in which your licensing data is saved
will be unique and non-discoverable.<br />
<br />
<b>getAlarmReceiverClassName()</b><br />
<b> </b>
<br />
This must return the class name of the BroadcastReceiver in your
application that should receive the alarm indicating that the download
should be restarted (which might happen if the downloader service
unexpectedly stops).<br />
<br />
For example, here's a complete implementation of DownloaderService:<br />
<br />
<pre class="brush: java ">public class SampleDownloaderService extends DownloaderService {
// You must use the public key belonging to your publisher account
public static final String BASE64_PUBLIC_KEY = "YourLVLKey";
// You should also modify this salt
public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98,
-100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84
};
@Override
public String getPublicKey() {
return BASE64_PUBLIC_KEY;
}
@Override
public byte[] getSALT() {
return SALT;
}
@Override
public String getAlarmReceiverClassName() {
return SampleAlarmReceiver.class.getName();
}
}
</pre>
<br />
<b>Notice:</b> You must update the BASE64_PUBLIC_KEY value
to be the public key belonging to your publisher account. You can find
the key in the Developer Console under your profile information. This is
necessary even when testing your downloads.<br />
<br />
Remember to declare the service in your manifest file:<br />
<br />
<pre class="brush: java "><application ...="...">
<service android:name=".SampleDownloaderService">
...
</service></application>
</pre>
<pre> </pre>
<pre> </pre>
<pre><b>Note: You have to add your BASE64 public key in </b> <b>SampleDownloaderService in your app.</b></pre>
<pre><b>This key you can get when you create app in Google Market. </b></pre>
<pre> </pre>
<h3 id="Implementing-the-alarm-receiver">
Implementing the alarm receiver</h3>
<div id="Implementing-the-alarm-receiver" style="text-align: left;">
In order to monitor the progress of the file downloads and restart the
download if necessary, the DownloaderService schedules an RTC_WAKEUP
alarm that delivers an Intent to a BroadcastReceiver in your
application. You must define the BroadcastReceiver to call an API from
the Downloader Library that checks the status of the download and
restarts it if necessary. </div>
<div id="Implementing-the-alarm-receiver" style="text-align: left;">
<br /></div>
You simply need to override the onReceive() method to call DownloaderClientMarshaller.startDownloadServiceIfRequired().<br />
<br />
For example:<br />
<br />
<pre class="brush: java ">public class SampleAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent,
SampleDownloaderService.class);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
}
</pre>
<pre> </pre>
<pre>Notice that this is the class for which you must return the name in your
service's getAlarmReceiverClassName() method (see the previous
section). </pre>
<pre> </pre>
<pre>Remember to declare the receiver in your manifest file:</pre>
<pre> </pre>
<pre class="brush: java "><application ...="...">
<receiver android:name=".SampleAlarmReceiver">
...
</receiver></application>
</pre>
<pre> </pre>
<h3 id="Activity-for-Expansion-Handling">
Activity for Expansion Handling</h3>
<pre class="brush: java ">public class VideoDownloaderActivity extends Activity implements
IDownloaderClient {
/**
* Here is where you place the data that the validator will use to determine
* if the file was delivered correctly. This is encoded in the source code
* so the application can easily determine whether the file has been
* properly delivered without having to talk to the server. If the
* application is using LVL for licensing, it may make sense to eliminate
* these checks and to just rely on the server.
*/
private static final XAPKFile[] xAPKS = { new XAPKFile(true, // true
// signifies
// a main
// file
1, // the version of the APK that the file was uploaded
// against
191696333L // the length of the file in bytes
),
private class CopyTask extends AsyncTask<Void, Void, Boolean> {
private ProgressDialog mProgressDialog;
private Context context;
public CopyTask(Context context) {
this.context = context;
}
/**
* Display the dialog first when the webservice call.
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
if (context != null) {
mProgressDialog = ProgressDialog.show(context, "",
context.getString(R.string.copy_video_message), true,
false);
}
}
/**
* Call the webservice and parse the data from the service in
* background.
*/
@Override
protected Boolean doInBackground(Void... params) {
// return wsLinks.executeService(currentPage);
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(
VideoDownloaderActivity.this, xf.mIsMain,
xf.mFileVersion);
if (!Helpers.doesFileExist(VideoDownloaderActivity.this,
fileName, xf.mFileSize, false))
return true;
fileName = Helpers.generateSaveFileName(
VideoDownloaderActivity.this, fileName);
ZipResourceFile zrf;
try {
zrf = APKExpansionSupport.getAPKExpansionZipFile(
VideoDownloaderActivity.this, 1, 0);
File path = new File(
Environment.getExternalStorageDirectory()
+ File.separator
+ getString(R.string.app_name));
if (!path.exists()) {
// create a File object for the
// parent directory
File photoDirectory = new File(
path.getAbsolutePath());
// have the object build the
// directory structure, if needed.
photoDirectory.mkdirs();
} else {
if (path.isDirectory()) {
String[] children = path.list();
Log.v(LOG_TAG, "file length:" + children.length);
for (int i = 0; i < children.length; i++) {
new File(path, children[i]).delete();
}
}
}
for (ZipEntryRO entry : zrf.getAllEntries()) {
Log.v(LOG_TAG, "name:" + entry.mFileName);
DataInputStream is = new DataInputStream(
zrf.getInputStream(entry.mFileName));
// AssetFileDescriptor af =
// zrf.getAssetFileDescriptor(entry.mFileName);
long length = entry.mCompressedLength;
byte[] buf = new byte[1024 * 256];
Log.v("assetfilediscripter", "" + length);
// FileOutputStream fos = new FileOutputStream("");
// OutputStream stream = new BufferedOutputStream(new
// FileOutputStream("/storage/sdcard0/Download/sample.mp3"));
String[] bits = entry.mFileName.split("/");
String lastOne = bits[bits.length-1];
Log.v(LOG_TAG, "path:" + path + ":"+ lastOne);
OutputStream stream = new BufferedOutputStream(
new FileOutputStream(path + "/"
+ lastOne));
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = is.read(buffer)) != -1) {
stream.write(buffer, 0, len);
}
if (stream != null)
stream.close();
// break;
}
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
return true;
}
/**
* onPostExecute method after called webService and Set the data into
* adapter after background task is complete. this method set footerView
* into listView according to totalPAge.
*/
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
if (result) {
finish();
Intent intent = new Intent(VideoDownloaderActivity.this,
VideoListActivity.class);
startActivity(intent);
} else {
errorDialog(context, context.getString(R.string.copy_failed));
}
}
}
}
</pre>
<pre> </pre>
<h3 id="Testing-Your-Expansion-Files">
Testing Your Expansion Files</h3>
<div id="Testing-Your-Expansion-Files" style="text-align: left;">
<span style="font-weight: normal;">Before publishing your application, there are two things you should test: Reading the expansion files and downloading the files. </span></div>
<div id="Testing-Your-Expansion-Files" style="text-align: left;">
<br /></div>
<div id="Testing-Your-Expansion-Files" style="text-align: left;">
<b>Testing file reads</b></div>
<div id="Testing-Your-Expansion-Files" style="text-align: left;">
<br /></div>
Before you upload your application to Google Play, you should test
your application's ability to read the files from the shared storage.
All you need to do is add the files to the appropriate location on the
device shared storage and launch your application:<br />
<br />
1.) On your device, create the appropriate directory on the shared storage where Google Play will save your files.<br />
<br />
For
example, if your package name is com.example.android, you need to
create the directory Android/obb/com.example.android/ on the shared
storage space. (Plug in your test device to your computer to mount the
shared storage and manually create this directory.)<br />
<br />
2.) Manually add the expansion files to that directory. Be sure that
you rename your files to match the file name format that Google Play
will use.<br />
<br />
For example, regardless of the file type, the main expansion file
for the com.example.android application should be
main.0300110.com.example.android.obb. The version code can be whatever
value you want. Just remember:<br />
<ul>
<li>The main expansion file always starts with main and the patch file starts with patch.</li>
<li>The package name always matches that of the APK to which the file is attached on Google Play.</li>
</ul>
3.) Now that the expansion file(s) are on the device, you can install and run your application to test your expansion file(s).<br />
<br />
Here are some reminders about handling the expansion files:<br />
<ul>
<li>Do not delete or rename the .obb expansion files (even if you
unpack the data to a different location). Doing so will cause Google
Play (or your app itself) to repeatedly download the expansion file.</li>
<li>Do not save other data into your obb/ directory. If you must
unpack some data, save it into the location specified by
getExternalFilesDir().</li>
</ul>
<b>Testing file download</b><br />
<br />
Because your application must sometimes manually download the expansion
files when it first opens, it's important that you test this process to
be sure your application can successfully query for the URLs, download
the files, and save them to the device.<br />
<br />
To test your application's implementation of the manual download
procedure, you must upload your application to Google Play as a "draft"
to make your expansion files available for download:<br />
<br />
1.) Upload your APK and corresponding expansion files using the Google Play Developer Console<br />
<br />
2.) Fill in the necessary application details (title, screenshots,
etc.). You can come back and finalize these details before publishing
your application.<br />
<br />
Click the Save button. Do not click Publish. This saves the
application as a draft, such that your application is not published for
Google Play users, but the expansion files are available for you to test
the download process.<br />
<br />
3.) Install the application on your test device using the Eclipse tools or adb.<br />
<br />
4.) Launch the app.<br />
<br />
If everything works as expected, your application should begin
downloading the expansion files as soon as the main activity starts.<br />
<br />
<b><br /></b>
<b>References: </b><a href="http://developer.android.com/google/play/expansion-files.html">http://developer.android.com/google/play/expansion-files.html</a><br />
<br />
<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com257tag:blogger.com,1999:blog-6372537297560266349.post-79451955400230116792013-01-08T02:38:00.000-08:002013-01-09T20:56:39.987-08:00Overview of NDK and Set up Eclipse for Android C/C++ Development<div dir="ltr" style="text-align: left;" trbidi="on">
<h3 class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
<b>This tutorial shows overview of NDK & how
to setup Eclipse for using C/C++ together with Java in Android
projects.</b></h3>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
<br /></div>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
<b>How NDK comes into Picture? </b></div>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
<br /></div>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
Portability among hardware and adaptability to the constrained resources of mobile devices: this is the real essence of the mobile challenge from a technical perspective. With Android, ones has to deal with multiple screen resolutions, various CPU and GPU speed or capabilities, memory limitations, and so on, which are not topics specific to this Linux-based system.</div>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
<br />
To ease portability, Google engineers packaged a virtual machine with a complete framework (the Android SDK) to run programs written in one of the most spread programming language nowadays: Java.</div>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
<br /></div>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
Java, augmented with the Android framework, is really powerful. But first,<br />
Java is specific to Android. Apple's products are written for example in Objective C and can be combined with C and C++. </div>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
<br /></div>
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
And second, a Java virtual machine does not always give you enough capability to exploit the full power of mobile devices, even with just-in-time compilation<br />
enabled. Resources are limited on these devices and have to be carefully exploited to offer the best experience. This is where the Android Native Development Kit comes into place. </div>
<h3 style="text-align: left;">
When to Use NDK</h3>
However, we’d like to take a moment to talk about why the NDK
is important, when it should be used.<br />
<br />
Generally speaking, you only need to use the
NDK if your application is truly processor bound. That is, you have
algorithms that are using all of the processor within the DalvikVM and
would benefit from running natively. Also, a JIT compiler will improve the performance of such code as well.<br />
<br />
Another
reason to use the NDK is for ease of porting. If you’ve got loads of C
code for your existing application, using the NDK could speed up your
project’s development process.<br />
<br />
<br />
<div class="entry-title" style="color: #444444; font-weight: normal; text-align: left;">
You need to have Google ADT (Android Development Tools) installed. See <a href="http://developer.android.com/sdk/eclipse-adt.html">http://developer.android.com/sdk/eclipse-adt.html</a> how to do it.</div>
<br />
You also need Android ndk. Download it from <a href="http://developer.android.com/sdk/ndk/index.html">http://developer.android.com/sdk/ndk/index.html</a> and unpack it somewhere.<br />
<br />
<b>1) Install CDT (C/C++ Development Tools) into Eclipse.</b><br />
<br />
Choose <i>Help->Install New Software…</i> from the main menu.<br />
<br />
Choose <i><a href="http://download.eclipse.org/releases/galileo" rel="nofollow">http://download.eclipse.org/releases/galileo</a></i> as the source site. If you have another Eclipse release than Galileo choose the appropriate url.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIiFSYc2SFIZg2Tas_Oacg9M-uVH9_u6VSSX0s4w2rVWzikzWKGXXvJ_XQKKzxmy7Ja_l37eCN08ReXDOHp34k3koferYaVdaRKi9VPMkrDMZOLsGEeJCZ1HWIYgvhkfoc0d_BVoY_n4oN/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIiFSYc2SFIZg2Tas_Oacg9M-uVH9_u6VSSX0s4w2rVWzikzWKGXXvJ_XQKKzxmy7Ja_l37eCN08ReXDOHp34k3koferYaVdaRKi9VPMkrDMZOLsGEeJCZ1HWIYgvhkfoc0d_BVoY_n4oN/s320/1.png" width="320" /></a></div>
<br />
<b> </b> Click <i>Next</i>, Accept licences and finish the installation process. <br />
<br />
<br />
<br />
<b>2) In file manager create <i>jni/</i> directory in your project directory and place your C/C++ sources file here. Also put here <i>Android.mk</i> file which is a makefile that tells Android build-system how to build your files.</b><br />
<br />
Take a look into Android ndk <i>docs/ANDROID-MK.html</i> file how to create one.<br />
Simple example of <i>Android.mk</i> file:<br />
<br />
<code class="plain"><br />
<pre class='brush: java'>
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := com_anky_ndk
LOCAL_SRC_FILES := com_anky_ndk_test.c
include $(BUILD_SHARED_LIBRARY)
</pre> </code><br />
<table><tbody>
<tr><td class="number"></td><td class="content"></td><td class="content"><code class="plain"></code></td><td class="content"></td><td class="content"></td><td class="content"></td><td class="content"></td><td class="content"></td><td class="content"></td><td class="content"></td><td class="content"></td><td class="content"></td><td class="content"></td><td class="content"></td></tr>
</tbody></table>
<span style="font-family: monospace;"><br /></span>
<b>3) Refresh (F5) directories in <i>Package Explorer</i> to see <i>jni</i> directory here. Open your .c/.cpp file.</b><br />
<br />
Your .c/.cpp file (<i>native.c</i> in my case) contains a lot of
syntax errors which are not truly syntax errors. This is because Eclipse
threats the project as a pure Java project. We have to convert the
project into mixed Java & C/C++ project.<br />
<br />
<br />
<br />
<b>4) Press <i>Ctrl+n</i> (or choose <i>File->New->Other…</i> from main menu) and select <i>Convert to a C/C++ Project</i>.</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOiUgakAw4Xhrpx1YVPOvG8_HhPl-ivRBn69mmfugogCsfFPjPmqtpYZHk9enOu7cVz73_JK73U9xuYgz6dd_UvbEoKQ8pojZm5yQEoUe68DFYLzNDZEOAzZa904awg7A8wIFAm62G134c/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOiUgakAw4Xhrpx1YVPOvG8_HhPl-ivRBn69mmfugogCsfFPjPmqtpYZHk9enOu7cVz73_JK73U9xuYgz6dd_UvbEoKQ8pojZm5yQEoUe68DFYLzNDZEOAzZa904awg7A8wIFAm62G134c/s320/3.png" width="320" /></a></div>
<br />
This will convert your project into a mixed Java & C/C++ project
rather than into pure C/C++ project (the name of the function is
misleading).<br />
<br />
Click <i>Next</i>. Then choose your project and below choose <i>Makefile project</i> and <i>– Other Toolchain –</i>. Click <i>Finish</i>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZOOas1_j3u83gpd1TvCbGBqKfNJnXg1Qak3dhXBx3I_r3gJnwwz-yL_uHIhVteq-3RSvJYeigdSP9jv5V6PUFvv757uo-e5cx9g4JfNgBeroFxNqk9iM8_Ja9e1DSpuQcBldHlAisSxzG/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZOOas1_j3u83gpd1TvCbGBqKfNJnXg1Qak3dhXBx3I_r3gJnwwz-yL_uHIhVteq-3RSvJYeigdSP9jv5V6PUFvv757uo-e5cx9g4JfNgBeroFxNqk9iM8_Ja9e1DSpuQcBldHlAisSxzG/s320/4.png" width="282" /></a></div>
<br />
<br />
<br />
<br />
<br />
After doing this Eclipse will ask you if you want to switch to C/C++ perspective. Choose <i>Yes</i> because otherwise you wouldn’t be able to set C/C++ build preferences.<br />
<br />
<br />
<b>5) Click on your project with right button and select <i>Properties</i> or press Alt+Enter</b><br />
<br />
Properties windows will appear. Here you have to configure use of
ndk-build instead of make all command and set proper include paths.<br />
<br />
<b>6) Choose <i>C/C++ Build</i> and configure <i>ndk-build</i> as a build command</b><br />
In <i>Builder settings</i> fill <i>ndk-build</i> into <i>Build command</i> entry. You have to uncheck <i>Use default build command</i>. You also need to have ndk-build script in your PATH.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhffHCSxwrrJrlUd_9q4V35XB3OIr22KKTWlOPfVUF7jLC_R4r4WlYRta7LZQAiHZDdx7fdJkYYuuZBUPnQ1lo5pSPty_qvdCzymt6SV_PyDb-2Sck4KZuMuSWybdAqPA3luek-n8cyvxrQ/s1600/5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhffHCSxwrrJrlUd_9q4V35XB3OIr22KKTWlOPfVUF7jLC_R4r4WlYRta7LZQAiHZDdx7fdJkYYuuZBUPnQ1lo5pSPty_qvdCzymt6SV_PyDb-2Sck4KZuMuSWybdAqPA3luek-n8cyvxrQ/s320/5.png" width="320" /></a></div>
<br />
<br />
<br />
<br />
<br />
In <i>Behaviour</i> setting uncheck <i>clean</i> (ndk-build cleans project automatically on build and does not support separate clean command) and clear all text from build (<i>ndk-build</i> does not accept <i>all</i> as a parameter.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-rIWTnjEQzZLLbeoKH6Qlna26tS1M0k0ts_sGUFVNiNyN83h0X3aRshtUsP7OxT8WVKkz9BV6sQS1j_yjZUZeAkG3LV9BbQzrNcdBJXcU6uvXbohc2Z6D6h-slYp_fmlY2aA9sRAw8-8p/s1600/6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-rIWTnjEQzZLLbeoKH6Qlna26tS1M0k0ts_sGUFVNiNyN83h0X3aRshtUsP7OxT8WVKkz9BV6sQS1j_yjZUZeAkG3LV9BbQzrNcdBJXcU6uvXbohc2Z6D6h-slYp_fmlY2aA9sRAw8-8p/s320/6.png" width="320" /></a></div>
<br />
Click <i>Apply</i> to save settings.<br />
<br />
<br />
<br />
<b>7) Choose <i>C/C++ General->Paths and Symbols</i> and configure include path</b><br />
<br />
In <i>Includes</i> tab choose <i>GNU C</i> or <i>GNU C++</i> and click <i>Add…</i> button. Add path to include directory which is located in <i>platforms/android-4/arch/arm/usr/include</i> subdirectory of place where you’ve unpacked Android ndk. Include path depends on target for which you are compiling (<i>android-4</i> in my case — i.e. Android 1.6).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqloFmDMP9JkZFezyhwJCN9AK2SQGMafnGL74GaoaVeEKzByZ53Rytx_QgshLmn5WKt1zhWERYtrNqd0DVye_ik2ZXbAaUyM2i9lDEuA0MFFrKCxW3oDuPtqrQPxXOWPdU2a_xa-5bg386/s1600/7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqloFmDMP9JkZFezyhwJCN9AK2SQGMafnGL74GaoaVeEKzByZ53Rytx_QgshLmn5WKt1zhWERYtrNqd0DVye_ik2ZXbAaUyM2i9lDEuA0MFFrKCxW3oDuPtqrQPxXOWPdU2a_xa-5bg386/s320/7.png" width="320" /></a></div>
<br />
<br />
<br />
<br />
<br />
Finally click <i>Apply</i> and <i>OK</i> and that is all. Now you can use all Eclipse power for editing your C/C++ sources. If you click <i>Run</i> or <i>Debug</i>
Eclipse will compile C/C++ code as well as Java code and run it on
device/emulator. However you will not be able to debug C/C++ code. <br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<b> </b><b> </b> </div>Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com161tag:blogger.com,1999:blog-6372537297560266349.post-62601673998418016432013-01-02T03:24:00.001-08:002013-01-02T03:24:49.170-08:00Measure Performance Time Using NDK.<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Difference between Performance time in NDK in JAVA through One Application.<br />
<br />
Create <b>MathLib</b> class and put below code.<br />
<br />
<br />
package com.anky.mathsndk;<br />
<br />
import android.util.Log;<br />
<br />
public class MathLib {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>private static final String TAG = "Math_lib";<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>private static long fib(long n) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return n <= 0 ? 0 : n == 1 ? 1 : fib(n - 1) + fib(n - 2);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// Recursive Java implementation of the Fibonacci algorithm<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// (included for comparison only)<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>public static long fibJR(long n) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Log.d(TAG, "fibJR(" + n + ")");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return fib(n);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// Function prototype for future native recursive implementation<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// of the Fibonacci algorithm<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>public native static long fibNR(long n);<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// Iterative Java implementation of the Fibonacci algorithm<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// (included for comparison only)<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>public static long fibJI(long n) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Log.d(TAG, "fibJI(" + n + ")");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>long previous = -1;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>long result = 1;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>for (long i = 0; i <= n; i++) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>long sum = result + previous;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>previous = result;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = sum;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return result;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>public static long factorialJ(long n) {<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>long fact = 1;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Log.e(TAG, "" + "Factorial of " + n + ":");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// System.out.println("Factorial of " + n + ":");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>for (int i = 1; i <= n; i++) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>fact = fact * i;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return fact;<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// Function prototype for future iterative recursive implementation<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// of the Fibonacci algorithm<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>public native static long fibNI(long n);<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>public native static long factorialN(long n);<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>static {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// as defined by LOCAL_MODULE in Android.mk<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>System.loadLibrary("com_anky_mathsndk_MathLib");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
}<br />
<div>
<br /></div>
<div>
<br /></div>
<div>
Create <b>MainActivity</b> and Put below code.</div>
<div>
<br /></div>
<div>
<div>
package com.anky.mathsndk;</div>
<div>
<br /></div>
<div>
import android.app.Activity;</div>
<div>
import android.app.ProgressDialog;</div>
<div>
import android.content.Context;</div>
<div>
import android.os.AsyncTask;</div>
<div>
import android.os.Bundle;</div>
<div>
import android.os.SystemClock;</div>
<div>
import android.text.TextUtils;</div>
<div>
import android.view.Menu;</div>
<div>
import android.view.View;</div>
<div>
import android.view.View.OnClickListener;</div>
<div>
import android.widget.Button;</div>
<div>
import android.widget.EditText;</div>
<div>
import android.widget.RadioGroup;</div>
<div>
import android.widget.TextView;</div>
<div>
<br /></div>
<div>
public class MainActivity extends Activity implements OnClickListener {</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>private EditText input;</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>private RadioGroup type;</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>private TextView output;</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>private Context context;</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>@Override</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>protected void onCreate(Bundle savedInstanceState) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>super.onCreate(savedInstanceState);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>setContentView(R.layout.maths_test);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>this.input = (EditText) super.findViewById(R.id.input);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>this.type = (RadioGroup) super.findViewById(R.id.type);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>this.output = (TextView) super.findViewById(R.id.output);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>Button button = (Button) super.findViewById(R.id.button);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>button.setOnClickListener(this);</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>context = MainActivity.this;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>@Override</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>public boolean onCreateOptionsMenu(Menu menu) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>// Inflate the menu; this adds items to the action bar if it is present.</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>getMenuInflater().inflate(R.menu.activity_main, menu);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>return true;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>@Override</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>public void onClick(View v) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>// TODO Auto-generated method stub</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>String s = this.input.getText().toString();</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>if (TextUtils.isEmpty(s)) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>return;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>final ProgressDialog dialog = ProgressDialog.show(context, "",</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>"Calculating...", true);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>final long n = Long.parseLong(s);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>new AsyncTask<Void, Void, String>() {</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>@Override</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>protected String doInBackground(Void... params) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>long result = 0;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>long t = SystemClock.uptimeMillis();</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>switch (MainActivity.this.type.getCheckedRadioButtonId()) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>case R.id.type_fib_jr:</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = MathLib.fibJR(n);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>break;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>case R.id.type_fib_ji:</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = MathLib.fibJI(n);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>break;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>case R.id.type_fib_nr:</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = MathLib.fibNR(n);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>break;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>case R.id.type_fib_ni:</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = MathLib.fibNI(n);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>break;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>case R.id.type_fact_j:</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = MathLib.factorialJ(n);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>break;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>case R.id.type_fact_n:</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = MathLib.factorialN(n);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>break;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>t = SystemClock.uptimeMillis() - t;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>return String.format("(%d)=%d in %d ms", n, result, t);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>@Override</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>protected void onPostExecute(String result) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>dialog.dismiss();</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>MainActivity.this.output.setText(result);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}.execute();</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<br /></div>
<div>
}</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div>
Create jni directory project and Create <b>Android.mk file</b> in jni and Put this code.</div>
<div>
<br /></div>
<div>
LOCAL_PATH := $(call my-dir)</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
include $(CLEAR_VARS)</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
LOCAL_LDLIBS := -llog</div>
<div>
<br /></div>
<div>
LOCAL_MODULE := com_anky_mathsndk_MathLib</div>
<div>
LOCAL_SRC_FILES := com_anky_mathsndk_MathLib.c</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
include $(BUILD_SHARED_LIBRARY)</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Generate header file using External Tools or Terminal com_anky_mathsndk_MathLib.h</div>
<div>
<br /></div>
<div>
<div>
/* DO NOT EDIT THIS FILE - it is machine generated */</div>
<div>
#include <jni.h></div>
<div>
/* Header for class com_indianic_mathsndk_MathLib */</div>
<div>
<br /></div>
<div>
#ifndef _Included_com_indianic_mathsndk_MathLib</div>
<div>
#define _Included_com_indianic_mathsndk_MathLib</div>
<div>
#ifdef __cplusplus</div>
<div>
extern "C" {</div>
<div>
#endif</div>
<div>
/*</div>
<div>
* Class: com_indianic_mathsndk_MathLib</div>
<div>
* Method: fibNR</div>
<div>
* Signature: (J)J</div>
<div>
*/</div>
<div>
JNIEXPORT jlong JNICALL Java_com_anky_mathsndk_MathLib_fibNR</div>
<div>
(JNIEnv *, jclass, jlong);</div>
<div>
<br /></div>
<div>
/*</div>
<div>
* Class: com_indianic_mathsndk_MathLib</div>
<div>
* Method: fibNI</div>
<div>
* Signature: (J)J</div>
<div>
*/</div>
<div>
JNIEXPORT jlong JNICALL Java_com_anky_mathsndk_MathLib_fibNI</div>
<div>
(JNIEnv *, jclass, jlong);</div>
<div>
<br /></div>
<div>
/*</div>
<div>
* Class: com_indianic_mathsndk_MathLib</div>
<div>
* Method: factorialN</div>
<div>
* Signature: (J)J</div>
<div>
*/</div>
<div>
JNIEXPORT jlong JNICALL Java_com_anky_mathsndk_MathLib_factorialN</div>
<div>
(JNIEnv *, jclass, jlong);</div>
<div>
<br /></div>
<div>
#ifdef __cplusplus</div>
<div>
}</div>
<div>
#endif</div>
<div>
#endif</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Create <b>com_anky_mathsndk_MathLib.c</b> file and put this code.</div>
<div>
<br /></div>
<div>
<div>
#include "com_anky_mathsndk_MathLib.h"</div>
<div>
#include <android/log.h></div>
<div>
<br /></div>
<div>
static jlong fib(jlong n) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>return n <= 0 ? 0 : n == 1 ? 1 : fib(n - 1) + fib(n - 2);</div>
<div>
}</div>
<div>
<br /></div>
<div>
JNIEXPORT jlong JNICALL Java_com_anky_mathsndk_MathLib_fibNR(JNIEnv* env,</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>jclass clazz, jlong n) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>__android_log_print(ANDROID_LOG_DEBUG, "FibLib.c", "fibNR(%lld)", n);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>return fib(n);</div>
<div>
<br /></div>
<div>
}</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
JNIEXPORT jlong JNICALL Java_com_anky_mathsndk_MathLib_fibNI(JNIEnv *env,</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>jclass clazz, jlong n) {</div>
<div>
<br /></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>jlong previous = -1;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>jlong result = 1;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>jlong i;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>__android_log_print(ANDROID_LOG_DEBUG, "FibLib.c", "fibNI(%lld)", n);</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>for (i = 0; i <= n; i++) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>jlong sum = result + previous;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>previous = result;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = sum;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>return result;</div>
<div>
}</div>
<div>
<br /></div>
<div>
JNIEXPORT jlong JNICALL Java_com_anky_mathsndk_MathLib_factorialN(</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>JNIEnv *env, jclass clazz, jlong n) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>jlong fact = 1;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>jlong i;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>for (i = 1; i <= n; i++) {</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>fact = fact * i;</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>return fact;</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
}</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Compile the project using NDKBuild and Run the project.</div>
<div>
</div>
<div>
<br /></div>
<div>
You have to notice the difference between JAVA and NDK.</div>
<div>
<br /></div>
<div>
Execution time for factorial and Fibonaci series of number in NDK is faster than JAVA.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/10893508217853098223noreply@blogger.com10