tag:blogger.com,1999:blog-14748894689599663162024-03-14T02:19:05.586+05:30Tech DroidTips for Android Developers and my experiences with AndroidAnonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.comBlogger65125tag:blogger.com,1999:blog-1474889468959966316.post-26677097392774474152019-08-03T08:29:00.001+05:302019-08-03T08:29:43.494+05:30Y he try hg<div style="text-align: center; padding: 5px;"><a href="http://res.cloudinary.com/dbvy9fjpa/image/upload/v1564801181/blogger/yeilzbmqgc2uvvurvhpz.jpg"><img src="http://res.cloudinary.com/dbvy9fjpa/image/upload/v1564801181/blogger/yeilzbmqgc2uvvurvhpz.jpg" cursor: pointer;" width="320px" style="border: 1px solid; border-radius: 2px;padding: 5px; max-width: 320px " /></a></div><div class="blogaway-section"><p>Vvjj</p></div><br/>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0Sector 51, Gurugram, India28.4304743 77.0706257tag:blogger.com,1999:blog-1474889468959966316.post-47266776903963831592019-08-03T01:08:00.001+05:302019-08-03T01:08:17.770+05:30Gnjh<div class="blogaway-section"><p>Hdhfuf</p></div><br/>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0Sector 51, Gurugram, India28.4304864 77.070629tag:blogger.com,1999:blog-1474889468959966316.post-46242198271729268332015-03-28T10:46:00.003+05:302015-03-28T11:23:02.581+05:30PIN Screen Library for Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="tr_bq">
Here's a simple and easy implementation for adding PIN lock support for your Android apps. The library can be themed with your app theme colors. It has smooth animations and vibrate cues when something's wrong.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-LE1QiJeEcOE/VRY3JRNpDHI/AAAAAAAAyXs/DZqP8gRUJ_Q/s1600/demo.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-LE1QiJeEcOE/VRY3JRNpDHI/AAAAAAAAyXs/DZqP8gRUJ_Q/s1600/demo.gif" height="320" width="186" /></a></div>
<br />
To use this, you just have to write about 10 lines of code, including layouts and everything. It's so simple.<br />
<br />
<b><span style="font-size: large;">Steps to implement</span></b><br />
<ul>
<li>Add as dependency</li>
</ul>
Maven:<br />
<blockquote class="tr_bq">
<b><span style="color: purple; font-size: x-small;"><dependency><br /> <groupId>com.kbeanie</groupId><br /> <artifactId>pinscreenlibrary</artifactId><br /> <version>1.0.0</version><br /></dependency></span></b></blockquote>
Android Studio:<br />
<blockquote class="tr_bq">
<b><span style="color: purple; font-size: x-small;">compile 'com.kbeanie:pinscreenlibrary:1.0.0@aar' </span></b></blockquote>
<ul style="text-align: left;">
<li>Add <b>PinView</b> to your layout file. </li>
</ul>
<blockquote class="tr_bq">
<b><span style="color: purple; font-size: x-small;"><com.kbeanie.pinscreenlibrary.views.PinView<br /> android:id="@+id/pinView"<br /> android:layout_width="match_parent"<br /> android:layout_height="wrap_content" /></span></b></blockquote>
<ul style="text-align: left;">
<li>Initialize <b>PinView</b> in two modes </li>
</ul>
<blockquote>
<b><span style="color: purple; font-size: x-small;">pinView.setModeSetup(PinEntrySetupListener);<br />pinView.setModeAuthenticate(PinEntryAuthenticationListener)</span></b></blockquote>
<br />
And finally, handle the callbacks for all events. The <a href="https://github.com/coomar2841/PINScreenLibrary" target="_blank">complete source code</a> for this project can be found on <a href="https://github.com/coomar2841/PINScreenLibrary" target="_blank">Github</a>. Let me know if you have any queries or issues. I would be happy to resolve them. </div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-43255419362434560122014-11-20T23:09:00.001+05:302014-11-21T09:37:57.306+05:30New Sensors in Android 5.0 (Lollipop)<div dir="ltr" style="text-align: left;" trbidi="on">
I found a few non-documented sensors on Lollipop (Android 5.0) on a Nexus 5.<br />
<div style="text-align: right;">
</div>
<br />
Tried looking for them, but could't find any documentation on them on. Looks like they are mostly software sensors.<br />
<br />
<a href="https://play.google.com/store/apps/details?id=com.beanie.shaker" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="Android app on Google Play" src="https://developer.android.com/images/brand/en_app_rgb_wo_60.png" /></a>Here's the list that I have found. I have written a simple app that displays all the sensors and shows there values. Not to mention that, only for the ones that are documented. For the ones not documented, you can only see it's details.<br />
<br />
There are only a few which appear on <a href="http://developer.android.com/about/versions/lollipop.html" target="_blank">developer.android.com</a>.<br />
Here's an excerpt from the announcement.<br />
<br />
<blockquote class="tr_bq" style="background-color: #f9f9f9; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; line-height: 19px; margin-bottom: 15px;">
New types of sensors<br />
<hr style="background: rgb(204, 204, 204); border: 0px; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; height: 1px; line-height: 19px; margin: 3px 0px 12px;" />
In Android 5.0, a new <strong>tilt detector</strong> sensor helps improve activity recognition on supported devices, and a <strong>heart rate sensor </strong>reports the heart rate of the person touching the device.<br />
New <strong>interaction composite sensors</strong> are now available to detect special interactions such as a <em>wake up</em> gesture, a <em>pick up</em>gesture, and a <em>glance</em> gesture.</blockquote>
<br />
Since there's no documentation, for some of them, I don't really know what they do. The only thing that gives you a clue is the sensor name. And, I don't know how to work with them as well.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK-myrtWfj_XG9fHvMWSAgctAQFAssOFd9v52I2DXCHKCBRYCYr-cctTBN1wbfgCBReFtnlTyTLshTCOhIkU1ixcDY1PFjy8zw8AJnlZtHwAD0DMkGIzSzlWNEiqs4rTF8kii4TaYz7JX3/s1600/Screenshot_2014-11-20-22-45-37.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK-myrtWfj_XG9fHvMWSAgctAQFAssOFd9v52I2DXCHKCBRYCYr-cctTBN1wbfgCBReFtnlTyTLshTCOhIkU1ixcDY1PFjy8zw8AJnlZtHwAD0DMkGIzSzlWNEiqs4rTF8kii4TaYz7JX3/s1600/Screenshot_2014-11-20-22-45-37.png" height="182" width="320" /></a></div>
<br />
<div style="text-align: center;">
Tilt Detector</div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlOQ0mTyPqcCnby9GRdONjZoY2B8HGwqTspnvjvY_e46aG94Oh3yV6WAxenQJo4jC5ED3AX_L51mWnl4N6NzNGTY3nujzrKrmBOXjK6VQLkoscsWJZI2J4i6JGlydV13ZOICeLI6COueK6/s1600/Screenshot_2014-11-20-22-46-39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlOQ0mTyPqcCnby9GRdONjZoY2B8HGwqTspnvjvY_e46aG94Oh3yV6WAxenQJo4jC5ED3AX_L51mWnl4N6NzNGTY3nujzrKrmBOXjK6VQLkoscsWJZI2J4i6JGlydV13ZOICeLI6COueK6/s1600/Screenshot_2014-11-20-22-46-39.png" height="171" width="320" /></a></div>
<br />
<div style="text-align: center;">
AMD Sensor (No idea, whats that)</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFNJLNuLEVF8bysjUV21L8tV5w9aZuy3N5NhdzZ9_P_hcEHAZn4L-Iq3kbHFa6mYL46uTdB785cWsyfchRRaHKZqQpYWFA-XPt__OATbAILFclF-dS54yHZYUAmH49w1j7jhomfOfba8S1/s1600/Screenshot_2014-11-20-22-46-47.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFNJLNuLEVF8bysjUV21L8tV5w9aZuy3N5NhdzZ9_P_hcEHAZn4L-Iq3kbHFa6mYL46uTdB785cWsyfchRRaHKZqQpYWFA-XPt__OATbAILFclF-dS54yHZYUAmH49w1j7jhomfOfba8S1/s1600/Screenshot_2014-11-20-22-46-47.png" height="177" width="320" /></a></div>
<br />
<div style="text-align: center;">
RMD Sensor (No idea, whats that)</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEXmmYOL417RH_wjqzpXn_02HD8um0FY2E4klkVLFnMjyU1eJtALqUplhj9R9hxdX0OI-VjCygBE_EilX-vKrYh6_Gtdxg1WyOoqclIZSv2Fy7TAGTVg16wWNnA-O5PYjEBR1pAjl2o_1k/s1600/Screenshot_2014-11-20-22-47-02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEXmmYOL417RH_wjqzpXn_02HD8um0FY2E4klkVLFnMjyU1eJtALqUplhj9R9hxdX0OI-VjCygBE_EilX-vKrYh6_Gtdxg1WyOoqclIZSv2Fy7TAGTVg16wWNnA-O5PYjEBR1pAjl2o_1k/s1600/Screenshot_2014-11-20-22-47-02.png" height="173" width="320" /></a></div>
<br />
<div style="text-align: center;">
Basic Gestures Sensor</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPI88pwZIfZobWPB89pHeZBYNkvy8eKebggv6engG5TejuL52fRboIZxZq7RrH3v7SC3aGnA65j8psWbzRv1LPvL4MYGjJpQbTj7ydrsitmqeT3WppdBO5tLFDgzKZKFB4pbYdONAshFao/s1600/Screenshot_2014-11-20-22-47-22.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPI88pwZIfZobWPB89pHeZBYNkvy8eKebggv6engG5TejuL52fRboIZxZq7RrH3v7SC3aGnA65j8psWbzRv1LPvL4MYGjJpQbTj7ydrsitmqeT3WppdBO5tLFDgzKZKFB4pbYdONAshFao/s1600/Screenshot_2014-11-20-22-47-22.png" height="168" width="320" /></a></div>
<br />
<div style="text-align: center;">
Tap Sensor</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBny8QE1vE_WkJcmTGfR-bdxXI4qn7N5SDvoBJIQVnC6E7cGp6nJ84sP4pUh7xIhyzU0O5YJh7_iCHkmg10z6RdZ2QYSC65M-ywVu1Ccc6lp51KwMBkXl64bccmohvUPWcVkth2-6MI2AI/s1600/Screenshot_2014-11-20-22-47-32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBny8QE1vE_WkJcmTGfR-bdxXI4qn7N5SDvoBJIQVnC6E7cGp6nJ84sP4pUh7xIhyzU0O5YJh7_iCHkmg10z6RdZ2QYSC65M-ywVu1Ccc6lp51KwMBkXl64bccmohvUPWcVkth2-6MI2AI/s1600/Screenshot_2014-11-20-22-47-32.png" height="178" width="320" /></a></div>
<br />
<div style="text-align: center;">
Facing Sensor</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdgNqOKeOPeZ5-8tbiEPjbwbhTnNs5u53HsL_X-SZiXwrmnYAJ2TCr8pFrrGRLzcTHGYDSXZPvDCHkFwQmyRU2A8DTUL7RozmupsmxJ0SZwzP7BW0i6BDT1eYkbWM0dJjq5c_1omedAyHw/s1600/Screenshot_2014-11-20-22-47-39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdgNqOKeOPeZ5-8tbiEPjbwbhTnNs5u53HsL_X-SZiXwrmnYAJ2TCr8pFrrGRLzcTHGYDSXZPvDCHkFwQmyRU2A8DTUL7RozmupsmxJ0SZwzP7BW0i6BDT1eYkbWM0dJjq5c_1omedAyHw/s1600/Screenshot_2014-11-20-22-47-39.png" height="175" width="320" /></a></div>
<br />
<div style="text-align: center;">
Tilt Sensor</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkRCBpLjyUfGG27qNC1xJnJfcrlU2EPuo-nj4hFoH5iTZ5MVfI8JOinx-dwLzMXa64WjHAtcl0eP5YTxWCrKO3IvLAnJvq8md6IZwwXCkxNP18CgcPSDcH8OZuRiTKoODTeMi7iydhHf5J/s1600/Screenshot_2014-11-20-22-47-53.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkRCBpLjyUfGG27qNC1xJnJfcrlU2EPuo-nj4hFoH5iTZ5MVfI8JOinx-dwLzMXa64WjHAtcl0eP5YTxWCrKO3IvLAnJvq8md6IZwwXCkxNP18CgcPSDcH8OZuRiTKoODTeMi7iydhHf5J/s1600/Screenshot_2014-11-20-22-47-53.png" height="168" width="320" /></a></div>
<br />
<div style="text-align: center;">
Pedometer</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJBEq6ajUUR05Kyejyc6YQ6yVNW7lLYqFX_GWWjVXn15JUvPEDM46nfRaMDUpCmkm3g4npP8vjKxzGXbGKBC_Ya48Tb68bPM7kwSRI_Y3A1IQIEmIQycL994fle-QH9IS44W9qcvpmpLAf/s1600/Screenshot_2014-11-20-22-48-12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJBEq6ajUUR05Kyejyc6YQ6yVNW7lLYqFX_GWWjVXn15JUvPEDM46nfRaMDUpCmkm3g4npP8vjKxzGXbGKBC_Ya48Tb68bPM7kwSRI_Y3A1IQIEmIQycL994fle-QH9IS44W9qcvpmpLAf/s1600/Screenshot_2014-11-20-22-48-12.png" height="178" width="320" /></a></div>
<br />
<div style="text-align: center;">
Pedestrian Activity Monitor</div>
<br />
<b>Update: </b>Seems, the documentation is coming soon. <a href="http://www.xda-developers.com/android/updated-android-lollipop-documentation-for-android-lollipop/" rel="nofollow" target="_blank">XDA picked this up</a>.<br />
<br />
<div style="text-align: right;">
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-83377007931018285222014-06-20T23:29:00.000+05:302014-06-20T23:29:02.523+05:30Easy Swipe to Refresh in Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiemh52onJJt95uWwNEzWaxUo6BjVCmjcxD5vabWUNdoSZPd3IdMC1axwHfwomgA9RvkXhdPr5So7ug0hffjHNTri8D60eMOE_SSQcRVF6WqlglZ8vlXQiWOY99BQeyyT87YJI5QsFUyxJd/s1600/bloggif_53a4724ce1df5.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="Swipe to Refresh Android" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiemh52onJJt95uWwNEzWaxUo6BjVCmjcxD5vabWUNdoSZPd3IdMC1axwHfwomgA9RvkXhdPr5So7ug0hffjHNTri8D60eMOE_SSQcRVF6WqlglZ8vlXQiWOY99BQeyyT87YJI5QsFUyxJd/s1600/bloggif_53a4724ce1df5.gif" height="320" title="Swipe to Refresh Android" width="180" /></a></div>
Recently, Google released a new version of the Support Library, which has an interesting component. It's called <a href="http://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html" target="_blank">SwipeRefreshLayout</a>. With that, it's become a child's play to implement a quick Swipe-to-Refresh control for your apps.<br />
<br />
<b>A few things first</b><br />
<br />
<ol style="text-align: left;">
<li>Available only with <b>android-support-v13. </b>Which means that only apps target SDK level 13 and above can use this.</li>
<li>It can only contain one scrollable direct child such as a <b>ListView</b> or a <b>ScrollView</b>.</li>
</ol>
<div>
That's all you need to know. Well.. A few things more, basically some xml and java code.</div>
<div>
<br /></div>
<div>
For this example, we use a <b>ListView </b>with some demo data. Once the list view is scrolled, we do some task, wait for sometime, and update the list view's adapter. Finally, ask the SwipeRefreshLayout to stop the progress indicator, since we are done with refreshing.</div>
<div>
<br /></div>
<div>
<b>The layout file</b></div>
<div>
<blockquote class="tr_bq">
<span style="color: #990000; font-size: x-small;"><b><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"<br /> xmlns:tools="http://schemas.android.com/tools"<br /> android:layout_width="match_parent"<br /> android:layout_height="match_parent"<br /> tools:context="${packageName}.${activityClass}" ><br /> <android.support.v4.widget.SwipeRefreshLayout<br /> android:id="@+id/swipeLayout"<br /> android:layout_width="match_parent"<br /> android:layout_height="match_parent" ><br /> <ListView<br /> android:id="@+id/listView"<br /> android:layout_width="match_parent"<br /> android:layout_height="match_parent" ><br /> </ListView><br /> </android.support.v4.widget.SwipeRefreshLayout><br /></RelativeLayout></b></span></blockquote>
</div>
<div>
<b>The UI initialization</b></div>
<div>
<blockquote class="tr_bq">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #990000; font-size: x-small;"><b>private void initializeViews() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>refreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeLayout);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>refreshLayout.setOnRefreshListener(this);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span> // The default colors for the progress bar are not so nice.<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>setColorSchemeForProgressBar();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ListView listView = (ListView) findViewById(R.id.listView);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>adapter = new ArrayAdapter<String>(this,<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>android.R.layout.simple_list_item_1);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>adapter.addAll(getDemoData(5));<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>listView.setAdapter(adapter);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span> }</b></span></blockquote>
<b>The Refresh Task</b><br />
<blockquote>
<span style="color: #990000; font-size: x-small;"><b> @Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void onRefresh() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>Log.i(TAG, "Refresh Requested");<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>doRefresh();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// Fetch data and update listview's adapter<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>private void doRefresh() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>RefreshTask task = new RefreshTask();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>task.execute((Void) null);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>} </b></span></blockquote>
<b>The Completion Work</b><br />
<blockquote class="tr_bq">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #990000; font-size: x-small;"><b>private void postRefreshComplete() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// Stop the refresh animation<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>refreshLayout.setRefreshing(false);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// Update adapter with new data<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>adapter.clear();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>adapter.addAll(getDemoData(new Random().nextInt(20)));<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>adapter.notifyDataSetChanged();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span> }</b></span></blockquote>
<br />
And there you go, a simple swipe to refresh usage for your Android apps. You can find the whole <a href="https://github.com/coomar2841/swipe-to-refresh-android" target="_blank">source code here</a>. </div>
</div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-83923601716680310162014-03-31T09:26:00.000+05:302014-03-31T09:28:54.231+05:30Step Detector and Step Counter Sensors on Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="tr_bq">
Android KitKat has added a few more hardware sensors to it's API list. Step Sensors are one of them, which looks very promising. Although, not a lot of phones yet have these Step Sensors, in the future, this would gradually become a standard I think. Currently, Nexus 5 has them.</div>
<br />
Let's see how we can interact with these sensors. Basically, there are 2 sensors.<br />
<ol style="text-align: left;">
<li><b>Step Counter: </b>This keeps a count of the number of steps that you have taken. The counter is only reset when you re-boot the device, else, for every step you take (or the phone thinks you took, you counts up).</li>
<li><b>Step Detector:</b> This sensor just detects when you take a step. That's it. </li>
</ol>
<div>
The example project shows you how to initialize and setup the <b>SensorManager </b>and respond to events from the Sensors.</div>
<blockquote>
<b><i><span style="color: #134f5c;"><span class="Apple-tab-span" style="white-space: pre;"> </span>// Step Counter<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sManager.registerListener(new SensorEventListener() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void onSensorChanged(SensorEvent event) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>float steps = event.values[0];<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>textViewStepCounter.setText((int) steps + "");<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void onAccuracyChanged(Sensor sensor, int accuracy) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}, sManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>SensorManager.SENSOR_DELAY_UI);</span></i></b></blockquote>
<br />
<blockquote>
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #134f5c;"><b><i>// Step Detector<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>sManager.registerListener(new SensorEventListener() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void onSensorChanged(SensorEvent event) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// Time is in nanoseconds, convert to millis<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>timestamp = event.timestamp / 1000000;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void onAccuracyChanged(Sensor sensor, int accuracy) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}, sManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR),<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>SensorManager.SENSOR_DELAY_UI); </i></b></span></blockquote>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo81NF8hGn8iWj5lCpM0HMBncA0qzZJJ_dj2AB1V-HgdLPEvpSZtOFvsyfY1ePBZk3mozwjg6Df99atcvtQpz9cSCXtv1AvUr14KO3jkwm7azyXi9OLlYJaI0A-9ideZCrGJWS9gcbO4X4/s1600/device-2014-03-31-091634.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo81NF8hGn8iWj5lCpM0HMBncA0qzZJJ_dj2AB1V-HgdLPEvpSZtOFvsyfY1ePBZk3mozwjg6Df99atcvtQpz9cSCXtv1AvUr14KO3jkwm7azyXi9OLlYJaI0A-9ideZCrGJWS9gcbO4X4/s1600/device-2014-03-31-091634.png" height="320" width="180" /></a></div>
No special permissions are required.<br />
<br />
Head over to <a href="https://github.com/coomar2841/android-step-sensors" target="_blank">Github to get the full source code</a>.<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-14009009744705097182013-12-07T21:34:00.000+05:302013-12-07T21:37:37.093+05:30Smartphone Usage Statistics Highlight Its Importance In Our Lives<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: center;">
<p>
<img style="max-width: 80%;" src="http://www.couponaudit.com/blog/wp-content/uploads/2013/12/Smartphone-Usage-Statistics-Highlight-Its-Importance-In-Our-Lives1.jpg" alt="Smartphone Usage Statistics Highlight Its Importance In Our Lives" />
</p>
</div>
<p></a></p>
<div style="text-align: center;">
<p>This Infographic is produced by <a href="http://www.couponaudit.com/coupons/finishline">Coupon Audit (provides Finish Line promo code) </a> and <a href="http://techdroid.kbeanie.com">Techdroid.Kbeanie</a> </p>
<p>
If you would like to add this inforgraphic on your website or blog, copy and paste the below code as given in the textbox.
</p>
<textarea cols="50" rows="5">
<img style="max-width: 80%;" src="http://www.couponaudit.com/blog/wp-content/uploads/2013/12/Smartphone-Usage-Statistics-Highlight-Its-Importance-In-Our-Lives1.jpg" alt="Smartphone Usage Statistics Highlight Its Importance In Our Lives" /></p>
<p></a></p>
<p> This Infographic is produced by <a href="http://www.couponaudit.com/coupons/finishline">Coupon Audit (provides Finish Line promo code) </a> and <a href="http://techdroid.kbeanie.com">TECHDROID.KBEANIE.COM</a> </p>.<br />
</textarea>
</div>
</div>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-91190879133915316332013-09-27T10:34:00.001+05:302013-09-27T10:34:28.579+05:30Making your Android apps crash-proof<div dir="ltr" style="text-align: left;" trbidi="on">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7BoLwlE5zjGdG8ZgGcy1VdNU5QVpmgB7QzKYaX53WYqQuLhs3CTahmiW4Cc73INJxWqFcXF-HB0FDDwpI5R_sVyeogj6DIGTa6iU7C4zGHlJFiDq-navWHO2yiB-LUeXQ-2qWXQQKeBSA/s1600/cost-of-failure-whitepaper.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7BoLwlE5zjGdG8ZgGcy1VdNU5QVpmgB7QzKYaX53WYqQuLhs3CTahmiW4Cc73INJxWqFcXF-HB0FDDwpI5R_sVyeogj6DIGTa6iU7C4zGHlJFiDq-navWHO2yiB-LUeXQ-2qWXQQKeBSA/s320/cost-of-failure-whitepaper.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Image courtesy: <a href="https://www.crittercism.com/">Crittercism Website</a></td></tr>
</tbody></table>
<b><span style="font-size: x-large;">D</span>o you have an android app on the Play Store, and get lots of negative comments/feedback?</b><br />
<br />
<br />
Most of the time, apps crash on the first interaction with the user. And that's the reason most users are frustrated of even downloading your app, and that's when most of the negative comments start pouring in.<br />
<br />
Of course, you have to look for crashes everywhere in your app, but crashing on the first page itself, is a really really bad situation. When that happens, and the user leaves a bad comment, instead of sending you a support mail, you have no idea how to fix it. You have no idea about the user's device, and other important information that would help you in determining the problem, and fixing it. And if you continue having such a build even for a week on the store, that puts a dent on your overall app reviews. People generally look at the first few reviews, and make a decision based on that, whether to try your app or not.<br />
<br />
I have had an app on the store for years now, which I didn't update for a long time. And finally, when I got the time to work on it again, I decided to integrate <a href="https://www.crittercism.com/">Crittercism SDK</a> within my app, along with <a href="https://developers.google.com/analytics/devguides/collection/android/v2/">Google Analytics SDK</a>.<br />
<br />
The very first update with <a class="g-profile" href="http://plus.google.com/101428951672351564441" target="_blank">+Crittercism</a> along with <a class="g-profile" href="http://plus.google.com/111224383669619377607" target="_blank">+Google Analytics</a> , my inbox was flooded with crash reports. I was amazed at how many un-reported crashes my app had. I was living in the dark, as to what all problems users were having with my app. <b>Crittercism</b> logs had more information about the crashes than I could have asked for. They were pretty detailed, in terms of the user's device name, and OS versions, the version of the application, and a device snapshot (Memory/Storage) when the crash occurred.<br />
<br />
After about a week, I made the next update, and this time, the crash notifications reduced dramatically, although the number of users and the average usage of my app went up. From this, I can guess that the users who are still using my app are a happy lot. And that makes me happy as well.<br />
<br />
I would strongly recommend integrating such a live error reporting tool into your apps to get live feedback for your apps. Specifically for <b>Crittercism</b>, there are free and paid plans. Currently, I am on the free plan, and it gives me the almost everything that I need to know to fix those random crashes. With paid plans, you have more reporting, which I think I don't need right away. Receiving crash notifications is just the one part of <b>Crittercism</b>. They call this solution as a <b>"Mobile Application Performance Management"</b> solution. Rightly so?<br />
<br />
Have you used <b>Crittercism </b>in your apps? Do you have anything to say?</div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-25461475221653732552013-04-09T22:22:00.000+05:302013-04-09T22:34:36.161+05:30Easy Video Chooser Library for Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjQMOyEjOUj0EId39OUWJsdK4lZNDnPpPxnYhYRkd3ul_MBgz4SFMLsFwphX4aU2rwOhzYWVTSokrpmqHVYtRyQ80RSdAZRbn5zqzIhOb7ThkIht4G8IWPARMXVkStn6MbkBLEppYqlKpe/s1600/Screenshot_2013-04-09-22-17-22.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjQMOyEjOUj0EId39OUWJsdK4lZNDnPpPxnYhYRkd3ul_MBgz4SFMLsFwphX4aU2rwOhzYWVTSokrpmqHVYtRyQ80RSdAZRbn5zqzIhOb7ThkIht4G8IWPARMXVkStn6MbkBLEppYqlKpe/s320/Screenshot_2013-04-09-22-17-22.png" width="180" /></a></div>
After I wrote the "<a href="http://techdroid.kbeanie.com/2013/03/easy-image-chooser-library-for-android.html">Easy Image Chooser library for Android</a>", I thought I could easily extend this library to handle other things as well. For now, I have implemented the option of choosing/recording a video. And in the future, I am planning to extend this library for choosing other types of files.<br />
<br />
Choosing videos, is again very similar to how the images are handled. Using this library, you would be also able to choose videos that reside in your Picasa albums on your phone. And this should work for all OSes and devices.<br />
<br />
After processing, the library would return a <a href="https://github.com/coomar2841/image-chooser-library/blob/master/src/com/beanie/imagechooser/api/ChosenVideo.java">ChosenVideo </a>object, which would contain the original path to the video file, and 2 differently-sized thumbnails which you can directly use as a preview.<br />
<br />
Here is how to use this library.<br />
<br />
<ul style="text-align: left;">
<li>For capturing a video using the camera</li>
</ul>
<blockquote class="tr_bq">
<span style="color: #990000; font-size: x-small;"><b>videoChooserManager = new VideoChooserManager(this, ChooserType.REQUEST_CAPTURE_VIDEO);<br />videoChooserManager.setVideoChooserListener(this);<br />videoChooserManager.choose();</b></span></blockquote>
<ul style="text-align: left;">
<li> For choosing a video from the gallery</li>
</ul>
<div style="text-align: left;">
<blockquote class="tr_bq">
<span style="color: #990000; font-size: x-small;"><b>videoChooserManager = new VideoChooserManager(this, ChooserType.REQUEST_PICK_VIDEO);<br />videoChooserManager.setVideoChooserListener(this);<br />videoChooserManager.choose();</b></span></blockquote>
<ul style="text-align: left;">
<li>On Activity Result, write this</li>
</ul>
<blockquote class="tr_bq">
<b><span style="color: #990000; font-size: x-small;">@Override<br />protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (resultCode == RESULT_OK &&<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>(requestCode == ChooserType.REQUEST_PICK_VIDEO ||<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>requestCode == ChooserType.REQUEST_CAPTURE_VIDEO)) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>videoChooserManager.submit(requestCode, data);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />} </span></b></blockquote>
<div style="text-align: left;">
</div>
<ul style="text-align: left;">
<li> Implement this method from the <a href="https://github.com/coomar2841/image-chooser-library/blob/master/src/com/beanie/imagechooser/api/VideoChooserListener.java">VideoChooserListener</a></li>
</ul>
<blockquote class="tr_bq">
<b><span style="color: #990000; font-size: x-small;">@Override<br />public void onVideoChosen(final ChosenVideo video) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>runOnUiThread(new Runnable() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void run() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (video != null) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// Use the video<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// video.getFilePathOriginal();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// video.getFileThumbnail();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// video.getFileThumbnailSmall();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>});<br />}</span></b></blockquote>
<ul style="text-align: left;">
<li>Handling error conditions from the <a href="https://github.com/coomar2841/image-chooser-library/blob/master/src/com/beanie/imagechooser/api/VideoChooserListener.java">VideoChooserListener</a> interface.</li>
</ul>
<blockquote class="tr_bq">
<b><span style="color: #990000; font-size: x-small;">@Override<br />public void onError(final String reason) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>runOnUiThread(new Runnable() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void run() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// Show error message<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>});<br />}</span></b></blockquote>
Here's the link to the <a href="https://github.com/coomar2841/image-chooser-library">Github project</a>. Do let me know your thoughts and feedbacks, and also any bugs if you come across. I will try to fix them as soon as possible.</div>
</div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-21140873629165597672013-03-30T23:49:00.002+05:302013-04-09T22:38:32.818+05:30Easy Image Chooser Library for Android<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrgC2lz1fTKxbn00QuaF38WgQUWz8H3x6N9Mpi9d_gJ73jFpDGC8GQFYFQeT7Fdpu1h2SEUq7mxHou3vQ_OCpa3BTJxgHS1-sNwKcFhFs0mCgOxUgvuPPIAvx3H6zp36vcK2SrYOlgx2_3/s1600/Image+Chooser+App.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrgC2lz1fTKxbn00QuaF38WgQUWz8H3x6N9Mpi9d_gJ73jFpDGC8GQFYFQeT7Fdpu1h2SEUq7mxHou3vQ_OCpa3BTJxgHS1-sNwKcFhFs0mCgOxUgvuPPIAvx3H6zp36vcK2SrYOlgx2_3/s320/Image+Chooser+App.png" width="180" /></a></div>
<b><span style="font-size: x-large;">I</span></b>n almost all the Android apps that I have worked on, there has been a requirement for choosing an image or taking a snap and using the device's camera.<br />
<br />
Taking a snap, is rather straightforward to implement, but choosing an image from your gallery is sometimes a hard nut to crack. And to implement this correctly, you would always end up writing a lot of code. Assuming that you want to target all OSes, devices, folders etc.<br />
<br />
For example, choosing a picture from the Camera folder of your phone is nice and easy. But, if you want to have the user chose an image from one of his picasa web albums, which he has synced on his phone, you will find a dead-end. Well, almost.<br />
<br />
For myself, I must have at-least rewritten the same code, multiple number of times. Of course, the platform should help us in achieving this seemingly straightforward feature with as less code as possible. But, right now, it's not possible.<br />
<br />
So, I thought of creating a library which anyone could integrate within one's own app, without really worrying about the nitty-gritties and the bugs, to implement or add this feature into his app. And there's more. Most of the time, you would need a scaled down version of the chosen image to show a preview or use it in a listview. This library would give you 3 sizes, as of now.<br />
<ol style="text-align: left;">
<li>Original Size</li>
<li>Thumbnail Size</li>
<li>Thumbnail Smaller Size</li>
</ol>
<div>
The sizes are dynamically calculated, based on the original size of the image. It's pretty rough here, but I am looking forward to improve that part.</div>
<div>
<br /></div>
<div>
This version of the library is pretty basic. But, I would be working on improving this library to add more functionality in the future.</div>
<div>
<br /></div>
<div>
You can find more information about this library here.</div>
<div>
<a href="https://github.com/coomar2841/image-chooser-library">image-chooser-library (Github Page)</a></div>
<div>
<br /></div>
<div>
By using this library in the current state, you could handle all these cases/special cases with just a few lines of code. An example of this is shown below.</div>
<div>
<br /></div>
<div>
<div>
<b>Usage:</b></div>
<div>
<br /></div>
<div>
<b><i>1. For choosing an image from gallery</i></b></div>
<blockquote class="tr_bq">
<span style="color: #990000; font-size: x-small;"><b>imageChooserManager = new ImageChooserManager(this, ChooserType.REQUEST_PICK_PICTURE);<br />imageChooserManager.setImageChooserListener(this);<br />imageChooserManager.choose();</b></span></blockquote>
<div>
<b><i>2. For capturing a picture using your camera</i></b></div>
<blockquote class="tr_bq">
<span style="color: #990000; font-size: x-small;"><b>imageChooserManager = new ImageChooserManager(this, ChooserType.REQUEST_CAPTURE_PICTURE);<br />imageChooserManager.setImageChooserListener(this);<br />imageChooserManager.choose();</b></span></blockquote>
<div>
<br /></div>
<div>
<b><i>3. On Activity result, do this:</i></b></div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="color: #990000;"><b>@Override<br />protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (resultCode == RESULT_OK &&<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>(requestCode == ChooserType.</b></span><b style="color: #990000;">REQUEST_PICK_PICTURE</b><span style="color: #990000;"><b>||<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>requestCode == ChooserType.</b></span><b style="color: #990000;">REQUEST_CAPTURE_PICTURE</b><span style="color: #990000;"><b>)) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>imageChooserManager.submit(requestCode, data);<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />}</b></span></span></blockquote>
<div>
<b><i>4. Implement the ImageChooserListener interface and override these methods:</i></b></div>
<blockquote>
<span style="color: #990000; font-size: x-small;"><b>@Override<br />public void onImageChosen(final ChosenImage image) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>runOnUiThread(new Runnable() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void run() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>if (image != null) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// Use the image<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// image.getFilePathOriginal();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// image.getFileThumbnail();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// image.getFileThumbnailSmall();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>});<br />}<br />@Override<br />public void onError(final String reason) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>runOnUiThread(new Runnable() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>public void run() {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>// Show error message<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>});<br />}</b></span></blockquote>
That's all you need to code. And the library takes care of handling all kinds of images, and also generates 2 thumbnails which you could directly use. Let me know if you need to add any new features or if you find a bug. I will try to address those as soon as humanly possible. If you would like to contribute to this project, drop me a mail.</div>
</div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com2tag:blogger.com,1999:blog-1474889468959966316.post-63358475047720586252013-02-24T00:26:00.002+05:302013-02-24T00:26:51.841+05:30Google Maps API v2 on Android<div dir="ltr" style="text-align: left;" trbidi="on">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBZtAAteatJLP1Ut7uDXR5hPs3o1rLIHtPwgWXwLRI4buSSH5bwFURdd02T_b54z70jFlvPwc_52hrnhScMsxyQ4QXM551RfsHpogEXUxK-ilMDYsULGm6FCXWfA4L2XVOCtKraDuN5nPI/s1600/Maps101_3.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="2" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBZtAAteatJLP1Ut7uDXR5hPs3o1rLIHtPwgWXwLRI4buSSH5bwFURdd02T_b54z70jFlvPwc_52hrnhScMsxyQ4QXM551RfsHpogEXUxK-ilMDYsULGm6FCXWfA4L2XVOCtKraDuN5nPI/s320/Maps101_3.png" width="180" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The Splash Screen</td></tr>
</tbody></table>
I don't even remember when was the last time I did something with MapView on Android. I was aware of the new version 2 of the Google Maps API, but never got a chance to work on it until today.<br />
<br />
There were initial hitches to setup the project. But, once the first steps were done, it was quite easy to build up a simple app.<br />
<br />
I want to list down the first steps of the process, and then move on to the sample application.<br />
<br />
<b>Step 1: Getting the API key.</b><br />
<br />
<ol style="text-align: left;">
<li>Go to <a href="https://code.google.com/apis/console">Google API Console</a></li>
<li>Go to Services link, and enable <b>Google Maps Android API v2</b>. <i><span style="color: #cc0000;">(Don't confuse this with Google Maps API v2. I got confused, and was wondering what was I doing wrong when the maps failed to load)</span></i></li>
<li>After enabling the service, go to the <b>API Access</b> link.</li>
<li>In the Simple API access section, click on <b>"Create New Android Key"</b>.</li>
<li>Enter your keystore's SHA1 fingerprint along with your application's package name separated by a semi-colon in the dialog and click on "Save".</li>
<li>Your API should be visible now on the same page.</li>
</ol>
<div>
<b>Step 2: Setting up the project.</b></div>
<div>
<ol style="text-align: left;">
<li>You need to find the library project for the Google Maps API v2. It should be available in your SDK directory. If not, open up the Android SDK manager and download the same by selecting <b>Google Play Services</b> in the <b>Extras</b> section.</li>
<li>You would find the required library project in the following location of the SDK folder. <b>(..\android-sdks\extras\google\google_play_services\libproject)</b></li>
<li>My suggestion would be to make a copy of this project somewhere else, and then import the project into eclipse.</li>
<li>Once imported into Eclipse, use this as a library project for your application.</li>
</ol>
<div>
<b>Step 3: Setting up the manifest file.</b></div>
</div>
<div>
<ol style="text-align: left;">
<li>Your manifest file should look like this. <a href="https://github.com/coomar2841/android-map101-v2/blob/master/AndroidManifest.xml">AndroidManifest.xml</a></li>
<li>You can change the package names for the permissions to use your own package name.</li>
<li>Now, replace your API key with the place-holder API Key in the manifest.</li>
</ol>
<div>
<b>Step 4: MapFragment and more code...</b></div>
</div>
<div>
<ol style="text-align: left;">
<li>To show a map, I used the MapFragment in the <a href="https://github.com/coomar2841/android-map101-v2/blob/master/res/layout/activity_location.xml">activity's layout</a>.</li>
</ol>
<div>
That's it. These are the broad steps to configure the new version of Google Maps for your Android application.</div>
</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz46WDoBGZoz-2LSSXLqB14-xX_nIABY7WB5-7SoIeBDE4wrRST3e0b8qei4AJPLC7eW5oB4SxhOaUe2YCumyq-I_A_0w9tqnoS-mlsiHr1pzDu8dxIhOiX1E7fnwpA7MbGW6_fnWyZ8Vj/s1600/Maps101_1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="2" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz46WDoBGZoz-2LSSXLqB14-xX_nIABY7WB5-7SoIeBDE4wrRST3e0b8qei4AJPLC7eW5oB4SxhOaUe2YCumyq-I_A_0w9tqnoS-mlsiHr1pzDu8dxIhOiX1E7fnwpA7MbGW6_fnWyZ8Vj/s320/Maps101_1.png" width="180" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Your Places</td></tr>
</tbody></table>
<table 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/AVvXsEhRuGUtUBAhsOnZK3lCxafJKoU2RfE5RR5FMmK8PqEMdFGycA9hPq0zbtSL4m1TMQOqcFLS1RLxVYWLGWT0f6am3mHmPQrVYVA_gRrjRVE5TjIh5Z2INXESye7sH3IFtW2F6SkWWk_4Uvq9/s1600/Maps101_2.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="2" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRuGUtUBAhsOnZK3lCxafJKoU2RfE5RR5FMmK8PqEMdFGycA9hPq0zbtSL4m1TMQOqcFLS1RLxVYWLGWT0f6am3mHmPQrVYVA_gRrjRVE5TjIh5Z2INXESye7sH3IFtW2F6SkWWk_4Uvq9/s320/Maps101_2.png" width="179" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Add a new place</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<div>
<b>What this application does?</b></div>
<div>
<ol style="text-align: left;">
<li>On opening the application, you would see a splash screen, and it would try to get your current location.</li>
<li>Once it gets your location, it would switch to the map view, and display your current location with a marker.</li>
<li>Tapping on an unmarked area of the app, you would see a dialog, through which you can add a new place.</li>
<li>After saving the new place by providing a name and a description, this place would be saved into the database and you would be able to see the newly added place on the map.</li>
<li>Tapping on an already visible marker will show you the details of that place.</li>
<li>The next time you open the application, all the previously stored places would appear on the map along with your current location.</li>
</ol>
</div>
<div>
<b>Suggested optimizations</b></div>
<div>
<ol style="text-align: left;">
<li>While loading the points from the database, it would be nice if we can only load the places which are within the currently visible area of your app.</li>
<li>When the map is re-sized or moved, we could re-query the database for the fresh list of places and update the markers based on the new visible area.</li>
</ol>
</div>
<div>
<b>Problems:</b></div>
<div>
<ol style="text-align: left;">
<li>The VisibleRegion API, currently, doesn't work. Need to think of a workaround for this.</li>
</ol>
</div>
</div>
<b><i>You can find the full source-code here at the github respository</i></b>: <b><a href="https://github.com/coomar2841/android-map101-v2">android-map101-v2</a></b></div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com4tag:blogger.com,1999:blog-1474889468959966316.post-88173233984571826082012-11-15T17:00:00.002+05:302012-11-15T17:00:45.319+05:30Easier Bug Reporting on 4.2<div dir="ltr" style="text-align: left;" trbidi="on">
With the recent release of an updated Jelly Bean version, i.e, 4.2, there have been quite some new things to awe you.<br />
<br />
These are two things that could probably make a developers life easier.<br />
<br />
<br />
<ul style="background-color: #f9f9f9; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; line-height: 19px; margin: 0px 0px 15px 18px; padding: 0px;">
<li style="margin: 0px 0px 5px;"><strong>Take bug report</strong> — immediately takes a screen shot and dumps device state information to local file storage, then attaches them to a new outgoing email message.</li>
<li style="margin: 0px 0px 5px;"><strong>Power menu bug reports</strong> — Adds a new option to the device power menu and quick settings to take a bug report (see above).</li>
</ul>
<div>
<span style="color: #222222; font-family: Roboto, sans-serif;"><span style="font-size: 14px; line-height: 19px;">Remember, while you were testing your app on a bus, or you were away from your desktop/laptop and got a dreaded crash!! You, so eagerly want to have a look at the logcat, or even save the logcat output for later investigation. And most of the times, I don't have SendLog, which I could fire up, and send me the logs.</span></span></div>
<div>
<span style="color: #222222; font-family: Roboto, sans-serif;"><span style="font-size: 14px; line-height: 19px;"><br /></span></span></div>
<div>
<span style="color: #222222; font-family: Roboto, sans-serif;"><span style="font-size: 14px; line-height: 19px;">With 4.2, it's already built-in to your phone. Here are a few screenshots, that give you an idea.</span></span></div>
<div>
<span style="color: #222222; font-family: Roboto, sans-serif;"><span style="font-size: 14px; line-height: 19px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiFWkgq8FBXAWtVzUEWhd4jZdawpzqCtFCIhRbMeEiUdXERrE8ANuPSVqYiFZo3IsM8PsObJW3UkiqbRs539uC-cKRJjv8You8otnpoTRLTwy4d5noYqLZkqFeqP3cZsHEAHqsJGCI0c7u/s1600/Bug+Reporting+1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiFWkgq8FBXAWtVzUEWhd4jZdawpzqCtFCIhRbMeEiUdXERrE8ANuPSVqYiFZo3IsM8PsObJW3UkiqbRs539uC-cKRJjv8You8otnpoTRLTwy4d5noYqLZkqFeqP3cZsHEAHqsJGCI0c7u/s400/Bug+Reporting+1.png" width="225" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
Enable this option from the Settings Page.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfnr00bvSp89rYX47foSscQcwlIfsxzCeq2U_ZVQzNmb5v8AFw9qI76swLbMHSCFSOaelNJJbriGejSNphhwcnw6qr2NJOD7Te_QVQfpx2zyHVpTUG7m1aKKfohgeGKIYlipfySXmefghR/s1600/Bug+Reporting+2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfnr00bvSp89rYX47foSscQcwlIfsxzCeq2U_ZVQzNmb5v8AFw9qI76swLbMHSCFSOaelNJJbriGejSNphhwcnw6qr2NJOD7Te_QVQfpx2zyHVpTUG7m1aKKfohgeGKIYlipfySXmefghR/s400/Bug+Reporting+2.png" width="225" /></a></div>
<div>
<span style="color: #222222; font-family: Roboto, sans-serif;"><span style="font-size: 14px; line-height: 19px;"><br /></span></span></div>
<div style="text-align: center;">
<span style="color: #222222; font-family: Roboto, sans-serif;"><span style="font-size: 14px; line-height: 19px;">Hold the power button, to see the option to capture a "Bug Report"</span></span></div>
<div style="text-align: center;">
<span style="color: #222222; font-family: Roboto, sans-serif;"><span style="font-size: 14px; line-height: 19px;"><br /></span></span></div>
<div style="text-align: left;">
<span style="color: #222222; font-family: Roboto, sans-serif;"><span style="font-size: 14px; line-height: 19px;">Happy Coding...</span></span></div>
</div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-29171539831090744112012-08-23T11:46:00.000+05:302012-08-23T11:47:12.870+05:30Check orientation of images/captures<div dir="ltr" style="text-align: left;" trbidi="on">
A lot of times, you would need your app to either pick an image from the gallery or use the device's camera for capturing a picture that your app could use. I have seen a lot of apps, do it plain wrong. Especially, the orientation of the images.<br />
<br />
The default gallery app, reads the orientation properly, and displays the images/thumbnails properly. So, our apps can also handle images in various orientations properly. And the good news is, it's very easy to handle.<br />
<br />
There's a class called <a href="http://developer.android.com/reference/android/media/ExifInterface.html">ExifInterface</a>. Most of the times, when you have a similar situation, you would almost never want a full-scaled image to be shown in your app. Most often, we use a thumbnail view for the purpose. The following code would get you a re-sized bitmap, from your original file.<br />
<br />
Say for example, we have this path to the actual image file. <b>imagePath</b><br />
<b><br /></b>
<b>1. Create a Bitmap from the file</b><br />
<br />
<blockquote class="tr_bq">
<span style="color: #660000;"><b><i>Bitmap b = BitmapFactory.decodeFile(imagePath);</i></b></span></blockquote>
<div class="p1">
<br /></div>
<div class="p1">
<b>2. Resize the Bitmap by scaling it to appropriate level</b></div>
<div class="p1">
</div>
<blockquote class="tr_bq">
<b><i><span style="color: #660000;"><span class="s1">int</span> width = b.getWidth();<br /><span class="s1">int</span> height = b.getHeight();<br /><span class="s1">int</span> newWidth = 150;<br /><span class="s1">int</span> newHeight = 150;<br /><span class="s1">float</span> scaleWidth = ((<span class="s1">float</span>) newWidth) / width;<br /><span class="s1">float</span> scaleHeight = ((<span class="s1">float</span>) newHeight) / height;<br />Matrix matrix = <span class="s1">new</span> Matrix();<br />matrix.postScale(scaleWidth, scaleHeight);<br />// Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, width, height, matrix, <span class="s1">true</span>);<br />// resizedBitmap.compress(Bitmap.CompressFormat.<span class="s2">JPEG</span>, 70, out);</span></i></b></blockquote>
<div class="p1">
<br /></div>
<div class="p1">
<b>3. Handle orientation of the image</b></div>
<div class="p1">
</div>
<blockquote class="tr_bq">
<b><i><span style="color: #660000;">ExifInterface exif = <span class="s1">new</span> ExifInterface(imagePath);<br />String orientation = exif.getAttribute(ExifInterface.<span class="s2">TAG_ORIENTATION</span>);<br /><span class="s1">if</span> (orientation.equals(ExifInterface.<span class="s2">ORIENTATION_NORMAL</span>)) {<br /> // Do nothing. The original image is fine.<br />} <span class="s1">else</span> <span class="s1">if</span> (orientation.equals(ExifInterface.<span class="s2">ORIENTATION_ROTATE_90</span>+<span class="s3">""</span>)) {<br /> matrix.postRotate(90);<br />} <span class="s1">else</span> <span class="s1">if</span> (orientation.equals(ExifInterface.<span class="s2">ORIENTATION_ROTATE_180</span>+<span class="s3">""</span>)) {<br /> matrix.postRotate(180);<br />} <span class="s1">else</span> <span class="s1">if</span> (orientation.equals(ExifInterface.<span class="s2">ORIENTATION_ROTATE_270</span>+<span class="s3">""</span>)) {<br /> matrix.postRotate(270);<br />}</span></i></b></blockquote>
<div class="p1">
<br /></div>
<div class="p1">
<b>4. Save the new bitmap </b></div>
<div class="p1">
</div>
<blockquote class="tr_bq">
<b><i><span style="color: #660000;">out = <span class="s1">new</span> FileOutputStream(<span class="s1">new</span> File("some output file path"));<br />Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, width, height, matrix, <span class="s1">true</span>);<br />resizedBitmap.compress(Bitmap.CompressFormat.<span class="s2">JPEG</span>, 70, out);</span></i></b></blockquote>
Now your output file would be an image that is resized and handled properly for orientation of the images. You could directly use the "resized" bitmap, but I prefere files.<br />
<br />
<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com4tag:blogger.com,1999:blog-1474889468959966316.post-16189710261612373012012-08-09T16:48:00.002+05:302012-08-09T17:24:24.254+05:30Android Themes: A dialog without a title<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Most of the times, I have seen developers not leveraging the power of themes and styles. Themes and styles are a great way to easily create UI that are manageable and compatible for various platforms. Here's the <a href="http://developer.android.com/guide/topics/ui/themes.html">official documentation</a> that explains styles and themes in details, and I consider this portion of documentation to be equally important to any developer working with Android.<br />
<br />
For the example of this post, we will see how to make a dialog, a custom dialog, not to have a title. The easiest way to do this, is through code byt writing this snippet in your custom dialog class.<br />
<br />
<blockquote class="tr_bq">
<b><span style="color: #741b47; font-size: x-small;"><i>requestWindowFeature(Window.<span class="s1">FEATURE_NO_TITLE</span>);</i></span></b></blockquote>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfp-EOPBQX6-uZfBMlnFSUIiXCWDGArG9AgPMJyqEAVNPcJupeCfJBPqz9Ec9vZAJ_-N2fFekxNuxscLE-hQNdGt8-gYOx8x5CFejCdNTtaTJmrV1EbDw9s1pH8ctEOrPHqjsic3gV6zmB/s1600/GB+Dialog+with+Title.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfp-EOPBQX6-uZfBMlnFSUIiXCWDGArG9AgPMJyqEAVNPcJupeCfJBPqz9Ec9vZAJ_-N2fFekxNuxscLE-hQNdGt8-gYOx8x5CFejCdNTtaTJmrV1EbDw9s1pH8ctEOrPHqjsic3gV6zmB/s320/GB+Dialog+with+Title.png" width="213" /></a></div>
<br />
<div style="text-align: center;">
<b>Dialog with Title on Android 2.2</b></div>
<div style="text-align: center;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJDG4sxZcvh4bbtkAZm3U2a1haIFzS_naeH97obnFhiB3NkUS1fu0RhL3bhItfSqmGM9UtSFvWAY6AOVlyJxkgLeHGbwulPe4C9BSxTRja10U_CEHmsx8oazckokTlkINpgaAvdJnjWFDo/s1600/GB+Dialog+No+Title.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJDG4sxZcvh4bbtkAZm3U2a1haIFzS_naeH97obnFhiB3NkUS1fu0RhL3bhItfSqmGM9UtSFvWAY6AOVlyJxkgLeHGbwulPe4C9BSxTRja10U_CEHmsx8oazckokTlkINpgaAvdJnjWFDo/s320/GB+Dialog+No+Title.png" width="213" /></a></div>
<div style="text-align: center;">
<b><br /></b></div>
<div style="text-align: center;">
<b>Dialog with no title on Android 2.2</b></div>
<br />
While this would work anyway, and would also be compatible with all the versions of Android. But, it's a good idea to use more of your themes and styles in your programming, so that your code base is maintainable and your apps would behave and feel consistently. Using styles and themes makes it very easy to tweak or adapt to various platform versions and/or device sizes and resolutions. So, let's get in.<br />
<br />
The application tag, has a configurable attribute called <b>"android:theme"</b> with which you can set a theme to your application as a whole. You can also specify themes for individual themes for all your activities separately. Sounds nice!!! But, let's stick to one theme for our application as a whole for simplicity.<br />
<br />
For this example, we have a theme (it's actually called a style), called <i style="font-weight: bold;">MyThemeSelector </i>as shown below. This is specified in the <b>styles.xml</b> in your <b>values</b> folder. Notice, your custom theme is a child of the <b>Theme</b>, which is one of the system's default themes.<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="color: #741b47;"><b><i><span class="s1"><</span>resources<span class="s1">></span></i></b></span><span style="color: #741b47;"><b><i><span class="s2"> </span><span class="s1"><</span><span class="s3">style</span><span class="s2"> </span><span class="s4">name</span><span class="s2">=</span>"MyThemeSelector"<span class="s2"> </span><span class="s4">parent</span><span class="s2">=</span>"@android:style/Theme"<span class="s1">></</span><span class="s3">style</span><span class="s1">></span></i></b></span><span style="color: #741b47;"><b><i><span class="s1"></</span>resources<span class="s1">></span></i></b></span></span></blockquote>
<br />
Ideally, you should also declare your custom theme to extend one of the basic themes that are available with platforms on or above Honeycomb. For example, here we have created another <b>styles.xml</b> in a folder called <b>values-v11</b>, which looks like this.<br />
<br />
<blockquote class="tr_bq">
<i><span style="color: #741b47; font-size: x-small;"><b><resources><br /> <style name="MyThemeSelector" parent="@android:style/Theme.DeviceDefault.Light"></style><br /></resources></b></span></i></blockquote>
<br />
So, your basic theme is now compatible with both older versions and versions greater than Honeycomb. By this, I mean, that, when you run the app, your app would adapt to the platform that it is running on, and would give a consistent look and feel for your users.<br />
<br />
Now, coming back to the main problem. <i style="font-weight: bold;">"Creating a dialog without title"</i>. Here also, we would use themes, as against code. Here are the two new themes that you would be declaring.<br />
<br />
For <b>values</b> folder: (Platform versions older than Honeycomb)<br />
<br />
<blockquote class="tr_bq">
<b><i><span style="color: #741b47; font-size: x-small;"><style name="My.Theme.Dialog" parent="@android:style/Theme.Dialog"><br /> <item name="android:windowNoTitle">true</item><br /></style><br /><style name="MyThemedDialog" parent="@style/My.Theme.Dialog"></style></span></i></b></blockquote>
<br />
For <b>values-v11</b> folder: (Platform version for Honeycomb and above)<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><b><i><span style="color: #741b47;"><style name="My.Dialog.Theme" parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"></style></span></i></b><b><i><span style="color: #741b47;"><br /></span></i></b><b><i><span style="color: #741b47;"><style name="MyThemedDialog" parent="@style/My.Dialog.Theme"></style></span></i></b></span></blockquote>
There's a subtle difference between the two versions. Of course, other than the parent classes. In older platform versions, there wasn't a version of the Dialog theme without a title bar. So, what we do here, is to extend the basic Dialog them, and overwrite an attribute, so that our custom <b>"My.Theme.Dialog"</b> is a dialog without a title bar.<br />
<br />
But, for Honeycomb and above, the platform itself provides a version of the Dialog theme, without the title bar (or the Action Bar).<br />
<br />
And finally, the last step for getting everything to work is set the theme to your dialogs.<br />
<blockquote class="tr_bq">
<b><i><span style="color: #741b47; font-size: x-small;">MyDialog dialog = <span class="s1">new</span> MyDialog(<span class="s1">this</span>, R.style.<span class="s2">MyThemedDialog</span>);<br />dialog.setTitle(<span class="s3">"Here's my title"</span>);<br />dialog.show(); </span></i></b></blockquote>
Why didn't we use <b>"My.Theme.Dialog"</b> directly? Well, we could still try and tweak the theme for older versions, in the values folder, by adding a few more attributes.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHyT1KG9mc7gt0oMotrKbXheiT45EorO6i-lnTxksYYUyMo0JxYGR1dCwsJaz7uP0yeoSxd-ZEviX6og4OaiQy9g_Lb-QFfe91Q-jM0AplvcicNWAYmtKkEFEQnMyFOwP4qU1qSCrM6xJ8/s1600/JB+Simple+Dialog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHyT1KG9mc7gt0oMotrKbXheiT45EorO6i-lnTxksYYUyMo0JxYGR1dCwsJaz7uP0yeoSxd-ZEviX6og4OaiQy9g_Lb-QFfe91Q-jM0AplvcicNWAYmtKkEFEQnMyFOwP4qU1qSCrM6xJ8/s320/JB+Simple+Dialog.png" width="192" /></a></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<b>Dialog with title on Android 4.1</b></div>
<div style="text-align: center;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigaPtLfqOxsoJFVB3IplOsnl_OzYBl-NseJh1Pq3zEmtImPqA3OGAEnKLX4nWZ2f0tlfqdtBAFv0T_Z8Sq_-vks0DCAB8cTUaH2RjYOOcuRO2Vm8bCxanIMFTLouVy8oLK20EbjC3rqm6L/s1600/JB+Dialog+No+Title.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigaPtLfqOxsoJFVB3IplOsnl_OzYBl-NseJh1Pq3zEmtImPqA3OGAEnKLX4nWZ2f0tlfqdtBAFv0T_Z8Sq_-vks0DCAB8cTUaH2RjYOOcuRO2Vm8bCxanIMFTLouVy8oLK20EbjC3rqm6L/s320/JB+Dialog+No+Title.png" width="192" /></a></div>
<div style="text-align: center;">
<b><br /></b></div>
<div style="text-align: center;">
<b>Dialog with no title on Android 4.1</b></div>
<div style="text-align: center;">
<b><br /></b></div>
<div style="text-align: left;">
As you can see, for both older and newer platforms, the app runs by adapting itself and gives a consistent look and feel. You didn't have to do much with your code. </div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<b><i>15 lines of XML is the MAGIC here!!!! (I didn't count though, just guessing)</i></b></div>
<br />
<a href="https://github.com/coomar2841/StylesAndThemes">Sample project here.</a><br />
<br /></div>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-51184424767669121812012-02-03T23:52:00.000+05:302012-02-03T23:52:42.767+05:30Sending SMS on Android and tracking it<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijkO3Cxe-ufSgWyGergObkyqgNZr9rHhJDqpzKJBOvGQuwVH-38pCNx8hagrhUqo-5gQ7bcNy_m7buTeCqGsmGGk58Y84kiedYTHCn84OBEB01lNw5SbfeaBEoPz78dpCrBzW-KqI9m5AI/s1600/sms.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijkO3Cxe-ufSgWyGergObkyqgNZr9rHhJDqpzKJBOvGQuwVH-38pCNx8hagrhUqo-5gQ7bcNy_m7buTeCqGsmGGk58Y84kiedYTHCn84OBEB01lNw5SbfeaBEoPz78dpCrBzW-KqI9m5AI/s1600/sms.png" /></a></div>
Lets look at how to send an SMS. It's pretty simple though. A few lines of code and your SMS is gone. To make it more convenient and meaningful, we should also be able to track and let the user know when the SMS is sent and when it is delivered. For a start, I won't be looking into how to trap the error messages here and log or show it to the user. May be, when I get some more time, I will update this post. For now, lets track our SMS.<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><b style="color: #990000;"> Intent sentIntent = new Intent(INTENT_ACTION_SENT);<br /> PendingIntent pendingSentIntent = PendingIntent.getBroadcast(this,<br /> REQUEST_CODE_ACTION_SENT, sentIntent,<br /> PendingIntent.FLAG_UPDATE_CURRENT);<br /><br /> Intent deliveryIntent = new Intent(INTENT_ACTION_DELIVERY);<br /> PendingIntent pendingDeliveryIntent = PendingIntent.getBroadcast(this,<br /> REQUEST_CODE_ACTION_DELIVERY, deliveryIntent,<br /> PendingIntent.FLAG_UPDATE_CURRENT);<br /><br /> SmsManager smsManager = SmsManager.getDefault();<br /><br /> // Second parameter is the service center number. Use null if you want<br /> // to use the default number<br /> smsManager.sendTextMessage(number, null, message, pendingSentIntent,<br /> pendingDeliveryIntent);</b></span></blockquote>
<b> </b><br />
In the above code snipped, you can see that we are passing 2 pending intents to the SMSManager, one of which will be fired when the SMS is sent, and the other, when the SMS is delivered. It would also let you know the error type if the sending or delivery fails, so that you can take action for the errors. INTENT_ACTION_SENT and INTENT_ACTION_DELIVERY are string constants, which are just some random actions required to setup of the PendingIntents and receive them back.<br />
<br />
<a href="http://developer.android.com/reference/android/telephony/SmsManager.html#sendTextMessage%28java.lang.String,%20java.lang.String,%20java.lang.String,%20android.app.PendingIntent,%20android.app.PendingIntent%29">Setting up the SMS</a> is super easy. How do we track or listen to the updates, which happen through the PendingIntents? Well, those pending intents could be for starting an Activity, a Service or sending out a Broadcast. As you can see, here, I have used a Broadcast, to keep it simple. So, in our activity, we would need to register BroadcastReceivers for the same actions.<br />
<blockquote class="tr_bq">
<b style="color: #990000;"><span style="font-size: x-small;"> IntentFilter filter = new IntentFilter(INTENT_ACTION_SENT);<br /> filter.addAction(INTENT_ACTION_DELIVERY);<br /><br /> registerReceiver(smsSentDeliveredReceiver, filter);</span></b></blockquote>
<br />
Now, the onReceive() method will be fired, when those events happen, and thus you can notify the user about when the message is sent and delivered.<br />
<blockquote class="tr_bq" style="color: #990000;">
<b><span style="font-size: x-small;"> String action = intent.getAction();<br /> Log.i(TAG, "Received: " + action);<br /><br /> if (action.equals(INTENT_ACTION_SENT)) {<br /> Log.i(TAG, "Message: Sent");<br /> Toast.makeText(this, "Message sent", Toast.LENGTH_LONG).show();<br /> } else if (action.equals(INTENT_ACTION_DELIVERY)) {<br /> Log.i(TAG, "Message: Delivered");<br /> Toast.makeText(this, "Message delivered", Toast.LENGTH_LONG).show();<br /> }</span></b></blockquote>
<br />
You can find the sample app and the <a href="https://github.com/coomar2841/SendSMSnMMSDroid">source code here</a>. Give it a run.<br />
<div style="color: red;">
<span style="font-size: x-small;"><i><b><br /></b></i></span></div>
<span style="color: red; font-size: x-small;"><i><b>Note: Using this example, you cannot send SMS to real numbers from an emulator. The SMS will be sent, but it will never be delivered.</b></i></span></div>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com3tag:blogger.com,1999:blog-1474889468959966316.post-6060980215189466002012-01-12T22:55:00.000+05:302012-01-12T23:09:29.514+05:30Download Videos from Youtube Trick<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh784jlSasVyjNNqeK28CsQXI0rzRbmu3L2SAKO8oQYexibH_INriWFBo2-H_v95kWUCSG09i43q4TKucL6puc735tAXP6fPS4sX7MpDUnRT9QR2LhZhUTA2ILm47u9NizsYN1wNgRKpF0E/s1600/yt_powered_by_black.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh784jlSasVyjNNqeK28CsQXI0rzRbmu3L2SAKO8oQYexibH_INriWFBo2-H_v95kWUCSG09i43q4TKucL6puc735tAXP6fPS4sX7MpDUnRT9QR2LhZhUTA2ILm47u9NizsYN1wNgRKpF0E/s1600/yt_powered_by_black.png" /></a></div>
First things first. Is it legal to download videos from Youtube?<br />
<br />
As much I have understood from the <a href="http://www.youtube.com/t/terms">Terms of Service</a>, it's not a straight yes or no. Basically, Youtube doesn't have a publicly available API or service that would allow users to download the videos. Of course, you can download back the videos that you had originally uploaded. But who would do that anyway?<br />
<br />
However, there are workarounds and tricks with which you can actually download any video from the website. There are many softwares/add-ons that easily do this job. Here is a snapshot from the published "<a href="http://www.youtube.com/t/terms">Terms of Service</a>".<br />
<blockquote class="tr_bq">
<br />
<div style="color: blue;">
<i>You shall not download any Content unless you see a “download” or
similar link displayed by YouTube on the Service for that Content. You
shall not copy, reproduce, make available online or electronically
transmit, publish, adapt, distribute, transmit, broadcast, display,
sell, license, or otherwise exploit any Content for any other purposes
without the prior written consent of YouTube or the respective licensors
of the Content. YouTube and its licensors reserve all rights not
expressly granted in and to the Service and the Content.</i></div>
</blockquote>
<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/AVvXsEiorxS7xWf7ZJwP81n1khBvScWcby72PlhKc6XCrtE16EEWtEqsGqiwN8jzo4b3PylGuhm-kmqkQcWAei_ST7kQFtniDoLK8fjU1Ki7Wgl09Jj1OlrdicZoUraPxuvzrmvTfTHEIpJ_lVyQ/s1600/Youtube+Policy.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiorxS7xWf7ZJwP81n1khBvScWcby72PlhKc6XCrtE16EEWtEqsGqiwN8jzo4b3PylGuhm-kmqkQcWAei_ST7kQFtniDoLK8fjU1Ki7Wgl09Jj1OlrdicZoUraPxuvzrmvTfTHEIpJ_lVyQ/s400/Youtube+Policy.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">From Youtube <a href="http://www.youtube.com/t/terms">Terms of Service</a></td></tr>
</tbody></table>
<br />
It says, that you cannot exploit the content/content-owners by selling the videos or re-distributing it, thereby, making a profit against your sales. That's obviously illegal for any kind of content, unless of course, the license makes that content freely re-distributable. So, if you download the videos using those workarounds and tricks, only for your personal use (ex, offline viewing), you probably aren't breaking any rules. What about those add-ons/softwares that do this? Well, it's not illegal for them, since they are just distributing the software. So, they are off the hook. <br />
<br />
For personal use, it seems ok to download videos off from Youtube. So? let's see how hard or difficult it is to get this working.Actually, it's quite simple.<br />
<br />
<b>Step 1:</b> You should have the <b style="color: blue;">VIDEO ID</b> of the video that you want to download.<br />
<br />
<b>Step 2:</b> You need to make a call to this api, to get the details for that video. The <b>fmt</b> parameter is for getting the specified format of the videos. See the <b>"Quality and Codecs"</b> section on <a href="http://en.wikipedia.org/wiki/YouTube">this page on Wikipedia</a>.<br />
<blockquote class="tr_bq">
<b><span style="font-size: x-small;"><i>URL => <span style="color: blue;">http://www.youtube.com/get_video_info?video_id=VIDEO_ID&fmt=6</span></i></span></b></blockquote>
<b>Step 3:</b> Process the response. You will get a plain string response. That response contains all the direct URLs to various formats of the video. Look for the key <b>"url_encoded_fmt_stream_map"</b> and the value for this key is what you need from this response. You will need to filter out all the URLs from here, and get hold of the URL to the format you want to download. Here are some sample URLs.<br />
<blockquote class="tr_bq" style="color: #990000;">
<b><span style="font-size: xx-small;">http://o-o.preferred.bharti-bom1.v8.lscache7.c.youtube.com/videoplayback?sparams=id,expire,ip,ipbits,itag,source,ratebypass,cp&fexp=904510,914501,908302,902315,916201,905267&itag=45&ip=203.0.0.0&signature=095A9503E49931B0B849257048E73EB7388F515A.C13F4074ED92A82DF94BBD73E808E917369C224D&sver=3&ratebypass=yes&source=youtube&expire=1326412828&key=yt1&ipbits=8&cp=U0hRS1RMUF9HUkNOMV9MRlRJOjZ2TTNoOG9ialZD&id=c418f3a4b0f1b751&quality=hd720&fallback_host=tc.v8.cache7.c.youtube.com&type=video/webm; codecs="vp8.0, vorbis"&itag=45</span></b></blockquote>
<blockquote class="tr_bq">
<b><span style="font-size: xx-small;"><span style="color: #990000;">http://o-o.preferred.bharti-bom1.v11.lscache3.c.youtube.com/videoplayback?sparams=id,expire,ip,ipbits,itag,source,ratebypass,cp&fexp=904510,914501,908302,902315,916201,905267&itag=22&ip=203.0.0.0&signature=2C46F096073FDACEFD3B4895EDBC3CA1162682AD.3BCAE9E76BBE98D3FB687AF16ECC595E35AD8173&sver=3&ratebypass=yes&source=youtube&expire=1326412828&key=yt1&ipbits=8&cp=U0hRS1RMUF9HUkNOMV9MRlRJOjZ2TTNoOG9ialZD&id=c418f3a4b0f1b751&quality=hd720&fallback_host=tc.v11.cache3.c.youtube.com&type=video/mp4; codecs="avc1.64001F, mp4a.40.2"&itag=22</span> </span></b></blockquote>
If you notice the URLs, there is a type parameter, where you can determine which URL is for which format (<b>type=video/mp4</b>, <b>type=video/webm</b> etc).<br />
<br />
<b>Step 4:</b> To finally be able to download the video, you need to strip off a few values from these URLs, just to make sure your calls don't fail due to long URLs. What I have noticed is that if you strip off (everything after the quality param) the last parts of the URLs, everything's just fine. So, the final URL would be something like:<br />
<blockquote class="tr_bq">
<b style="color: #990000;"><span style="font-size: xx-small;">http://o-o.preferred.bharti-bom1.v11.lscache3.c.youtube.com/videoplayback?sparams=id,expire,ip,ipbits,itag,source,ratebypass,cp&fexp=904510,914501,908302,902315,916201,905267&itag=22&ip=203.0.0.0&signature=2C46F096073FDACEFD3B4895EDBC3CA1162682AD.3BCAE9E76BBE98D3FB687AF16ECC595E35AD8173&sver=3&ratebypass=yes&source=youtube&expire=1326412828&key=yt1&ipbits=8&cp=U0hRS1RMUF9HUkNOMV9MRlRJOjZ2TTNoOG9ialZD&id=c418f3a4b0f1b751&quality=hd720</span></b></blockquote>
<br />
<b>Step 5:</b> Save the file with the proper extension. That's it. You are done.<br />
<br />
If you ask how I got to know about this trick? Well, everything's already out there on the web. A lot of people have already blogged about it before. But, I had to dig for it for almost 2 days. So, I hope someone finds it useful. So, if you want to make your own <b>Youtube Downloader</b>, now you know "How to Download Youtube Videos programmatically". <br />
<br />
<i><span style="font-size: x-small;"><b style="color: blue;">Note: This method might stop working as and when Google/Youtube blocks this loophole. </b><b style="color: blue;">In the past, Youtube has been known to block a few other workarounds that had existed.</b></span></i></div>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com11tag:blogger.com,1999:blog-1474889468959966316.post-6384279759982969952011-12-28T23:47:00.000+05:302011-12-29T23:03:09.796+05:30Bluetooth on Android : Part I<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="color: #0b5394;">
<span style="font-size: small;"><i>This is a part of a series of posts in which I will put forward a full working app what uses bluetooth on your Android device to discover, connect, pair, send and receive files. The source code would be tagged with each part of this series.</i></span></div>
<br />
<i><b><a href="https://github.com/coomar2841/droid_bt_connect/zipball/v1.0">Part 1</a>: The app should be able to discover and list out the devices (paired/unpaired).</b></i><br />
<br />
To start off with learning about bluetooth on Android, visit the <a href="http://developer.android.com/guide/topics/wireless/bluetooth.html">official documentation</a>. The documentation is quite lucid and clear. Here I will try to explain parts of my code.<br />
<br />
The first activity (<a href="https://github.com/coomar2841/droid_bt_connect/blob/master/src/com/beanie/bluetooth/HomeActivity.java">HomeActivity</a>), for now, will have a single button "Discover Devices", which will take you to the activity(<a href="https://github.com/coomar2841/droid_bt_connect/blob/master/src/com/beanie/bluetooth/DiscoverDevicesActivity.java">DiscoverDevicesActivity</a>) where you can see the list of devices that are visible by your device.<br />
<br />
This activity does a few things, quite a few if-else conditions.<br />
<ul style="text-align: left;">
<li>First, you need to check if your device supports bluetooth. If you don't have the hardware capability on your phone, you won't be able to run this application. Eh!! Most of the phones would obviously have bluetooth. Ummm...Yes... But the emulators don't. Arrggghhh!!!!</li>
<li>Once you are sure that your device has bluetooth capability, the next thing to check if it is enabled or not. If it's enabled, move on to the next step, else you will need to turn it on first.</li>
</ul>
<blockquote class="tr_bq">
<div style="color: #990000;">
<b><span style="font-size: x-small;"><i>Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);</i></span></b></div>
<b style="color: #990000;"><span style="font-size: x-small;"><i>startActivityForResult(intent, REQUEST_ENABLE_BT); </i></span></b></blockquote>
<ul style="text-align: left;">
<li>Once, you click on "Yes" on the confirmation dialog that you will see, bluetooth radio will be switched on for you. On the screen, the "Scan" button will become active. Once you tap the "Scan" button, the ListView will show the list of devices that your device can discover.</li>
</ul>
That's all for the first part of the series. But, there's a little more to understand abut discovery.<br />
<br />
The process of discovery is asynchronous. The list view, currently shows two kinds of devices.<br />
<ol style="text-align: left;">
<li>Devices which your phone already knows about (Paired)</li>
<li>Devices which are discovered (Which are not paired with your device)</li>
</ol>
Getting the already paired devices is simple. The <a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html">BluetoothAdapter</a> will give you details about such devices. <br />
<blockquote class="tr_bq">
<div style="color: #990000;">
<i><span style="font-size: x-small;"><b>// Check already discovered devices</b></span></i></div>
<i style="color: #990000;"><span style="font-size: x-small;"><b>Set<BluetoothDevice> devices = bluetoothAdapter.getBondedDevices();<br />for (BluetoothDevice device : devices) {<br /> adapter.addDevice(device);<br />}<br />adapter.notifyDataSetChanged();</b></span></i></blockquote>
Now comes the actual discovery part. For this, you will need to register a broadcast receiver which will be called whenever a new device is found. After registering the receiver, you need to trigger the discovery by calling the <a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29">startDiscovery()</a> method of the <a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html">BluetoothAdapter</a>.<br />
<blockquote class="tr_bq">
<i style="color: #990000;"><b><span style="font-size: x-small;">// Scan for new devices<br />IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);<br />registerReceiver(devicesReceiver, filter);<br /><br />bluetoothAdapter.startDiscovery();</span></b></i></blockquote>
On the receiver's onReceive() method, we pick up the details about the new device found, and add it to our ListView.<br />
<blockquote class="tr_bq">
<div style="color: #990000;">
<span style="font-size: x-small;"><i><b>public void onReceive(Context context, Intent intent) {<br /> String action = intent.getAction();<br /> // When discovery finds a device<br /> if (BluetoothDevice.ACTION_FOUND.equals(action)) {<br /> Log.i(TAG, "Device found");<br /> <br /> // Get the BluetoothDevice object from the Intent<br /> BluetoothDevice device = intent<br /> .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);<br /> // Add the name and address to an array adapter to show in a ListView<br /> adapter.addDevice(device);<br /> adapter.notifyDataSetChanged();</b></i></span></div>
<span style="font-size: x-small;"><i style="color: #990000;"><b>}</b></i></span></blockquote>
The <a href="https://github.com/coomar2841/droid_bt_connect/blob/master/src/com/beanie/bluetooth/DevicesAdapter.java">DevicesAdapter</a> is a custom adapter for the ListView which we will be updating in the subsequent posts to show more information about the devices.<br />
<br />
As always, you should unregister your receiver, once your activity is paused. Also, in addition to this, you should also cancel the discovery if at all you have started by calling the cancelDiscovery() method of the BluetoothAdapter. <br />
<br />
The part 1 of the project can be checked out by fetching the source code and checking out the v1.0 tag from the repository. The <a href="https://github.com/coomar2841/droid_bt_connect/">complete source code can be found here</a>.<br />
<br />
Alternately, if you want to download the source of Part 1 as a zip, use <a href="https://github.com/coomar2841/droid_bt_connect/zipball/v1.0">this link to Part 1</a>.</div>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com6tag:blogger.com,1999:blog-1474889468959966316.post-72235215476989863582011-11-01T04:03:00.000+05:302011-11-01T04:10:06.514+05:30Drag and Drop (Honeycomb/ICS)<div dir="ltr" style="text-align: left;" trbidi="on">
Drag and drop is already available with Honeycomb and up. In this example, we will see how to implement a simple Drag and Drop Operation.<br />
<br />
We have a ListView with some items. The other half of the screen would have a drop area which has a single <a href="http://developer.android.com/reference/android/widget/TextView.html">TextView</a>. We will see, how to drag items from the <a href="http://developer.android.com/reference/android/widget/ListView.html">ListView</a>, drop them into the drop area, which will update the <a href="http://developer.android.com/reference/android/widget/TextView.html">TextView</a> with the list item's title, and also, that particular item would be removed from the <a href="http://developer.android.com/reference/android/widget/ListView.html">ListView</a>.<br />
<br />
We will trigger the drag operation, when you long tap on an item in the ListView. After the drag operation is started, you will see a floating view of the selected item, which you can move around the screen. When you approach the drop area, the background of the drop area would change, which means that you can now drop your item. Once you leave the item, the TextView inside the drop area will show the text of the selected item.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyDI1cWKaTz2txdxePTXZX9R65zojf-EQMwwRYL9LONOGkA6IfcOWQCNlOpAJQMiY53V9kvah6giycuFCGFD3_cbAMDImjH8nksZOqU19LullE1d65z1AbG-S7jzHMNbz30nU6xzAvqd5V/s1600/drag_drop_hc_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyDI1cWKaTz2txdxePTXZX9R65zojf-EQMwwRYL9LONOGkA6IfcOWQCNlOpAJQMiY53V9kvah6giycuFCGFD3_cbAMDImjH8nksZOqU19LullE1d65z1AbG-S7jzHMNbz30nU6xzAvqd5V/s400/drag_drop_hc_1.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiGwt0kheVvyF1JbTvcb0B2i7BCo8R_XgEPHgpfCU0k7MfKLA4Ygi9CICHVEnrjYqqf3K6EFoXonjd0-OA6VzWlm6gwk-nDieiMc2uVxT5TpvX24lIs1Bs7q2LynV89tpq95Ba7eh0srHS/s1600/drag_drop_hc_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiGwt0kheVvyF1JbTvcb0B2i7BCo8R_XgEPHgpfCU0k7MfKLA4Ygi9CICHVEnrjYqqf3K6EFoXonjd0-OA6VzWlm6gwk-nDieiMc2uVxT5TpvX24lIs1Bs7q2LynV89tpq95Ba7eh0srHS/s400/drag_drop_hc_2.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLsNh60rzOtVtpvhh_V3uPZoAQ1VTafUOb3UOHwlZ-qp_PUuPTH9CijB08BlwiXC0srNWOqI3EJqbvgHB8oknMXwH_j2iIVXZJV_ptauLOPGKNzfzTPkIm3YO7PNkb2UJqvwdccyaO-b9T/s1600/drag_drop_hc_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLsNh60rzOtVtpvhh_V3uPZoAQ1VTafUOb3UOHwlZ-qp_PUuPTH9CijB08BlwiXC0srNWOqI3EJqbvgHB8oknMXwH_j2iIVXZJV_ptauLOPGKNzfzTPkIm3YO7PNkb2UJqvwdccyaO-b9T/s400/drag_drop_hc_3.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjutFT0nu69kY0vNa00fRmLcL9QyuGbcjKKmXSnbwScQb1qOvK-vuFsVCn1T8I57bc8bL6eHxBc7yhgP7ckPYQbD-KsibQQmTdDtkUmSRAPwbsEcz8xf0qX4urNX8KiUMccogjyWnwkzrmX/s1600/drag_drop_hc_4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjutFT0nu69kY0vNa00fRmLcL9QyuGbcjKKmXSnbwScQb1qOvK-vuFsVCn1T8I57bc8bL6eHxBc7yhgP7ckPYQbD-KsibQQmTdDtkUmSRAPwbsEcz8xf0qX4urNX8KiUMccogjyWnwkzrmX/s400/drag_drop_hc_4.png" width="400" /></a></div>
<br />
This should also work on Ice Cream Sandwich. You can find the whole <a href="http://code.google.com/p/myandroidwidgets/source/browse/#svn%2Ftrunk%2FHCDragDrop">source code here</a>. The code is quite self-explanatory. But, if you have any queries, let me know through the comment form. There are a few comments in the code to help you.</div>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com11tag:blogger.com,1999:blog-1474889468959966316.post-44677136185184754322011-10-19T04:19:00.000+05:302011-10-25T00:10:37.481+05:30Simple ViewPager for Android<div dir="ltr" style="text-align: left;" trbidi="on">
You would have seen many applications recently, which make use of the new and awesome <b>ViewPager</b> that allows views to be horizontally scrollable. The new <b>Android Market</b> app also implements a flavor of the ViewPager, although it's a little more complex that what we will see here. This class is not available directly for you to use. Check <a href="http://android-developers.blogspot.com/2011/08/horizontal-view-swiping-with-viewpager.html">this blog</a> for some insight. It would required you to download a <b>compatibility library</b> from Google, add it to your project wherever you would like to use it, and go about paging views.<br />
<br />
And yes, it's very simple to implement. I have coded up a little sample where it shows you how to use a <b>ViewPager</b> with a simple <b>PagerAdapter</b>. More or less, it works like the <b>ListViews</b>. Although there is not much documentation for this, it's quite easy to set up everything.<br />
<br />
Firstly, you would need to add the ViewPager into your layout file.<br />
<br />
<b>Listing of main.xml</b><br />
<blockquote>
<b style="color: #990000;"><span style="font-size: x-small;"><?xml version="1.0" encoding="utf-8"?><br /><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br /> android:orientation="vertical" android:layout_width="fill_parent"<br /> android:layout_height="fill_parent"><br /> <TextView android:text="Page 1" android:id="@+id/textViewHeader"<br /> android:layout_width="fill_parent" android:layout_height="wrap_content"<br /> android:gravity="center" android:padding="10dip" android:textStyle="bold"></TextView><br /> <android.support.v4.view.ViewPager<br /> android:layout_width="fill_parent" android:layout_height="fill_parent"<br /> android:id="@+id/viewPager" /><br /></LinearLayout></span></b></blockquote>
In this sample, we are using an extra TextView which would show the current page you are on.<br />
<br />
<b>Setting up the ViewPager</b><br />
<blockquote>
<div style="color: #990000;">
<b><span style="font-size: x-small;">ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">MyPagerAdapter adapter = new MyPagerAdapter(this);</span></b></div>
<b><span style="color: #990000; font-size: x-small;">viewPager.setAdapter(adapter);</span></b></blockquote>
This code is almost identical to what we would do for a ListView or Gallery. The only difference is that the adapter here, extends a PagerAdapter instead.<br />
<br />
<b>The PagerAdapter</b><br />
<br />
The PagerAdapter has a few methods that you would implement. For this example, I have four different views, one for each page. 2 are ListViews, a TextView and a Button, not in that order. Here are the methods that you would need to implement. Look at the <b>MyPageAdapter</b> class for more.<br />
<br />
<blockquote>
<div style="color: #990000;">
<b><span style="font-size: x-small;">@Override</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">public void destroyItem(View view, int arg1, Object object) {</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;"> ((ViewPager) view).removeView((View)object);</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">}</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">@Override</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">public int getCount() {<br /> return views.size();</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">}</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">@Override</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">public Object instantiateItem(View view, int position) {<br /> View view = views.get(position);<br /> ((ViewPager) view).addView(view);<br /> return view;</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">}</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">@Override</span></b></div>
<div style="color: #990000;">
<b><span style="font-size: x-small;">public boolean isViewFromObject(View view, Object object) {<br /> return view == object;</span></b></div>
<b><span style="color: #990000; font-size: x-small;">}</span></b></blockquote>
And you are done!!! Sweet.... You can find the whole <a href="https://github.com/coomar2841/SimpleViewPager">source code here</a>.</div>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com22tag:blogger.com,1999:blog-1474889468959966316.post-22979105057290720602011-09-25T02:33:00.000+05:302011-09-25T02:37:35.920+05:30Automating Builds on Android - Part 2In the previous post, <a href="http://techdroid.kbeanie.com/2011/09/automating-builds-on-android-part-1.html">Automating Builds on Android - Part 1</a>, we saw how to setup our projects to automate the build process. In this post, we will automate the process further to make Ant automatically use the passwords for our keystore and alias, label our builds to whatever name we like and put it in a specific location on your system (from where others can access it).<br />
<br />
1. To make Ant use the passwords for our keystore automatically, we will create a separate properties file in our project folder where. Let's name it "<a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/HelloWorldAnt/passwords.properties">passwords.properties</a>". This file would contain two properties as listed below.<br />
<blockquote>
<b><span style="color: purple;">key.store.password=sample</span><br style="color: purple;" /><span style="color: purple;">key.alias.password=sample</span> </b></blockquote>
2. We will need to make a small change in our <b>build.xml</b> file to tell Ant to load this property file while building. To do this, we simply add this one line in the <b>build.xml</b> file.<br />
<blockquote>
<b><span style="color: purple;"><property file="passwords.properties" /></span></b></blockquote>
If you try to run <b>"ant release"</b> command in your terminal, you will notice that Ant doesn't ask you to enter your passwords anymore. It has picked up the passwords from your <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/HelloWorldAnt/passwords.properties">passwords.properties</a> file.<br />
<br />
3. Adding a name and a time-stamp to your builds while making a release build needs a little more effort. We will now create another properties file called "<a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/HelloWorldAnt/extras.properties">extras.properties</a>". This file would contain two more properties as listed below.<br />
<blockquote>
<div style="color: purple;">
<b>file_name_format=test_build_hello_world</b></div>
<b><span style="color: purple;">build_location=C:/Builds/HelloWorld</span></b></blockquote>
The <b>file_name_format</b> would be used to name your output builds. Sometimes, you would want to name your builds differently based on whether it is a "daily_build" or "weekly_build" or a "release_build". Instead of renaming the output file manually, you could just change this property accordingly just before your type in <b>"ant release"</b>, and your builds would automatically be named as you like. The other property, <b>build_location</b> is again a configurable value here, where Ant would put all your builds in the specified location. This could be a shared folder on your system from where anyone else can access it easily.<br />
<br />
4. Now comes the lengthy part. To accommodate these changes in our build process, our original <b>build.xml</b> is not enough. We will have to tweak the actual underlying <b>build.xml</b> to make our build process more streamlined. Let's see how to do it. Pick up the <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/HelloWorldAnt/build.xml">build.xml from the sample project</a> and replace the previous build.xml with this one. It will have a whole lot of Ant scripts. You don't have to worry about most of it, except for these lines.<br />
<br />
<blockquote>
<span style="font-size: small;"><b><span style="color: purple;"> <!-- Date/Time format for naming the file--></span><br style="color: purple;" /><span style="color: purple;"> <tstamp></span><br style="color: purple;" /><span style="color: purple;"> <format property="time" pattern="dd_MMM" /></span><br style="color: purple;" /><span style="color: purple;"> </tstamp></span><span style="color: purple;"></span><br style="color: purple;" /><span style="color: purple;"> <property file="local.properties" /></span><br style="color: purple;" /><span style="color: purple;"> <property file="passwords.properties" /></span><br style="color: purple;" /><span style="color: purple;"> <property file="extras.properties" /></span></b></span></blockquote>
<br />
Notice, that, we are using a time-stamp property which we would be using in our <b>build.xml</b> to version our builds based on the specific format. Our builds will be names as <b>"test_build_hello_world_22_SEP.apk"</b>.<br />
<br />
The last thing you need to change is this piece of code. You will find it somewhere in the new <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/HelloWorldAnt/build.xml">build.xml</a>.<br />
<br />
<blockquote>
<span style="font-size: x-small;"><b style="color: purple;"> <property name="out.release.file.name" value="${file_name_format}_${time}.apk" /><br /> <property name="out.release.file" location="${build_location}/${out.release.file.name}" /></b></span></blockquote>
<br />
5. Here, you can see that we have changed the property <b>"out.release.file.name"</b> to a value that we want the output file to be named as. And also, we changed the <b>"out.release.file"</b> to use our configured directory from the <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/HelloWorldAnt/extras.properties">extras.properties</a> file.<br />
<br />
The final step is to run <b>"ant release"</b> for the last time, and you will see your final release build placed at your desired location.<br />
<br />
You can find the <a href="http://code.google.com/p/myandroidwidgets/source/browse/#svn%2Ftrunk%2FHelloWorldAnt">sample project here</a>. <br />
<br />Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com2tag:blogger.com,1999:blog-1474889468959966316.post-91483157707447849882011-09-25T01:44:00.000+05:302011-09-25T02:37:19.463+05:30Automating Builds on Android - Part 1Do you find it hard to get a release build of an Android app? Well, you could say that it's not at all difficult. It just takes about 1 minute to get a build, sign it with your release keys and you are done. For a typical moderately big Android app, you could have a QA process where you send out builds for testing or verification to someone else. And you could be sending out the builds multiple times a day. In such situations, it becomes a tad tedious getting release builds out of your eclipse. In this post, we will try to automate this process of preparing the release builds.<br />
<br />
Our tool of choice is Ant. Most of you perhaps already know how to do set it up. We will, however, also see how to version or auto-label your builds in next post. In this post, we will go through the basics.<br />
<br />
<b>1.</b> To start off with, create a <a href="http://code.google.com/p/myandroidwidgets/source/browse/#svn%2Ftrunk%2FHelloWorldAnt">"HelloWorldAnt" Android project</a>.<br />
<br />
<b>2.</b> The next step is to prepare our project to use Ant scripts. To do this, fire up your terminal, go to the directory where your project rests and type out this command.<br />
<blockquote>
<b><span style="color: purple;">android update project -p . </span></b></blockquote>
3. A few files would be added to your project. Among these, the <b>build.xml</b> is the file that Ant would read and package your apk.<br />
<blockquote>
<div style="color: purple;">
<b>Updated local.properties</b></div>
<div style="color: purple;">
<b>Added file ./build.xml</b></div>
<b><span style="color: purple;">Updated file ./proguard.cfg</span></b></blockquote>
4. Now try running this command in the terminal. After we setup everything, this is the one single command that we would run every time we need to create a release build.<br />
<blockquote>
<b><span style="color: purple;">ant release</span></b></blockquote>
5. You will see a long log of what Ant is doing. Look towards the end of the logs and you will notice these lines:<br />
<blockquote>
<div style="color: purple;">
<b>-release-nosign:</b></div>
<div style="color: purple;">
<b> [echo] No key.store and key.alias properties found in build.properties.</b></div>
<div style="color: purple;">
<b> [echo] Please sign /workspace/HelloWorldAnt/bin/HelloWorldAntActivity-unsigned.apk manually</b></div>
<b><span style="color: purple;"> [echo] and run zipalign from the Android SDK tools. </span></b></blockquote>
<br />
6. So, till this point, the Ant tool has prepared an <b>unsigned apk</b> which it has kept in the bin folder of your project and it asks you to manually sign this apk with your release keys. Next step is to automate this process.<br />
<br />
7. Put your keystore inside your project folder. For this project, <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/HelloWorldAnt/sample_keystore"><b>sample_keystore</b></a> is the keystore that we would be using to sign this application. Now, we need to tell Ant to use this keystore to sign our builds with. Here, we will add a few files to our project.<br />
<br />
<b>Filename: <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/HelloWorldAnt/build.properties">build.properties</a></b><br />
<br />
<b>File Listing:</b><br />
<blockquote>
<b><span style="color: purple;">key.store=sample_keystore</span><br style="color: purple;" /><span style="color: purple;">key.alias=samplekeystore</span></b></blockquote>
8. At this point, if you try running <b>"ant release"</b> command, it will ask you to enter the password for the keystore and the alias name, and finally, it would put the release and signed builds in your bin folder. <br />
<br />
The next post will talk about customizing the build process to the next level.<br />
<br />
<a href="http://techdroid.kbeanie.com/2011/09/automating-builds-on-android-part-2.html">Automating Builds on Android - Part 2</a><br />
<br />
<a href="http://code.google.com/p/myandroidwidgets/source/browse/#svn%2Ftrunk%2FHelloWorldAnt">You can find the sample project here. </a>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com3tag:blogger.com,1999:blog-1474889468959966316.post-23623158298491609522011-07-15T01:15:00.000+05:302011-07-15T01:38:34.487+05:30Flip animation in Android<div style="text-align: center;">
<span style="font-size: large;">I love animations. Let's see the video first. If you are excited, go peek at the code.</span></div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dyEBXlHK-AYGRh53emPZ1vCbGJPif2nws-xDq0dP3pHbMAc8h63zSW8rsxXmuY1j8ngSU88unMRXhSN3JehPQ' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
In this example, the main layout contains two <a href="http://developer.android.com/reference/android/widget/ImageView.html">ImageView</a> widgets with two different images that are to be animated. The image views actually overlapp each other, at first, but as the animation starts, only one of them is visible at a time, while the other is invisible.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
For the animation, we are using a <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/FlipAnimatorExample/src/com/beanie/examples/animation/FlipAnimator/FlipAnimator.java">FlipAnimator</a> class, which extends the <a href="http://developer.android.com/reference/android/view/animation/Animation.html">Animation</a> class. Here is how we need to initialize and setup the animation.</div>
<blockquote>
<div style="text-align: left;">
<i style="color: #b45f06;"><b>FlipAnimator animator = new FlipAnimator(imageViewOriginal, imageViewFlip,<br /> imageViewFlip.getWidth() / 2, imageViewFlip.getHeight() / 2);<br /> if (imageViewOriginal.getVisibility() == View.GONE) {<br /> animator.reverse();<br /> }<br /> layout.startAnimation(animator);</b> </i></div>
</blockquote>
There is a small check to tell the animator where to reverse the animation. This is not the perfect way, but you will get an idea. To initialize the animator, you will need to pass the original view and the flipped view and the x and y position of the axes about which it will be flipped.<br />
<br />
The animator, internally uses a <a href="http://developer.android.com/reference/android/view/animation/AccelerateDecelerateInterpolator.html">AccelerateDecelerateInterpolator</a>.<br />
<i>"An interpolator where the rate of change starts and ends slowly but
accelerates through the middle."</i><br />
<br />
The main logic of the animation is written inside this method:<br />
<i><a href="http://developer.android.com/reference/android/view/animation/Animation.html#applyTransformation%28float,%20android.view.animation.Transformation%29">protected void applyTransformation(float interpolatedTime, Transformation t)</a></i><br />
<br />
<i>You can find the whole <a href="http://code.google.com/p/myandroidwidgets/source/browse/#svn%2Ftrunk%2FFlipAnimatorExample%253Fstate%253Dclosed">source code here</a>. </i><br />
<br />
<i><b>References:</b></i><br />
<a href="http://www.inter-fuser.com/2009/08/android-animations-3d-flip.html">http://www.inter-fuser.com/2009/08/android-animations-3d-flip.html</a> <i> </i>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com2tag:blogger.com,1999:blog-1474889468959966316.post-29384539924240691922011-07-11T01:05:00.000+05:302011-07-11T01:05:56.070+05:30Understanding Intents and Intent-Filters in Android<a href="http://developer.android.com/reference/android/content/Intent.html">Intents</a> or <a href="http://developer.android.com/reference/android/content/Intent.html">Intent</a> messaging is the Android’s way to pass messages/information to various components of Android. An <a href="http://developer.android.com/reference/android/content/Intent.html">Intent</a> object contains information that the target component can act upon. Through <a href="http://developer.android.com/reference/android/content/Intent.html">Intents</a>, your apps can trigger <a href="http://developer.android.com/reference/android/app/Activity.html">Activities</a>, <a href="http://developer.android.com/reference/android/app/Service.html">Services</a> and <a href="http://developer.android.com/guide/topics/manifest/receiver-element.html">Broadcast Receivers</a>.
The most common use of intents in any application is to directly launch
an Activity or Service to perform action on the data being passed with
the Intent object.<br />
<br />
<b>A sample use of Intent is shown in the following example.</b><br />
<i>1. To launch an Activity</i><br />
<blockquote>
<pre style="color: #b45f06;"><span style="font-size: small;"><i><b>Intent intent = new Intent(context, TagetActivity.class);
startActivity(intent);</b></i></span></pre>
</blockquote>
<i>2. To launch a Service</i><br />
<blockquote style="color: #b45f06;">
<pre><span style="font-size: small;"><i><b>Intent intent = new Intent(context, TargetService.class);
startService(intent);</b></i></span></pre>
</blockquote>
To pass some data within your intents you need pass them within the Intent object like this.<br />
<blockquote style="color: #b45f06;">
<pre><span style="font-size: small;"><i><b>intent.put(key, value);</b></i></span></pre>
</blockquote>
This way you can pass basic data-types that are supported by the
Intent class. In these examples, we are specifying the component names
explicitly, i.e, TagetActivity activity and TargetService service. These
intents are examples of <a href="http://developer.android.com/guide/topics/intents/intents-filters.html#ires">Explicit Intents</a> wherein you specify the target component that you want to handle your data.<br />
<br />
There would be situations where you would want the user to choose the
target component, or to put in another way, the target component is
determined dynamically at run-time depending on various factors. For an
example, you would like to write a E-Mail app. The basic requirement
would be that whenever a user clicks on an e-mail address, your app
should be triggered, and it should be designed to capture the e-mail
address that was clicked. This is where, <a href="http://developer.android.com/guide/topics/intents/intents-filters.html#ires">Implicit Intents</a>
come into picture. Since, the e-mail address link that the user clicks
on might not necessarily be a part of your application, you do not have
the privilege of launching your Compose Activity on the click event of
the link. What would you do in such a case?<br />
<br />
<b>What happens when the e-mail link is clicked?</b><br />
When an email link is clicked, the app would create an Implicit Intent
setting it up with the proper data and broadcast it. Something like
this:<br />
<blockquote style="color: #b45f06;">
<pre><span style="font-size: small;"><i><b>Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.put(Intent.EXTRA_EMAIL, {email addresses}];
startActivity(intent);</b></i></span></pre>
</blockquote>
In the above code snippet, we can see that the Intent here doesn’t
specify the component name. However, it specifies an action and the list
of email addresses. For this example, we just need to pass a string
array with just one email address that the user has clicked on.<br />
<br />
How would Android know which activity should be launched (or service
for example). In such cases, Android tries to find the best match, i.e,
the component that can handle such a payload. In case it finds multiple
components, it gives the user a choice to make. For instance, if you
have multiple email clients installed and all of them can handle such
type of Intents, the user gets a list of all these apps (see image). He
can then select one which would launch that particular component
(Activity for this example). If it fails to find any components to
handle this Intent, an exception will be thrown (<a href="http://developer.android.com/reference/android/content/ActivityNotFoundException.html">ActivityNotFoundException</a>
in this case). Here we have two email applications that can handle this
intent. The user is given a choice to select one of them when an e-mail
link is clicked. Depending on the user’s choice, the corresponding
activity will be launched.<br />
<b><br />
How do we write an Activity that can handle such Intents?</b><br />
We have to specify or rather design one of our activity, the compose
screen of our email client that can handle such intents. For that, we
need to specify Intent-Filters for this specific activity in the <a href="http://developer.android.com/guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a> file.<br />
<blockquote>
<span style="font-size: small;"><i><b><span style="color: #b45f06;"><activity android:name=".ComposeActivity"<br /> android:label="@string/app_name"><br /> <intent-filter android:label="@string/app_name"><br /> <action android:name="android.intent.action.SEND" /><br /> <data android:scheme="mailto" /> <br /> <category android:name="android.intent.category.DEFAULT"/><br /> </intent-filter><br /></activity></span></b></i></span></blockquote>
The above code itself is self-explanatory. Your activity now can handle
intents that are launched with this signature. The action is “<a href="http://developer.android.com/reference/android/content/Intent.html#ACTION_SEND">android.intent.action.ACTION_SEND</a>”
and the data scheme is “mailto”, i.e, any email address. So, in your
ComposeActivity, you can retrieve the email address list by querying the
intent for the key, <a href="http://developer.android.com/reference/android/content/Intent.html#EXTRA_EMAIL">EXTRA_EMAIL</a>
and you will get the list of email addresses (one in this case).
Typically, you will need to populate the Send To address field of your
ComposeActivity now.<br />
<br />
The intent resolution process tries to find a best match for the intent.
Once it finds an Intent and launches the Activity with or without user
interruption(in case multiple matches are found), the responsibility of
handling the intent now lies with the target component. To finish off
the article, here is the way to extract the email address that had been
clicked.<br />
<blockquote style="color: #b45f06;">
<pre><span style="font-size: small;"><i><b>Bundle data = getIntent().getExtras();
String[] emailAddresses = data.get(Intent.EXTRA_EMAIL);</b></i></span></pre>
</blockquote>
The <a href="http://developer.android.com/guide/topics/intents/intents-filters.html">developer docs</a>
on Intent, Intent Filters and Intent Resolution mechanism is a nice
read to understand the Intent mechanism of Android. You can find other
examples of the types of data and schemes that you can design your apps
for. <i></i> Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com5tag:blogger.com,1999:blog-1474889468959966316.post-81175109897602969062011-07-05T22:48:00.000+05:302011-09-26T23:47:30.271+05:30Custom title for your appsThe default title bar for the apps might not suit the theme of your app. You also might want to add a few more things to the title bar which the default title bar doesn’t help you with. This example will help you develop your own Title Widget which you can directly embed in your layouts containing a left icon, a title text and a progress bar. You can also control the contents of these three widgets and change it as required in your activities. Here we go.<br />
<br />
<b>1.</b> <b>The first thing you should do is to switch off the default title.</b> You can do this easily by specifying in your <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/TitleWidgetSample/AndroidManifest.xml" target="_blank">AndroidManifest.xml</a> file that do not intend to use it. <br />
<br />
<blockquote style="color: #b45f06;">
<span style="font-size: small;"><i><?xml version="1.0" encoding="utf-8"?><br />
<manifest xmlns:android="http://schemas.android.com/apk/res/android"<br />
package="com.beanie.samples.titlewidget" android:versionCode="1"<br />
android:versionName="1.0"><br />
<application android:icon="@drawable/icon" android:label="@string/app_name"<br />
android:theme="@android:style/Theme.NoTitleBar"><br />
<activity android:name=".TitleWidgetActivity"<br />
android:label="@string/app_name"><br />
<intent-filter><br />
<action android:name="android.intent.action.MAIN" /><br />
<category android:name="android.intent.category.LAUNCHER" /><br />
</intent-filter><br />
</activity><br />
</application><br />
<uses-sdk android:minSdkVersion="4" /><br />
</manifest></i></span></blockquote>
Here, in the application tag, set the theme of your app to use the <b>NoTitleBar</b> theme.<br />
<br />
<b>2.</b> Create a <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/TitleWidgetSample/res/layout/title_widget.xml" target="_blank">title_widget.xml</a> which would be the custom layout for your title bar. You can technically add any number of widgets here and finally display it with your custom title. As an example, we will add an <a href="http://developer.android.com/reference/android/widget/ImageView.html" target="_blank">ImageView</a>, a <a href="http://developer.android.com/reference/android/widget/TextView.html" target="_blank">TextView</a> and a <a href="http://developer.android.com/reference/android/widget/ProgressBar.html" target="_blank">ProgressBar</a> here.<br />
<br />
<b>3.</b> Create a <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/TitleWidgetSample/src/com/beanie/samples/titlewidget/TitleWidget.java" target="_blank">TitleWidget.java</a> class which extends LinearLayout(you can use any Layout) which loads this layout file and exposes methods to modify the contents of the widgets.<br />
<br />
<b>4.</b> Add the <a href="http://code.google.com/p/myandroidwidgets/source/browse/trunk/TitleWidgetSample/src/com/beanie/samples/titlewidget/TitleWidget.java" target="_blank">TitleWidget</a> class as the first view in all your activity layouts’ files to display your custom title bar.<br />
<br />
<blockquote style="color: #b45f06;">
<pre><i><?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.beanie.samples.titlewidget.TitleWidget
android:id="@+id/titleWidget"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</com.beanie.samples.titlewidget.TitleWidget>
</LinearLayout></i></pre>
</blockquote>
<b>5.</b> Now, in your activity, you can initialize this TitleWidget as any view, since it is a LinearLayout now, and can control the contents of all the widgets.<br />
<br />
<blockquote style="color: #b45f06;">
<pre><i> @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Initialize title Widget
TitleWidget titleWidget = (TitleWidget)</i></pre>
</blockquote>
<blockquote style="color: #b45f06;">
<pre><i> findViewById(R.id.titleWidget);
// Call the methods to change the underlying widgets
titleWidget.setTitle("My Custom Title");
titleWidget.setIcon(R.drawable.icon);
titleWidget.showProgressBar();
titleWidget.hideProgressBar();
}</i></pre>
</blockquote>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrEinirnw_5esnFIOs8UhxYZydixTPc-Dc5Z0AOAPpC7luCgHtdcsnJlxQLCQRpIi4Lp1-hK-P0mr5ELeMgXC3CncGi4ZaEo7RFzfxEa7KRlzQgkIhhukVSS9Ks_nfrAUY83eGO4kRMPEz/s1600/custom_title_bar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="86" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrEinirnw_5esnFIOs8UhxYZydixTPc-Dc5Z0AOAPpC7luCgHtdcsnJlxQLCQRpIi4Lp1-hK-P0mr5ELeMgXC3CncGi4ZaEo7RFzfxEa7KRlzQgkIhhukVSS9Ks_nfrAUY83eGO4kRMPEz/s320/custom_title_bar.png" width="320" /></a></div>
<br />
Now you have your own custom title. On the surface, it doesn’t actually feel like a title bar, and yes, it isn’t. It’s just a custom view, that you are trying to make it look like a title bar. Remember!! We switched off the titles by specifying that our app’s theme to “NoTitleBar”. <img alt=":)" class="wp-smiley" src="http://castlerockresearch.in/blog/dev/wp-includes/images/smilies/icon_smile.gif" /> <br />
You can find the whole <a href="http://code.google.com/p/myandroidwidgets/source/browse/#svn/trunk/TitleWidgetSample" target="_blank">source code here</a>.Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com0tag:blogger.com,1999:blog-1474889468959966316.post-72766554221617940512011-06-24T16:12:00.000+05:302011-06-25T05:48:30.992+05:30Simple canvas-based Ball gameThis is a small project that does this.<br />
<br />
<blockquote><i style="color: #38761d;">"On your phone's screen, you will have a ball lying at the bottom part, in the middle. Once you touch any part of the screen, the ball starts moving in that direction. It continues to move till it hits one of the walls, bounces off the wall, and keeps moving. Depending on the point of touch, the ball will hit the left/right walls a few times, before it eventually escapes out of the view when it crosses the upper boundary." </i></blockquote> Not super fancy stuff or algorithms. You can find the <a href="http://code.google.com/p/myandroidwidgets/source/browse/#svn%2Ftrunk%2Fsample_ball_game">source code here</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE0XCjSB35F7MrTka7MyuBG_o6vfirJD9Y4_9RPXs-EE1NwxTc4CfJeynGoY9epYONxXQjUGLJUCLyjLUjww1J0vN8kkO6FMbPBSsmDU3jAeIft311HwC7-AtDPysOSqy7d3I1i-msWWvD/s1600/sample_ball_game_android.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE0XCjSB35F7MrTka7MyuBG_o6vfirJD9Y4_9RPXs-EE1NwxTc4CfJeynGoY9epYONxXQjUGLJUCLyjLUjww1J0vN8kkO6FMbPBSsmDU3jAeIft311HwC7-AtDPysOSqy7d3I1i-msWWvD/s400/sample_ball_game_android.png" width="270" /></a></div>Anonymoushttp://www.blogger.com/profile/16335275017896132892noreply@blogger.com2