tag:blogger.com,1999:blog-2280359610899661922024-03-14T02:52:33.807+05:30Knowledge CandyThis blog provides tutorials and other useful information related to android, unity3d and back-end system designs.Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.comBlogger49125tag:blogger.com,1999:blog-228035961089966192.post-61264842919209882512021-01-02T06:44:00.005+05:302021-01-02T06:44:57.715+05:30Random cutout image augmentation preprocessing layer for tensorflow keras<p>Hello friends: </p><p>While training on image data, we often need to apply multiple augmentations like random cropping, random zoom etc. </p><p>With the new <a href="https://keras.io/api/layers/preprocessing_layers/image_preprocessing/" rel="nofollow" target="_blank">keras preprocessing layers</a>, these operations can be baked into the model pipeline. </p><p>However, there is one more image augmentation technique we can perform which can provide better results while training. The technique is RANDOM CUTOUT which basically means to replace random sections of the image. This techinque is detailed in <a href="https://arxiv.org/abs/1708.04552" rel="nofollow" target="_blank">this</a> paper. </p><p> In this post, I will share how can we have this technique as a keras preprocessing layer.
<b> </b></p><p><b>Tensorflow 2.3.1</b>
<script src="https://gist.github.com/ashwanikumar04/c2331a01a89c52be64093c99f75a5e6e.js"></script>
<b> </b></p><p><b>Tensorflow 2.4.0</b>
<script src="https://gist.github.com/ashwanikumar04/9ec4dc1d6ca7f9bb8b4cde51c91903f8.js"></script> </p><p> Full working Kaggle Notebook is available <a href="https://www.kaggle.com/ashwanikumar04/image-aug-keras-custom-cutout-preprocessing-layer" target="_blank">here</a>.
Hope this helps.</p>Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-42393320727948444212018-11-02T12:07:00.001+05:302018-11-02T12:19:08.119+05:30Most common git commands- Git Cheat sheet<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
<script src="https://gist.github.com/ashwanikumar04/8ae391abe0c96463efd66255bdf9d920.js"></script>
Hope this helps.
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-85738516385665737522018-02-20T13:47:00.000+05:302018-02-20T13:47:25.969+05:30Simple JSON Query tool<div dir="ltr" style="text-align: left;" trbidi="on">
Hello,<br />
<br />
Often we find ourselves in the position to query JSON data on the fly, without having to write a full blown application to fetch and query JSON.<br />
<br />
I also faced the similar situation.<br />
I searched on web for couple of existing solutions like <a href="http://www.jsonquerytool.com/" rel="nofollow" target="_blank">Json Query</a> but I needed some more flexibility like support for newer versions of the library, ability to save the code snippets etc.<br />
<br />
I have created my own version of JSON query tool.<br />
<br />
The code for the tool is available <a href="https://github.com/ashwanikumar04/json-query" target="_blank">here.</a><br />
<br />
I have hosted the same which can be accessed <a href="http://jq.ashwanik.in/#/" target="_blank">here</a>.<br />
<br />
Hope this helps someone.<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com2tag:blogger.com,1999:blog-228035961089966192.post-29012832966957882982017-05-07T23:33:00.002+05:302017-05-07T23:33:28.825+05:30Minify static resources in an android application<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
Sometimes an android application includes lots of static resources like html, css, jss or json files, this leads to a significant increase in the apk size. We all want our android application apk on diet. In this post, I will share a way to reduce the size of static resources thus reducing the size of apk.<br />
<br />
<a name='more'></a>I will be using node.js and gulp to compress static files. This post uses the code from a <a href="http://blog.ashwanik.in/2017/03/compress-html-json-css-and-js-resources.html" target="_blank">previous</a> post.<br />
<br />
This gradle <a href="https://github.com/srs/gradle-node-plugin" rel="nofollow" target="_blank">plugin </a>will be used to integrate minification within the build process.<br />
<br />
The process includes following steps:<br />
<br />
<ol style="text-align: left;">
<li>Update <b>build.gradle </b> <script src="https://gist.github.com/ashwanikumar04/516890b3daa510edfc373a60892191b0.js"></script>
</li>
<li>Put all the static resources in "static_src" under app folder. This path is configurable and can be changed in "minifyStaticResources" task</li>
</ol>
<br />
Following commands minify the static resources<br />
<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;">./gradlew iG
</pre>
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;">cd app/gulp-task
npm install</pre>
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;">./gradlew mSR
</pre>
<br />
Fully working code is available <a href="https://github.com/ashwanikumar04/android-compress-static-resources" target="_blank">here</a>.<br />
<br />
Hope this helps. Happy coding.<br />
<ol style="text-align: left;">
</ol>
</div>
</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-52008696910712376812017-03-25T20:50:00.001+05:302017-03-25T20:57:30.587+05:30Compress html, json, css and js resources <div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
We use static resources like html, css, js or json in multiple places to convey information. When we write these files they contain lots of white spaces which can increase the file size as a whole. Here I am going to share a simple tip to reduce the file sizes of static resources.<br />
<a name='more'></a><br />
We will create a gulp application which will use multiple gulp plug-ins to minify the resources.<br />
<br />
Following gulp file does all the magic
<script src="https://gist.github.com/ashwanikumar04/a6565c83fc2eaf743f0e9cf4197c5362.js"></script>
<br />
Complete working application is available <a href="https://github.com/ashwanikumar04/static-data-compressor" target="_blank">here.</a><br />
Happy coding!!!
<br />
</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com2tag:blogger.com,1999:blog-228035961089966192.post-82699362947931953632017-02-27T23:50:00.001+05:302017-02-27T23:52:35.945+05:30A simple flash card application in Node js and angular js<div dir="ltr" style="text-align: left;" trbidi="on">
Hello:<br />
<br />
In this post I will be sharing a node js based application to manage and test knowledge using flash cards.<br />
<br />
<a name='more'></a><br />
<br />
This application is motivated by <a href="https://github.com/jwasham/computer-science-flash-cards" rel="nofollow" target="_blank">this</a> project which is a part of Google Interview preparation. <br />
<br />
Flash cards help in recollecting information on a regular period.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-Auz6YDxpvUs/WLRsYq_2kbI/AAAAAAAAE7c/ouBtNy1J6c0M3dTyxW4qK-dzGPpof0P_QCLcB/s1600/flash-cards.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="467" src="https://2.bp.blogspot.com/-Auz6YDxpvUs/WLRsYq_2kbI/AAAAAAAAE7c/ouBtNy1J6c0M3dTyxW4qK-dzGPpof0P_QCLcB/s640/flash-cards.png" width="640" /></a></div>
<br />
A hosted demo version can be accessed <a href="http://demo.ashwanik.in/" target="_blank">here</a>.<br />
Credentials:<br />
UserName: admin<br />
Password: demo<br />
<br />
The full source code of the application is available <a href="https://github.com/ashwanikumar04/flash-cards" target="_blank">here</a>.<br />
<br />
You can follow <a href="http://blog.ashwanik.in/2017/01/infrastructre-as-code-for-nodejs-ubuntu.html" target="_blank">this</a> post to launch a micro instance on AWS using Terraform which can be used to host the application.<br />
<br />
Hope this helps. Happy coding.<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-37750562626752662982017-01-31T16:27:00.002+05:302017-01-31T16:36:53.841+05:30Infrastructre as a code for Nodejs, Ubuntu and Nginx<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
Hosting a web application on a cloud platform (like AWS, Azure etc) requires lots of housekeeping task involving server provisioning, installing software etc.<br />
<br />
Infrastructure as a code is a paradigm in which the necessary infrastructure is brought up with the help of code.<br />
<br />
<a name='more'></a> In this post, I will introduce <a href="https://www.terraform.io/" rel="nofollow" target="_blank">Terraform</a>, a toolkit to write code infrastructure.<br />
<br />
In short, Terraform helps in:<br />
<ol style="text-align: left;">
<li>Bringing up infrastructure using code</li>
<li>Maintaining changes to the infrastructure </li>
<li>Maintaining dependency graphs of resources</li>
</ol>
Bringing an AWS server up is as simple as executing a simple script.<br />
<br />
Terraform scripts are written in <b>.tf</b> files.<br />
<br />
<br />
<script src="https://gist.github.com/ashwanikumar04/e0b3f938832f798e6dc9093b57c1acaf.js"></script>
<br />
I have created Terraform scripts to bring up Ubuntu server with following software installed on AWS<br />
<ol style="text-align: left;">
<li>Nginx</li>
<li>Nodejs</li>
<li>PM2 </li>
</ol>
These scripts bring up Ubuntu server with all the necessary software needed to host a nodejs application.<br />
<br />
In order to change the instance type, update <a href="https://github.com/ashwanikumar04/terraform-ubuntu-nginx-nodejs/blob/master/aws/terraform.tfvars" target="_blank">this </a>file. <br />
Complete instructions and code is available <a href="https://github.com/ashwanikumar04/terraform-ubuntu-nginx-nodejs" target="_blank">here</a>.<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-52574555860245404382017-01-04T08:16:00.000+05:302017-01-04T08:16:40.116+05:30Must have libraries for Android application-Part2<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
<b>Happy new year.</b><br />
<br />
We all want to develop rapid and stable applications. This post is in continuation of <b><a href="http://blog.ashwanik.in/2015/07/7-must-have-libraries-in-android-application.html" target="_blank"><span style="color: #16a085;">this</span></a></b>.<br />
<br />
<a name='more'></a><br /><u><b>Making seamless network calls:</b></u><br />
<br />
<span style="font-size: large;"><span style="color: #16a085;"><b>Retrofit</b></span>:</span> It is an awesome library to make network calls. More info can be found <a href="https://github.com/square/retrofit" rel="nofollow" target="_blank">here</a>. Sample class to make new web request. I have released a wrapper on Retrofit which can be helpful. It can be found <a href="https://github.com/ashwanikumar04/retroclient" target="_blank">here</a>.<br />
<br />
<u><b>Icons:</b></u><br />
<br />
<span style="font-size: large;"><span style="color: #16a085;"><b>Android Iconics</b></span>: <span style="font-size: small;">This library helps reduce apk size as it provides highly scalable icons for all resolutions. More info can be found <a href="https://github.com/mikepenz/Android-Iconics" rel="nofollow" target="_blank">here</a>.</span></span><br />
<span style="font-size: large;"><span style="font-size: small;"><br /></span></span>
<span style="font-size: large;"><span style="font-size: small;"></span></span><br />
<u><b>Jobs:</b></u><br />
<br />
<span style="font-size: large;"><span style="color: #16a085;"><b>Priority Job Queue: </b></span></span><span style="font-size: large;"><span style="font-size: small;">This library makes life easier by providing easy to use interface for creating jobs instead of async tasks etc. More info is available <a href="https://github.com/yigit/android-priority-jobqueue" rel="nofollow" target="_blank">here</a>. </span></span><br />
<br />
<u><b>Logging</b></u><br />
<br />
<span style="color: #16a085;"><b><span style="font-size: large;">Timber</span></b></span>: This is small library to use for logging with in the application. Usage and other info available <a href="https://github.com/JakeWharton/timber" rel="nofollow" target="_blank">here</a>.<br />
<br />
<br />
<u><b>Date Time:</b></u><br />
<br />
<span style="color: #16a085;"><b><span style="font-size: large;">Joda Time Android</span></b></span> : This library is android port of famous JodaTime library to ease the pain of Date time manipulations. For more info check <a href="https://github.com/dlew/joda-time-android" rel="nofollow" target="_blank">here</a>.<br /><br />
<br />
Hope this helps. Happy coding.<br />
<br />
</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-21945494945481353372016-02-02T01:03:00.000+05:302016-02-02T01:09:04.799+05:30RetroClient- Library for making HTTP calls using Retrofit and OkHttp<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
Interaction with back-end using REST based API is very common in application development.<br />
There are multiple libraries to make network calls on Android. Following two are most used.<br />
<ol style="text-align: left;">
<li>Volley</li>
<li>Retrofit</li>
</ol>
In this tutorial I will share a library which can be helpful in making network calls on Android.<br />
<br />
<a name='more'></a><br />
<br />
<br />
<span style="color: white;"><b><a href="https://github.com/ashwanikumar04/retroclient" target="_blank">RetroClient</a></b></span> came into existence to minimize the code needed for making HTTP calls. Every call to API generally requires<br />
<ol style="text-align: left;">
<li>Boiler plate code to check and handle network state</li>
<li>Initialize HTTP client</li>
<li>Handle response</li>
<li>Handle error</li>
</ol>
This library is my effort to reduce the time involved in developing android applications which involves web interaction.<br />
<br />
Some features of the library<br />
<ol style="text-align: left;">
<li>Provides out of the box network check and error handling</li>
<li>Show progress view while making network calls</li>
<li>Multiple methods for initializing Retrofit services</li>
</ol>
Detailed usage is available <b><a href="https://github.com/ashwanikumar04/retroclient" target="_blank">here </a></b><br />
<br />
Hope this helps you in your future projects.<br />
Do share your feedback and issues.<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-11088652341778897342015-10-01T00:11:00.000+05:302015-10-01T00:11:07.171+05:30Issue with Webp on Android<div dir="ltr" style="text-align: left;" trbidi="on">
Hello,<br />
In my previous <a href="http://blog.ashwanik.in/2015/09/convert-png-jpeg-tiff-to-webp.html" target="_blank">post </a>I shared a utility for converting .png, .jpeg and .tiff files to webp. However webp has problem in rendering on Android Devices below <a href="http://developer.android.com/intl/es/guide/appendix/media-formats.html" rel="nofollow" target="_blank">API 4.2.1</a><br />
<br />
<br />
<a name='more'></a><br />
As per Android documentation, alpha compression (transparency) for Webp is supported only after API 4.2.1<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-TSQ9rD2-1YI/Vgwraj1pJfI/AAAAAAAAEQw/3DU71VcCxCc/s1600/webp.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="60" src="http://2.bp.blogspot.com/-TSQ9rD2-1YI/Vgwraj1pJfI/AAAAAAAAEQw/3DU71VcCxCc/s640/webp.jpg" width="640" /></a></div>
<br />
<br />
This issue is also logged for the webp project and can be found <a href="https://code.google.com/p/webp/issues/detail?id=170" rel="nofollow" target="_blank">here</a>.<br />
<br />
One way to fix the issue is to use <span style="font-size: large;"><b>-noalpha </b><span style="font-size: small;">switch while compression.</span></span><br />
<br />
<span style="font-size: large;"><span style="font-size: small;">Hope this helps. Happy coding. </span></span><span style="font-size: small;"> </span></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-51131481919340489872015-09-20T20:48:00.000+05:302015-09-20T21:02:15.596+05:30Convert PNG, JPEG, TIFF to WebP<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
Hello All:<br />
<br />
Everybody wants to reduce the size of his/her android application. Images contribute a lot in increasing the application size. Google has released a new image type <a href="https://developers.google.com/speed/webp/" rel="nofollow" target="_blank">Webp</a>. In this post I will share a simple utility which can do bulk conversion of images to webp.<br />
<a name='more'></a>Android support webp by default from Android 4.0 (<a href="http://developer.android.com/intl/es/guide/appendix/media-formats.html" rel="nofollow" target="_blank">Source</a>)</div>
<div>
<br /></div>
<div>
I have created a simple windows utility which uses Google's <a href="https://developers.google.com/speed/webp/docs/using" rel="nofollow" target="_blank">cwebp</a> encoder.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-IWcEnpFj3dk/Vf7HuUKv0iI/AAAAAAAAEQM/lvJJuXu2XP4/s1600/pngtowebp.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="http://4.bp.blogspot.com/-IWcEnpFj3dk/Vf7HuUKv0iI/AAAAAAAAEQM/lvJJuXu2XP4/s400/pngtowebp.jpg" width="400" /></a></div>
<br />
<br />
This utility provides following features<br />
<ol style="text-align: left;">
<li>Convert a file or all files in a folder</li>
<li>Backup the old files</li>
<li>By default, the utility deletes the file whose webp file size is less than the original file.</li>
<ol>
<li>"Delete Original" will override this</li>
</ol>
<li>Options to select file filters</li>
<li>Compression quality </li>
</ol>
</div>
<br />
The code for this can be found <a href="http://www.ashwanik.in/blog/downloads">here</a>.<br />
<br />
Hope this helps. Happy coding.<br />
<br />
<br />
<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com1tag:blogger.com,1999:blog-228035961089966192.post-13062591680084191102015-08-30T20:54:00.001+05:302015-08-30T20:54:39.825+05:30Support TabLayout inside a fragment<div dir="ltr" style="text-align: left;" trbidi="on">
Hello:<br />
<br />
Google has released new Support Design Library which contains some awesome widgets. One of them is TabLayout. In this post I will share the code to use TabLayout inside a fragment.<br />
<br />
<br />
<a name='more'></a>I will use ViewPager with TabLayout.<br />
<br />
Below is XML layout code.<br />
<pre class="brush:xml"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed" />
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</pre>
<br />
In the java file have the following code<br />
<pre class="brush: java">public class TabsFragment extends Fragment {
View view;
Adapter adapter;
private void setupViewPager(ViewPager viewPager) {</pre>
<pre class="brush: java">
///Here we have to pass ChildFragmentManager instead of FragmentManager.
<b><span style="font-size: large;"> adapter = new Adapter(getChildFragmentManager());</span></b>
adapter.addFragment(new Fragment1(), "Fragment1");
adapter.addFragment(new Fragment2(), "Fragment2");
viewPager.setAdapter(adapter);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.f_tabslayout, container, false);
super.onCreate(savedInstanceState);
ButterKnife.bind(this, view);
final ViewPager viewPager = ButterKnife.findById(view, R.id.viewpager);
setupViewPager(viewPager);
TabLayout tabLayout = ButterKnife.findById(view, R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
static class Adapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments = new ArrayList<>();
private final List<String> mFragmentTitles = new ArrayList<>();
public Adapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}
public void addFragment(Fragment fragment, String title) {
mFragments.add(fragment);
mFragmentTitles.add(title);
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitles.get(position);
}
}
}
</pre>
<br />
Hope this helps. Happy coding :)<br />
<br />
<br />
<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com12tag:blogger.com,1999:blog-228035961089966192.post-19917611473411043532015-08-20T17:32:00.000+05:302015-08-20T17:32:02.557+05:30Re-Login using Facebook SDK in Android Application<div dir="ltr" style="text-align: left;" trbidi="on">
Hello,<br />
<br />
Android applications often require login to identify the user and provide user specific content. Facebook login is one of the popular SDK used to authenticate users.<br />
<br />
<a name='more'></a>In this post I will share the code to smoothly re-login the user using Facebook SDK.<br />
<br />
Following is complete Login class which can be used for Facebook Login<br />
<br />
<pre class="brush: java">public class DemoLoginActivity extends AppCompatActivity {
LoginButton loginButton;
CallbackManager callbackManager;
FacebookCallback<LoginResult> loginResultFacebookCallback = new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(final LoginResult loginResult) {
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
@Override
public void onCompleted(
JSONObject object,
GraphResponse response) {
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id, name, picture,email");
request.setParameters(parameters);
request.executeAsync();
}
@Override
public void onCancel() {
}
@Override
public void onError(FacebookException exception) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(getApplicationContext());
setContentView(R.layout.loginflow);
loginButton = (LoginButton) findViewById(R.id.facebook_button);
List<String> permissions = new ArrayList<>();
permissions.add("email");
loginButton.setReadPermissions(permissions);
callbackManager = CallbackManager.Factory.create();
loginButton.registerCallback(callbackManager, loginResultFacebookCallback);
LoginManager.getInstance().registerCallback(callbackManager, loginResultFacebookCallback);
AccessToken accessToken = AccessToken.getCurrentAccessToken();
if (accessToken != null) {
if (accessToken.isExpired()) {
LoginManager.getInstance().logOut();
} else {
/// This is code responsible for re-login
LoginManager.getInstance().logInWithReadPermissions(this, permissions);
}
}
}
protected void onActivityResult(int requestCode, int responseCode,
Intent intent) {
super.onActivityResult(requestCode, responseCode, intent);
callbackManager.onActivityResult(requestCode, responseCode, intent);
}
}
Hope this helps. Happy coding :)
</pre>
<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-55412368904563998602015-07-21T09:12:00.000+05:302015-07-21T15:22:50.921+05:30EventBus with Volley in Android Application<div dir="ltr" style="text-align: left;" trbidi="on">
Hello:<br />
<br />
Developing De-coupled applications always helps in maintainability of the project. In android application development we use listener pattern using interfaces to handle callback. Though it gets the work done but with bigger projects this may result into maintainability issues.<br />
<br />
<a name='more'></a>In this post I will explain how to use Android Volley with EventBus without interface listeners.<br />
<br />
Volley: This library makes network calls and caching very easy. More info can be found <a href="http://blog.ashwanik.in/2015/07/7-must-have-libraries-in-android-application.html" target="_blank">here</a>.<br />
EventBus: This tiny library helps in implementing subscriber-publisher model with ease. More info can be found <a href="http://blog.ashwanik.in/2015/07/7-must-have-libraries-in-android-application.html" target="_blank">here</a>.<br />
<br />
Let us start.<br />
<br />
<ol style="text-align: left;">
<li>We will create a blank Project using Android Studio</li>
<li>In the build.gradle add following dependencies
<br />
<br />
<pre class="brush: java"> compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.mcxiaoke.volley:library:1.0.17'
compile 'de.greenrobot:eventbus:2.4.0'
compile 'com.google.code.gson:gson:2.3.1'
</pre>
<br />
</li>
<li>
Create class VolleyManager.java. This is singleton class for Volley.
<br />
<pre class="brush: java">public class VolleyManager {
private static VolleyManager instance;
private RequestQueue mRequestQueue;
public synchronized static void initialize(Context context) {
if (instance == null) {
instance = new VolleyManager();
instance.mRequestQueue = Volley.newRequestQueue(context);
}
}
public synchronized static VolleyManager getInstance() {
return instance;
}
public RequestQueue getRequestQueue() {
return mRequestQueue;
}
}
</pre>
<br />
</li>
<li>
BaseApplication to extend Applicaton class.
<br />
<pre class="brush: java">public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
VolleyManager.initialize(this);
}
}
</pre>
<br />
</li>
<li>
Create class HTTPRequestManager.java. This class will responsible for making network call using Volley
<br />
<pre class="brush: java">public class HTTPRequestManager<P extends BaseSuccessEvent, Q extends BaseErrorEvent> {
public static final String TAG = HTTPRequestManager.class.getSimpleName();
public boolean isBaseActivity;
ProgressDialog progressDialog;
int responseCode;
ErrorData errorData;
Response.Listener<JSONObject> jsonResponseListener;
Response.ErrorListener errorListener;
EventBus eventBus = EventBus.getDefault();
private HashMap<String, String> params;
private HashMap<String, String> headers;
private String url;
private Context context;
private Class<P> pClass;
private Class<Q> qClass;
public HTTPRequestManager(Context context, String url, Class<P> pClass, Class<Q> qClass) {
this.context = context;
this.url = url;
params = new HashMap<>();
headers = new HashMap<>();
addJSONHeaders();
errorData = new ErrorData();
isBaseActivity = true;
this.pClass = pClass;
this.qClass = qClass;
setListeners();
}
private void addJSONHeaders() {
AddHeader("Accept", "application/json");
AddHeader("Content-type", "application/json");
}
private void setListeners() {
jsonResponseListener = new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
dismissProgressDialog();
try {
P res = pClass.newInstance();
res.setResponse(response.toString());
eventBus.post(res);
} catch (Exception e) {
e.printStackTrace();
}
}
};
errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
dismissProgressDialog();
try {
Q err = qClass.newInstance();
ErrorData errorData = new ErrorData();
errorData.setMessage(error.toString());
err.setErrorData(errorData);
eventBus.post(err);
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
public HashMap<String, String> getParams() {
return params;
}
public HashMap<String, String> getHeaders() {
return headers;
}
public String getCompleteUrl() {
return url;
}
public int getResponseCode() {
return responseCode;
}
public ErrorData getErrorData() {
return errorData;
}
public void execute() {
progressDialog = new ProgressDialog(context);
progressDialog.setCancelable(false);
dismissProgressDialog();
progressDialog.show();
addToRequestQueue(getJsonRequest());
}
public void dismissProgressDialog() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
private <X> void addToRequestQueue(Request<X> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
VolleyManager.getInstance().getRequestQueue().add(req);
}
private <X> void addToRequestQueue(Request<X> req) {
addToRequestQueue(req, "");
}
public void AddParam(String name, String value) {
params.put(name, value);
}
public void AddHeader(String name, String value) {
headers.put(name, value);
}
Request<JSONObject> getJsonRequest() {
try {
getUrl();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new JsonObjectRequest(Request.Method.GET, url, jsonResponseListener, errorListener) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers;
}
@Override
protected Map<String, String> getParams() {
return params;
}
};
}
void getUrl() throws UnsupportedEncodingException {
String combinedParams = "";
if (!params.isEmpty()) {
combinedParams += "?";
for (Map.Entry<String, String> entry : params.entrySet()) {
String paramString = entry.getKey() + "="
+ URLEncoder.encode(entry.getValue(), "UTF-8");
if (combinedParams.length() > 1) {
combinedParams += "&" + paramString;
} else {
combinedParams += paramString;
}
}
}
url = url + combinedParams;
}
}
</pre>
</li>
<li>Because of Type Erasure in Java we can't use generic events with EventBus. <br />
We will create BaseEvents for Success and Error and then extend them for specific events
<br />
BaseSuccessEvent<br />
<pre class="brush: java">public class BaseSuccessEvent {
private String response;
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public <T> T getTypedResponse(Class<T> tClass) throws ClassNotFoundException {
return Json.deSerialize(response, tClass);
}
}
</pre>
<br />
BaseErrorEvent<br />
<pre class="brush: java">public class BaseErrorEvent {
private ErrorData errorData;
public ErrorData getErrorData() {
return errorData;
}
public void setErrorData(ErrorData errorData) {
this.errorData = errorData;
}
}
</pre>
<br />
</li>
<li>Now all set to use these
In the activity where we want to make network calls, code will look this
<br />
<pre class="brush: java">public class MainActivity extends ActionBarActivity {
static String TAG = "VolleyEventBus";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@EventBusHook
public void onEvent(GithubUserSuccessEvent githubUserSuccessEvent) {
Toast.makeText(this, "Success", Toast.LENGTH_SHORT).show();
Log.d(TAG, githubUserSuccessEvent.getResponse());
}
@EventBusHook
public void onEvent(GithubUserErrorEvent githubUserErrorEvent) {
Toast.makeText(this, "Error occurred.", Toast.LENGTH_SHORT).show();
Log.d(TAG, githubUserErrorEvent.getErrorData().getMessage());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
Button requests = (Button) findViewById(R.id.requests);
requests.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
HTTPRequestManager<GithubUserSuccessEvent, GithubUserErrorEvent> request = new HTTPRequestManager<>(MainActivity.this, "https://api.github.com/users/ashwanikumar04", GithubUserSuccessEvent.class, GithubUserErrorEvent.class);
request.execute();
}
});
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
</pre>
<br />
</li>
</ol>
Full working code can be downloaded from <a href="http://www.ashwanik.in/blog/downloads">here</a>.<br />
Hope this helps. Happy coding.
</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com5tag:blogger.com,1999:blog-228035961089966192.post-51451367139196096832015-07-12T20:48:00.000+05:302015-07-12T23:36:58.776+05:30Seven must have libraries in any android application<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
Developing a stable and professional application requires discipline and better coding practices. Sometimes it turns out that re-inventing the wheel also leads to some issues which can be avoided by using external libraries.<br />
<a name='more'></a>In this post I will share <b>SEVEN </b>must have libraries for any android application to enable fast and stable application development.<br />
<br />
<ol style="text-align: left;">
</ol>
<u><b>Making seamless network calls:</b></u><br />
<ol style="text-align: left;">
</ol>
<span style="font-size: large;"><span style="color: #16a085;"><b>Volley</b></span>:</span> It is an awesome library to make network calls. More info can be found <a href="https://developer.android.com/training/volley/index.html" rel="nofollow" target="_blank">here</a>. Sample class to make new web request<br />
<pre class="brush: java">public class HttpRequest {
ProgressDialog progressDialog;
int responseCode;
IAsyncCallback callback;
Response.Listener<JSONObject> jsonResponseListener;
Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
dismissProgressDialog();
callback.onError(new ErrorDetail(error));
}
};
private HashMap<String, String> params;
private HashMap<String, String> headers;
private String url;
private Activity context;
private String gameObject;
public HttpRequest(Activity localActivity,
String url, String gameObjectName) {
context = localActivity;
this.url = url;
gameObject = gameObjectName;
headers = new HashMap<>();
params = new HashMap<>();
addJSONHeaders();
setListeners();
}
public IAsyncCallback getCallback() {
return callback;
}
public Context getContext() {
return context;
}
private void addJSONHeaders() {
AddHeader("Accept", "application/json");
AddHeader("Content-type", "application/json");
}
private void setListeners() {
jsonResponseListener = new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
dismissProgressDialog();
WebResponse backendResponse;
try {
String responseString = response.toString();
backendResponse = new WebResponse(responseCode,
responseString);
if (responseString == null) {
callback.onError(new ErrorDetail(new Exception("Empty response returned")));
} else {
callback.onComplete(backendResponse);
}
} catch (Exception exception) {
exception.printStackTrace();
callback.onError(new ErrorDetail(exception));
}
}
};
}
public void AddParam(String name, String value) {
params.put(name, value);
}
public void AddHeader(String name, String value) {
headers.put(name, value);
}
public void dismissProgressDialog() {
context.runOnUiThread(new Runnable() {
@Override
public void run() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
});
}
public void execute() {
this.callback = new IAsyncCallback() {
@Override
public void onComplete(WebResponse responseContent) {
//Do processing
}
@Override
public void onError(ErrorDetail errorData) {
//Do processing
}
};
context.runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog = new ProgressDialog(getContext());
progressDialog.setCancelable(false);
progressDialog.setMessage("Please wait...");
dismissProgressDialog();
progressDialog.show();
}
});
addToRequestQueue(VolleyManager.getInstance(context).getRequestQueue(), getJsonRequest());
}
public <X> void addToRequestQueue(RequestQueue requestQueue, Request<X> req) {
requestQueue.add(req);
}
Request<JSONObject> getJsonRequest() {
try {
getUrl();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new JsonObjectRequest(Request.Method.GET, url, jsonResponseListener, errorListener) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers;
}
@Override
protected Map<String, String> getParams() {
return params;
}
};
}
void getUrl() throws UnsupportedEncodingException {
String combinedParams = "";
if (!params.isEmpty()) {
combinedParams += "?";
for (Map.Entry<String, String> entry : params.entrySet()) {
String paramString = entry.getKey() + "="
+ URLEncoder.encode(entry.getValue(), "UTF-8");
if (combinedParams.length() > 1) {
combinedParams += "&" + paramString;
} else {
combinedParams += paramString;
}
}
}
url = url + combinedParams;
}
}
</pre>
<br />
VolleyManager.Java<br />
<pre class="brush: java">public class VolleyManager {
private static VolleyManager instance;
private RequestQueue mRequestQueue;
public RequestQueue getRequestQueue() {
return mRequestQueue;
}
public synchronized static VolleyManager getInstance(Activity activity) {
if (instance == null) {
instance = new VolleyManager();
instance.mRequestQueue = Volley.newRequestQueue(activity);
}
return instance;
}
}
</pre>
<br />
<br />
<u><b>Downloading and caching images</b></u><br />
<br />
<span style="font-size: large;"><span style="color: #16a085;"><b>Glide</b></span>: <span style="font-size: small;">This library is designed for high performance during scrolling. It is ideal for caching and showing data is scrollable layouts (Gridview, ListView, RecyclerView etc). More info can be found <a href="https://github.com/bumptech/glide" rel="nofollow" target="_blank">here</a></span></span><br />
Using Glide is as simple as following code.<br />
<pre class="brush: java"> Glide.with(this).load(data.imageUrl).into(imageView);
</pre>
<br />
<u><b>JSON serialization and de-serialization</b></u><br />
<br />
<span style="font-size: large;"><span style="color: #16a085;"><b>GSON</b></span>: <span style="font-size: small;">This library provides easy to use methods for serializing and de-serializing data. More info can be found <a href="https://github.com/google/gson" rel="nofollow" target="_blank">here</a>.</span></span><br />
<span style="font-size: large;"><span style="font-size: small;">Following is a helper class which can be used to serialize and de-serialize data.</span></span><br />
<pre class="brush: java">public class Json {
public static <T> String serialize(T obj) {
Gson gson = new Gson();
return gson.toJson(obj);
}
public static <T> T deSerialize(String jsonString, Class<T> tClass) throws ClassNotFoundException {
Gson gson = new GsonBuilder().create();
return gson.fromJson(jsonString, tClass);
}
}
</pre>
<br />
<u><b>Exception and Crash logging</b></u><br />
<br />
<span style="color: #16a085;"><b><span style="font-size: large;">Crashlytics</span></b></span>: This library provides exception and crash logging which can help in catching bugs which may skip to production application. More info can be found <a href="http://try.crashlytics.com/sdk-android/" rel="nofollow" target="_blank">here</a>. Sample code can be found in this <a href="http://blog.ashwanik.in/2015/06/exception-handling-in-android.html" target="_blank">post</a>.<br />
<br />
<span style="font-size: large;"><span style="font-size: small;"><br /></span></span>
<br />
<u><b><span style="font-size: large;"><span style="font-size: small;">Avoiding boiler plate code by Dependency Injection</span></span></b></u><br />
<br />
<span style="color: #16a085;"><b><span style="font-size: large;">ButterKnife</span></b></span>: This library helps in removing boiler plate code which is repeated everywhere to nice and more readable code. More info can be found here.
This library converts following code<br />
<br />
<pre class="brush: java">public class SampleActivity extends Activity {
TextView txtName;
TextView txtEmail;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user);
txtName = (TextView)findViewById(R.id.name);
txtEmail = (TextView)findViewById(R.id.email);
}
}
</pre>
<br />
<b>TO</b><br />
<br />
<pre class="brush: java">public class SampleActivity extends Activity {
@Bind(R.id.name)
TextView txtName;
@Bind(R.id.email)
TextView txtEmail;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user);
ButterKnife.bind(this);
}
}
</pre>
<br />
<br />
<u><b>Passing data between activities</b></u><br />
<br />
<span style="color: #16a085;"><b><span style="font-size: large;">Parceler</span></b></span>: This library makes it super easy to pass object between activities. More info can be found <a href="https://github.com/johncarl81/parceler" rel="nofollow" target="_blank">here.</a><br />
<br />
<br />
<b><u>Communicating and passing data as events</u></b><br />
<br />
<span style="color: #16a085;"><b><span style="font-size: large;">EventBus</span></b></span>: This tiny library makes is very easy to pass data as events in the application. More info related to this library can be found <a href="https://github.com/greenrobot/EventBus" rel="nofollow" target="_blank">here</a>.<br />
<br />
<ul>
<li>Define events:<br />
<pre class="brush: java"> public class SampleEvent { }
</pre>
</li>
<li>Prepare subscribers:<br />
<pre class="brush: java"> eventBus.register(this);
public void onEvent(SampleEvent event) {/* Do something */};
</pre>
</li>
<li>Post events:<br />
<pre class="brush: java"> eventBus.post(event);
</pre>
</li>
</ul>
Hope this helps. Happy coding.</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-58615247918280499052015-06-29T10:35:00.000+05:302015-06-29T12:35:39.319+05:30Advanced exception debugging using Android Studio<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
During application development we often encounter situations where we need to debug our application by attaching the running application as a process to Android Studio.<br />
<a name='more'></a>In this post I will some settings/ features offered by Android Studio which can help us in debugging applications.<br />
<b><br /></b>
<b>I am using following version of Android Studio:</b><br />
<b><br /></b>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-hdph_wvgoLc/VZDOGscVejI/AAAAAAAAEKg/zNYrMfXEKBQ/s1600/Android%2BStudio.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="238" src="http://4.bp.blogspot.com/-hdph_wvgoLc/VZDOGscVejI/AAAAAAAAEKg/zNYrMfXEKBQ/s320/Android%2BStudio.jpg" width="320" /></a></div>
<b><br /></b>
<b><br /></b>
<b>Tip #1: Configuring Android Studio Debugger to break on a uncaught exception</b><br />
<br />
By default Android Studio debugger does not break on <b>uncaught </b>exceptions. To enable this feature we need to do some tweaks in settings.<br />
Go to Run-> View BreakPoints <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-oit5QHZjQ_Q/VZDONZjnz_I/AAAAAAAAEKo/UgrvOSWkskg/s1600/Exception%2BSetting.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="http://3.bp.blogspot.com/-oit5QHZjQ_Q/VZDONZjnz_I/AAAAAAAAEKo/UgrvOSWkskg/s400/Exception%2BSetting.jpg" width="220" /></a></div>
<br />
<br />
Then replicate the following settings<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-6yB0dVfBoo8/VZDOYPUuO4I/AAAAAAAAEKw/Ji_MFPOOgbs/s1600/Uncaught%2BException.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="282" src="http://1.bp.blogspot.com/-6yB0dVfBoo8/VZDOYPUuO4I/AAAAAAAAEKw/Ji_MFPOOgbs/s400/Uncaught%2BException.jpg" width="400" /></a></div>
<br />
<br />
Try running the application in debug mode, you will see the debugger breaks when ever we have uncaught exceptions.<br />
<br />
<b><br /></b>
<b>Tip #2: Analyzing stack trace using Android Studio</b><br />
<br />
In our applications we ofter use external libraries to report caught and uncaught exceptions. We can receive the stack trace using the web interface which is often provided by these libraries. Android studio has a very good feature of analyzing these stack trace and point to the culprit line of code.<br />
<br />
Suppose following is the stack trace which we received externally.<br />
<pre class="brush: java">06-29 10:24:05.479 5324-5324/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: ashwani.in.blogdemo, PID: 5324
java.lang.ArithmeticException: divide by zero
at ashwani.in.blogdemo.MainActivity$1.onClick(MainActivity.java:25)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
</pre>
<br />
Open the project of which you have the stack trace.<br />
<br />
Now if we want to pin point the culprit code we can either go through the entire stack track (which is easy in current case but can be messy) or we can use Android Studio's Analyze<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-gNXC6SUiX_Y/VZDQopIADwI/AAAAAAAAEK8/SWSUcpMo938/s1600/Analyze%2BStacktrace.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="395" src="http://3.bp.blogspot.com/-gNXC6SUiX_Y/VZDQopIADwI/AAAAAAAAEK8/SWSUcpMo938/s400/Analyze%2BStacktrace.jpg" width="400" /></a></div>
<br />
<br />
Click on this and it will pop-up following window<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-R7Nipdk7Hzg/VZDRC2mw_BI/AAAAAAAAELE/wKRCw5O5yIc/s1600/Analyze%2BStacktrace%2BInput.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="383" src="http://2.bp.blogspot.com/-R7Nipdk7Hzg/VZDRC2mw_BI/AAAAAAAAELE/wKRCw5O5yIc/s400/Analyze%2BStacktrace%2BInput.jpg" width="400" /></a></div>
<br />
Hit OK, and you will the stack trace in red with clickable link to Java files.<br />
<br />
Hope this helps. Happy coding.<br />
<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-79722030758482221362015-06-17T09:07:00.001+05:302015-06-17T09:07:36.343+05:30Exception handling in Android Application<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
During application development for any platform there are chances of missing some corner cases which in turn leads to exceptions which can lead to crashes. In terms of android applications development this leads to crash of the application with a pop-up saying<br />
<div style="text-align: center;">
<b>"XYZ has stopped working"</b></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
</div>
<a name='more'></a>There are various frameworks/ libraries available which can help is tracing down these unhandled exceptions. Some of these are<br />
<ol style="text-align: left;">
<li><a href="http://docs.crittercism.com/android/android.html" rel="nofollow" target="_blank">Crittercism</a></li>
<li><a href="https://parse.com/docs/android/guide" rel="nofollow" target="_blank">Parse</a></li>
<li><a href="https://try.crashlytics.com/" rel="nofollow" target="_blank">Crashlytics</a></li>
</ol>
My personal favorite is Crashlytics. Crashlytics is almost free. You can get your copy from <a href="http://try.crashlytics.com/pricing/" rel="nofollow" target="_blank">here</a>. <br />
<br />
Crashlytics comes with its own plugin for Android Studio which will do all the heavy lifting of setting up the library in your project.<br />
<br />
Once the library is setup in the project logging is as easy as calling<br />
<br />
<pre class="brush: java">Crashlytics.getInstance().core.logException(e);
</pre>
<br />
However I like to make it more general. Below is the Interface which I use to log the exceptions (handled)<br />
<br />
<pre class="brush: java">public interface ILogger {
void log(String message);
void log(Exception exception);
}
</pre>
<br />
then setting up it in a sub-class of Application.<br />
<pre class="brush: java"> public ILogger getLogger() {
if (logger == null) {
logger = new ILogger() {
@Override
public void log(String message) {
Crashlytics.getInstance().core.log(message);
}
@Override
public void log(Exception e) {
StringWriter errors = new StringWriter();
e.printStackTrace(new PrintWriter(errors));
log(errors.toString());
Crashlytics.getInstance().core.logException(e);
}
};
}
return logger;
}
</pre>
<br />
Use it like<br />
<pre class="brush: java">SuperApplication.getInstance().getLogger().log(exception);
</pre>
<br />
Here SuperApplication is sub-class of Application class.<br />
<br />
Hope this helps. Happy coding.<br />
<br />
<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-24996899793855421042015-05-31T22:04:00.000+05:302015-06-01T07:40:24.997+05:30EventHandling for Unity 4.6 UI Event system<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
Unity 4.6 comes with new UI system which has different way of handling different event like mouse over, mouse out, mouse in, click etc. <br />
<a name='more'></a>In this post I will share how to handle these events properly in Unity 4.6 UI. Unity 4.6 UI provides following Interfaces to handle these events<br />
<ul style="text-align: left;">
<li>IPointerEnterHandler</li>
<li>IPointerClickHandler</li>
<li>IPointerExitHandler</li>
</ul>
Full List can be found <a href="http://docs.unity3d.com/ScriptReference/EventSystems.IBeginDragHandler.html" rel="nofollow" target="_blank">here</a>. <br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-zwmrcvHd7VE/VWsXMl1h8FI/AAAAAAAAEGk/coVbrX37upc/s1600/interfaces.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="http://2.bp.blogspot.com/-zwmrcvHd7VE/VWsXMl1h8FI/AAAAAAAAEGk/coVbrX37upc/s400/interfaces.jpg" width="210" /></a></div>
<br />
Following code shows how to handle these interfaces
<pre class="brush: csharp">
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
public class AwesomeGameObject : IPointerEnterHandler, IPointerClickHandler, IPointerExitHandler
{
void Awake()
{
}
public void Start()
{
}
public void OnPointerEnter(PointerEventData eventData)
{
//handle this for pointer enter
}
public void OnPointerClick(PointerEventData eventData)
{
//Handle this for click
}
public void OnPointerExit(PointerEventData eventData)
{
//Handle this for exit
}
}
</pre>
<br />
Hope this helps. Happy coding.
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-89207527554465801032015-05-17T19:23:00.001+05:302015-06-17T11:14:02.230+05:30Handling adapter error while using RecyclerView in Android<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html" rel="nofollow" target="_blank">RecyclerView </a>is introduced with Android L and is also available with AppCompat library. RecyclerView provides better layout option and performance as compared to ListView. However, in this post I will share one of the possible solutions to a problem which occurs with RecyclerView.<br />
<a name='more'></a>Often in our application we rely on network data to be populated in our views. With RecyclerView one problem occurs when the data is not available during initialization.<br />
<br />
In the logcat, you can often see following error.<br />
<pre class="brush: java">recyclerview No adapter attached; skipping layout
</pre>
<br />
<br />
One way to fix this issue is to attach an empty adapter to the RecyclerView<br />
<br />
<pre class="brush: java"> void initializeRecyclerView() {
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
recyclerView.setAdapter(new SampleAdapter(getCurrentActivity()));
recyclerView.setLayoutManager(new LinearLayoutManager(getCurrentActivity()));
recyclerView.setHasFixedSize(true);
}</pre>
<pre class="brush: java"> </pre>
Call this method in OnCreateView or OnCreate methods.
<br />
Hope this helps. Let me know if you know any other way of fixing the issue.<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com4tag:blogger.com,1999:blog-228035961089966192.post-1456997077394298812015-05-08T00:12:00.000+05:302015-05-08T00:15:24.820+05:30Integrate Android Volley with Unity3d game<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
<a href="https://developer.android.com/training/volley/index.html" rel="nofollow" target="_blank">Volley</a> is a very robust framework to make network calls. It provides out of the box support for caching, retry etc. In this post I will show how to integrate Volley with in a unity game.<br />
<br />
<a name='more'></a>This post assumes you have idea of writing plugins for Unity3d. You can see these posts to get an idea for the same<br />
<ol style="text-align: left;">
<li><a href="http://blog.ashwanik.in/2013/09/android-plug-in-for-unity3d-part-1.html" rel="nofollow" target="_blank">Tutorial 1</a></li>
<li><a href="http://blog.ashwanik.in/2013/09/android-plug-in-for-unity3d-part-2.html" rel="nofollow" target="_blank">Tutorial 2</a></li>
</ol>
<br />
Integrating Volley with Unity game will involve two steps:<br />
<ol style="text-align: left;">
<li>We will create a plugin which will act as an bridge between Unity and Android</li>
<li>In unity game we will invoke this plugin</li>
</ol>
<br />
<b>Let us start with step 1:</b> <br />
<br />
Create an android application using Android Studio.<br />
<br />
<ol style="text-align: left;">
<li>Add Volley library to libs folder. You can get the Volley.jar from <a href="http://blog.ashwanik.in/2015/04/delete-expired-cached-entries-of-volley.html" target="_blank">here</a>.</li>
<li>Add classes.jar from {Unity Installation Directory}\Editor\Data\PlaybackEngines\androidplayer\release\bin </li>
</ol>
Now create a new class HttpRequest.java<br />
<pre class="brush: java">
public class HttpRequest {
ProgressDialog progressDialog;
int responseCode;
IAsyncCallback callback;
Response.Listener<JSONObject> jsonResponseListener;
Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
dismissProgressDialog();
callback.onError(new ErrorDetail(error));
}
};
private HashMap<String, String> params;
private HashMap<String, String> headers;
private String url;
private Activity context;
private String gameObject;
public HttpRequest(Activity localActivity,
String url, String gameObjectName) {
context = localActivity;
this.url = url;
gameObject = gameObjectName;
headers = new HashMap<>();
params = new HashMap<>();
addJSONHeaders();
setListeners();
}
public IAsyncCallback getCallback() {
return callback;
}
public Context getContext() {
return context;
}
private void addJSONHeaders() {
AddHeader("Accept", "application/json");
AddHeader("Content-type", "application/json");
}
private void setListeners() {
jsonResponseListener = new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
dismissProgressDialog();
WebResponse backendResponse;
try {
String responseString = response.toString();
backendResponse = new WebResponse(responseCode,
responseString);
if (responseString == null) {
callback.onError(new ErrorDetail(new Exception("Empty response returned")));
} else {
callback.onComplete(backendResponse);
}
} catch (Exception exception) {
exception.printStackTrace();
callback.onError(new ErrorDetail(exception));
}
}
};
}
public void AddParam(String name, String value) {
params.put(name, value);
}
public void AddHeader(String name, String value) {
headers.put(name, value);
}
public void dismissProgressDialog() {
context.runOnUiThread(new Runnable() {
@Override
public void run() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
});
}
public void execute() {
this.callback = new IAsyncCallback() {
@Override
public void onComplete(WebResponse responseContent) {
UnityPlayer.UnitySendMessage(gameObject, "OnComplete", responseContent.getResponse());
}
@Override
public void onError(ErrorDetail errorData) {
UnityPlayer.UnitySendMessage(gameObject, "OnError", errorData.toString());
}
};
context.runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog = new ProgressDialog(getContext());
progressDialog.setCancelable(false);
progressDialog.setMessage("Please wait...");
dismissProgressDialog();
progressDialog.show();
}
});
addToRequestQueue(VolleyManager.getInstance(context).getRequestQueue(), getJsonRequest());
}
public <X> void addToRequestQueue(RequestQueue requestQueue, Request<X> req) {
requestQueue.add(req);
}
Request<JSONObject> getJsonRequest() {
try {
getUrl();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new JsonObjectRequest(Request.Method.GET, url, jsonResponseListener, errorListener) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers;
}
@Override
protected Map<String, String> getParams() {
return params;
}
};
}
void getUrl() throws UnsupportedEncodingException {
String combinedParams = "";
if (!params.isEmpty()) {
combinedParams += "?";
for (Map.Entry<String, String> entry : params.entrySet()) {
String paramString = entry.getKey() + "="
+ URLEncoder.encode(entry.getValue(), "UTF-8");
if (combinedParams.length() > 1) {
combinedParams += "&" + paramString;
} else {
combinedParams += paramString;
}
}
}
url = url + combinedParams;
}
}
</pre>
<br />
VolleyManager.Java<br />
<pre class="brush: java">
public class VolleyManager {
private static VolleyManager instance;
private RequestQueue mRequestQueue;
public RequestQueue getRequestQueue() {
return mRequestQueue;
}
public synchronized static VolleyManager getInstance(Activity activity) {
if (instance == null) {
instance = new VolleyManager();
instance.mRequestQueue = Volley.newRequestQueue(activity);
}
return instance;
}
}
</pre>
<br />
Generate jar using build.gradle<br />
<br />
Now create a unity game. Add the above generate jar to Plugins/Android/ and Volley.jar to Plugins/Android/libs<br />
<br />
Create following scripts<br />
<br />
VolleyManager.cs<br />
<pre class="brush: csharp">
public class VolleyManager
{
private AndroidJavaObject unityActivity;
private VolleyManager()
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
}
public static VolleyManager Instance
{
get
{
return Inner.instance;
}
}
private class Inner
{
static Inner() { }
internal static readonly VolleyManager instance = new VolleyManager();
}
public void AddRequest(Request request)
{
GameObject gameObject = new GameObject(DateTime.Now.Ticks.ToString());
VolleyBindings volleyBindings = gameObject.AddComponent<VolleyBindings>();
volleyBindings.OnCompleteHandler = request.OnComplete;
volleyBindings.OnErrorHandler = request.OnError;
AndroidJavaObject httpRequest = new AndroidJavaObject("in.ashwanik.volleyandoid.HttpRequest", unityActivity, request.URL, gameObject.name);
foreach (var param in request.Params)
{
httpRequest.Call("AddParam", param.Key, param.Value);
}
foreach (var header in request.Headers)
{
httpRequest.Call("AddHeader", header.Key, header.Value);
}
httpRequest.Call("execute");
}
}
public class Request
{
public string URL { get; set; }
public Action<string> OnComplete { get; set; }
public Action<string> OnError { get; set; }
public Dictionary<string, string> Params { get; private set; }
public Dictionary<string, string> Headers { get; private set; }
public Request()
{
Params = new Dictionary<string, string>();
Headers = new Dictionary<string, string>();
}
}
</pre>
<br />
VolleyBindings.cs<br />
<pre class="brush: csharp">
public class VolleyBindings : MonoBehaviour {
public Action<string> OnCompleteHandler { get; set; }
public Action<string> OnErrorHandler { get; set; }
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void OnComplete(String response)
{
OnCompleteHandler(response);
DestroyObject(this.gameObject);
}
public void OnError(string error)
{
OnErrorHandler(error);
DestroyObject(this.gameObject);
}
}
</pre>
<br />
RequestTester.cs<br />
<pre class="brush: csharp">
public class RequestTester : MonoBehaviour
{
public Text logger;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void Request1()
{
Request request = new Request();
request.URL = "http://www.ashwanik.in/blog/blogpost";
request.Params.Add("data", "test data");
request.OnComplete = (data) =>
{
logger.text += "data: " + data + "\n";
Debug.Log("data: " + data);
};
request.OnError = (error) =>
{
Debug.Log("error: " + error);
};
VolleyManager.Instance.AddRequest(request);
}
}
</pre>
<br />
Hope this helps. You can get fully working code from <a href="http://www.ashwanik.in/blog/downloads">here</a>.<br />
Happy coding<br />
<br />
<br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-89991312019287387112015-04-27T20:44:00.000+05:302015-04-27T20:44:21.753+05:30HTML parsing using JSoup and Volley in Android Application<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
In application development, sometimes we want to parse HTML data to get relevant information. In this post I will show you how to parse HTML data using JSoup and Volley.<br />
<br />
<a name='more'></a>Let us start.<br />
<br />
We will be using following external libraries<br />
<ol style="text-align: left;">
<li>JSoup: JSoup is a Java library for working with real-world HTML.
It provides a very convenient API for extracting and manipulating data,
using the best of DOM, CSS, and jquery-like methods. More info can be found <a href="http://jsoup.org/" rel="nofollow" target="_blank">here</a>. </li>
<li>Volley: Volley is an excellent framework to make network calls.More info can be found <a href="https://developer.android.com/training/volley/index.html" rel="nofollow" target="_blank">here</a>. </li>
</ol>
Project structure<br />
<ol style="text-align: left;">
<li> Interfaces</li>
<ol>
<li>IHTMLParser</li>
<li>IAsyncCallback</li>
</ol>
<li>Classes</li>
<ol>
<li>HTMLParseAsyncTask: Extends Async task</li>
<li>BlogPostParser: Implements IHTMLParser</li>
<li>BaseHttpRequest: Main class to make network calls</li>
</ol>
</ol>
For Volley, we will be using Singleton.One way of achieving this is by extending Application class.<br />
Below are some of the important classes to use. I will be sharing the link for fully functional code at the bottom of the post.
<br />
<b>BaseApplication</b><br />
<pre class="brush: java">public class BaseApplication extends Application {
private static BaseApplication sInstance;
private RequestQueue mRequestQueue;
public synchronized static BaseApplication getInstance() {
return sInstance;
}
public RequestQueue getRequestQueue() {
return mRequestQueue;
}
@Override
public void onCreate() {
super.onCreate();
sInstance = this;
mRequestQueue = Volley.newRequestQueue(this);
}
}
</pre>
<b>Interfaces</b><br />
<pre class="brush: java">public interface IAsyncCallback {
void onComplete(WebResponse responseContent);
void onError(String errorData);
}
</pre>
<br />
<pre class="brush: java">public interface IHTMLParser {
BaseObject parseHTML(String htmlToParse);
}
</pre>
<br />
<b>Classes</b><br />
<pre class="brush: java">public class BaseHttpRequest {
ProgressDialog progressDialog;
int responseCode;
IAsyncCallback callback;
Response.Listener<String> stringResponseListener;
private IHTMLParser htmlParser;
private String url;
Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
StringWriter errors = new StringWriter();
error.printStackTrace(new PrintWriter(errors));
dismissProgressDialog();
callback.onError(error.toString());
}
};
private Context context;
public BaseHttpRequest(Activity localActivity,
String url) {
context = localActivity;
this.url = url;
setListeners();
}
public IHTMLParser getHtmlParser() {
return htmlParser;
}
public void setHtmlParser(IHTMLParser htmlParser) {
this.htmlParser = htmlParser;
}
public IAsyncCallback getCallback() {
return callback;
}
public Context getContext() {
return context;
}
private void setListeners() {
stringResponseListener = new Response.Listener<String>() {
@Override
public void onResponse(String response) {
HTMLParseAsyncTask task = new HTMLParseAsyncTask();
task.setCurrentRequest(BaseHttpRequest.this);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, response);
}
};
}
public void dismissProgressDialog() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
public void execute(IAsyncCallback callback, RequestQueue requestQueue) {
this.callback = callback;
progressDialog = new ProgressDialog(getContext());
progressDialog.setCancelable(false);
progressDialog.setMessage("Please wait...");
dismissProgressDialog();
progressDialog.show();
addToRequestQueue(requestQueue, getStringRequest());
}
public <X> void addToRequestQueue(RequestQueue requestQueue, Request<X> req) {
requestQueue.add(req);
}
Request<String> getStringRequest() {
return new StringRequest(Request.Method.GET, url, stringResponseListener, errorListener);
}
}
</pre>
<br />
<pre class="brush: java">public class HTMLParseAsyncTask extends AsyncTask<String, Void, Void> {
private BaseObject baseObject;
private BaseHttpRequest currentRequest;
public BaseHttpRequest getCurrentRequest() {
return currentRequest;
}
public void setCurrentRequest(BaseHttpRequest currentRequest) {
this.currentRequest = currentRequest;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(String... params) {
if (getCurrentRequest().getHtmlParser() != null) {
baseObject = getCurrentRequest().getHtmlParser().parseHTML(params[0]);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
getCurrentRequest().dismissProgressDialog();
try {
WebResponse webResponse = new WebResponse(baseObject);
getCurrentRequest().getCallback().onComplete(webResponse);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
</pre>
<br />
<pre class="brush: java">public class BlogPostParser implements IHTMLParser {
@Override
public BaseObject parseHTML(String htmlToParse) {
BlogResponse response = new BlogResponse();
try {
Document doc = Jsoup.parse(htmlToParse);
response.setPosts(new ArrayList<BlogPost>());
BlogPost post;
Elements anchors = doc.select(".entry-header a");
for (Element anchor : anchors) {
post = new BlogPost();
post.setURL(anchor.attr("href"));
post.setText(anchor.text());
response.getPosts().add(post);
}
} catch (Exception exception) {
exception.printStackTrace();
}
return response;
}
}
</pre>
<br />
<pre class="brush: java">
public class MainActivity extends FragmentActivity {
Button button;
ListView listView;
BlogResponse blogPosts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
listView = (ListView) findViewById(R.id.listView);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
BaseHttpRequest request = new BaseHttpRequest(MainActivity.this, "http://blog.ashwanik.in/search?max-results=50");
request.setHtmlParser(new BlogPostParser());
IAsyncCallback callback = new IAsyncCallback() {
@Override
public void onComplete(WebResponse responseContent) {
blogPosts = (BlogResponse) responseContent.getTypedObject();
listView.setAdapter(new BlogPostAdapter(MainActivity.this));
}
@Override
public void onError(String errorData) {
Toast.makeText(MainActivity.this, errorData, Toast.LENGTH_SHORT).show();
}
};
request.execute(callback, BaseApplication.getInstance().getRequestQueue());
} catch (Exception e) {
Toast.makeText(MainActivity.this, "Some error occurred.", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
try {
MainActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
.parse(blogPosts.getPosts().get(i).getURL())));
} catch (Exception exception) {
exception.printStackTrace();
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
static class ViewHolder {
TextView post;
}
public class BlogPostAdapter extends BaseAdapter {
Activity context;
ArrayList<BlogPost> arrayList;
LayoutInflater inflater;
public BlogPostAdapter(Activity context) {
super();
this.context = context;
this.arrayList = blogPosts.getPosts();
inflater = context.getLayoutInflater();
}
public int getCount() {
return arrayList.size();
}
public BlogPost getItem(int position) {
return arrayList.get(position);
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
BlogPost metaData = getItem(position);
if (convertView == null) {
convertView = inflater.inflate(R.layout.r_blogpost, parent, false);
holder = new ViewHolder();
holder.post = (TextView) convertView
.findViewById(R.id.post);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.post.setText(metaData.getText());
return convertView;
}
}
}
</pre>
<br />
Hope this helps. The full working code can be found <a href="http://www.ashwanik.in/blog/downloads" target="_blank">here</a>.<br /><br /></div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com2tag:blogger.com,1999:blog-228035961089966192.post-2104639143998591992015-04-17T18:28:00.002+05:302015-04-17T18:30:52.342+05:30Change authorise email for Google Play services integration<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<br />
<br />
<br />
Hello All:<br />
<br />
<br />
In order to make games viral, one of the key component is integration of social platforms like Google+ or Facebook. <a href="https://developer.android.com/google/play-services/games.html" rel="nofollow" target="_blank">Google play services</a> is a good platform to get in touch with friends who play same game.<br />
<br />
<a name='more'></a>In this post, I will share some details which can be helpful in changing EMAIL ID which will appear, when an application/ game ask for user log-in.<br />
<br />
While registering for developer account on <a href="https://play.google.com/apps/publish" rel="nofollow" target="_blank">Google Play</a>, we use Gmail emails. There can be many reasons when you may want to change the email address shown on <a href="https://developers.google.com/games/services/console/enabling" rel="nofollow" target="_blank">"<b>Authorize your app</b>"</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-lTUd9pATQBM/VTEBKlsNG3I/AAAAAAAAD08/h8wVwKBNt5A/s1600/Authorize%2BYour%2BApp.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-lTUd9pATQBM/VTEBKlsNG3I/AAAAAAAAD08/h8wVwKBNt5A/s1600/Authorize%2BYour%2BApp.jpg" height="216" width="400" /></a></div>
<br />
Follow below steps to change this email address:<br />
<ol style="text-align: left;">
<li>You will need a Gmail account for this. (create one if you do not have)</li>
<li>Add the account mentioned in Step#1 to the <a href="https://support.google.com/googleplay/android-developer/answer/2528691?hl=en" rel="nofollow" target="_blank">developer account </a></li>
<li>Create new app with this new account</li>
<li>You may get white blank screen if you proceed to "<b>Authorize your app</b>" screen. This is because you have not accepted Google's TOS. Go to <a href="https://console.developers.google.com/" rel="nofollow" target="_blank">this </a>link and select your app. Accept TOS</li>
<li>Now you will see this new email as Google Account on "<b>Authorize your app</b>" screen.</li>
</ol>
Hope this helps. Let me know in case you face any issues.<br />
<br />
</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-46188069009809308072015-04-06T14:14:00.000+05:302015-04-06T14:14:51.151+05:30Delete expired cached entries of Volley in Android Application<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
<a href="http://developer.android.com/training/volley/index.html" rel="nofollow" target="_blank">Volley </a>is an excellent framework to make network calls from with in the android application. However sometimes we want to reduce cache size by clearing all the expired entries.<br />
<a name='more'></a>In this post I will share the code to achieve the same. I needed the list of all the cached keys. However current Volley code does not have any support for the same. I have taken the base code from <a href="https://github.com/mcxiaoke/android-volley" rel="nofollow" target="_blank">here</a>.<br />
<br />
So I extended <b>Cache</b>to add
<br />
<pre class="brush: java">public List<String> getKeysList();</pre>
<br />
Then updated <b>DiskBasedCache.cs</b> to implement this method<br />
<pre class="brush: java">@Override
public synchronized List<String> getKeysList() {
if (mEntries != null && mEntries.size() > 0) {
List<String> keys = new ArrayList<String>();
keys.addAll(mEntries.keySet());
return keys;
}
return null;
}
</pre>
Following helper method helps in deleting stale cache entries
<br />
<pre class="brush: java"> public static void clearStaleCacheEntries() {
Cache cache = BaseApplication.getInstance().getRequestQueue().getCache();
if (cache != null) {
if (cache.getKeysList() != null) {
List<String> keys = cache.getKeysList();
for (String key : keys) {
Cache.Entry entry = cache.get(key);
if (entry != null) {
if (entry.isExpired()) {
cache.remove(key);
}
}
}
}
}
}
</pre>
Use following Async task to call this method
<br />
<pre class="brush: java"> public class CacheClearAsyncTask extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
try {
Helpers.clearStaleCacheEntries();
} catch (Exception exception) {
exception.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
}
}
</pre>
<br />
The compiled Volley.jar can be found from <b><a href="http://www.ashwanik.in/blog/downloads">here</a></b>.
<br />
Hope this helps. Happy coding :)
</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-2326680723498172612015-03-29T23:23:00.000+05:302015-03-29T23:26:53.649+05:30Background worker using AlarmManager in Android<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
In our application, sometimes we need to do some operations repeatedly at a given time. Android provides different options to achieve this. One such option is use of AlarmManager.<br />
<br />
<a name='more'></a>In this post, I will share the code to achieve the above said functionality using AlarmManager.<br />
<br />
More info related to <a href="http://developer.android.com/reference/android/app/AlarmManager.html" rel="nofollow" target="_blank">AlarmManager </a>can be found here. <br />
<br />
AlarmManager provides a simple mechanism to perform operations at a given time. However one problem with AlarmManager is that they are cleared once the device is restarted. This short coming can be easily dealt with by again registering Alarms once the device is booted.<br />
<br />
So let us start.<br />
<br />
First we need to create a class extending <b>BroadcastReceiver</b>.<br />
Let us call it <b>BlogDemoReceiver</b> and copy following code in it.<br />
<br />
<pre class="brush: java">package com.ashwanik.demo.receivers;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.widget.Toast;
public class BlogDemoReceiver extends BroadcastReceiver {
public final static String BlogDemoBroadcast = "com.ashwanik.actions";
public final static int StatusNotify = 100;
static AlarmManager alarmManager;
static PendingIntent autoNotifyPendingIntent;
static Intent localIntent;
public void CancelAutoNotify(Context context) {
localIntent = new Intent(BlogDemoBroadcast);
localIntent.putExtra("type", BroadcastType.DEMO);
autoNotifyPendingIntent = PendingIntent.getBroadcast(context, StatusNotify, localIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(autoNotifyPendingIntent);
}
private void initializeSettings(Context context) {
if (alarmManager == null) {
alarmManager = (AlarmManager) (context
.getSystemService(Context.ALARM_SERVICE));
}
}
public void enableBroadCastReceiver(Context context) {
CancelAutoNotify(context);
localIntent = new Intent(BlogDemoBroadcast);
localIntent.putExtra("type", BroadcastType.DEMO);
autoNotifyPendingIntent = PendingIntent.getBroadcast(context, StatusNotify,
localIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
SystemClock.elapsedRealtime(),
3 * 60 * 60 * 1000, autoNotifyPendingIntent);
}
@Override
public void onReceive(Context context, Intent intent) {
initializeSettings(context);
String action = intent.getAction();
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
enableBroadCastReceiver(context);
return;
}
String type = BroadcastType.NONE;
if (action.equalsIgnoreCase(BlogDemoBroadcast)) {
type = intent.getExtras().getString("type");
}
if (type.equalsIgnoreCase(BroadcastType.DEMOCHANGE)) {
enableBroadCastReceiver(context);
} else if (type.equalsIgnoreCase(BroadcastType.DEMO)) {
Toast.makeText(context, "Broad cast received", Toast.LENGTH_SHORT).show();
}
}
public class BroadcastType {
public static final String NONE = "N";
public static final String DEMO = "D";
public static final String DEMOCHANGE = "DC";
}
}
</pre>
<br />
Now in order to schedule the alarms we need to Broadcast. Below code will enable to create or update an existing alarm.<br />
<br />
<pre class="brush: java"> Intent localIntent = new Intent(BlogDemoReceiver.BlogDemoBroadcast);
localIntent.putExtra("type", BlogDemoReceiver.BroadcastType.DEMOCHANGE);
currentActivity.sendBroadcast(localIntent);</pre>
<pre class="brush: java"> </pre>
Now we need to do some changes in AndroidManifest.xml<br />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED">Add this in <b><application></application></b>
</uses-permission><br />
<pre class="brush: xml">
<receiver android:name=".receivers.BlogDemoReceiver">
<intent-filter>
<action android:name="com.ashwanik.actions" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</pre>
<br />
Hope this helps. Let me know if you face any issues. Happy coding :)
</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0tag:blogger.com,1999:blog-228035961089966192.post-58130984366359902982015-03-24T21:25:00.000+05:302015-03-24T21:25:10.254+05:30Screenshot of ListView in Android Application<div dir="ltr" style="text-align: left;" trbidi="on">
Hello All:<br />
<br />
Sometimes in our application we need to save layout containing ListView as image so that it can be shared or saved somewhere.<br />
<a name='more'></a>In this post I will share the code which saves a ListView with Header view as bitmap.<br />
<br />
Following helper method can be used to save listview to an image.<br />
<pre class="brush: java">
public static <T extends BaseAdapter> String getBitmapPath(ListView view, T adapter) {
try {
view.setDrawingCacheEnabled(true);
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.buildDrawingCache(true);
List<Bitmap> bitmaps = new ArrayList<Bitmap>();
int count = adapter.getCount();
bitmaps.add(view.getDrawingCache());
int fullHeight = view.getHeight();
for (int index = 0; index < count; index++) {
View childView = adapter.getView(index, null, view);
childView.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());
childView.setDrawingCacheEnabled(true);
childView.buildDrawingCache(true);
bitmaps.add(childView.getDrawingCache());
fullHeight += childView.getMeasuredHeight();
}
Bitmap bitmapToSave = Bitmap.createBitmap(view.getWidth(), fullHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmapToSave);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
int height = 0;
for (Bitmap bitmap : bitmaps) {
canvas.drawBitmap(bitmap, 0, height, paint);
height += bitmap.getHeight();
bitmap.recycle();
}
///To support older devices
for (int index = 0; index < count; index++) {
View childView = adapter.getView(index, null, view);
childView.setDrawingCacheEnabled(false);
}
bitmaps.clear();
File file, outputFile;
file = new File(android.os.Environment.getExternalStorageDirectory(), "cacheFolder");
if (!file.exists()) {
file.mkdirs();
}
String path = file.getAbsolutePath() + File.separator + "listview" + ".png";
outputFile = new File(path);
FileOutputStream outputStream = new FileOutputStream(outputFile);
bitmapToSave.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
outputStream.close();
view.setDrawingCacheEnabled(false);
return path;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
</pre>
This helper method can be used save listview as an image.
<br />
Hope this helps. Happy coding :)
<br />
</div>
Ashwanihttp://www.blogger.com/profile/06875451536444254875noreply@blogger.com0