Tuesday, September 11, 2012

Gully Cricket Scorer - Cricket scoring android app

After a long time i am posting in my blog.
I had recently wrote an android app to score for your own cricket matches. If you have friends playing cricket professionally or street crickets for fun,please share with them. Any feedbacks are welcome. If you are use android phone, just type "gullycricket" in Play store, you would see my app with my name (Manii) . Other platform users please ignore. Thanks.

https://play.google.com/store/apps/details?id=com.gullycricket ( free )



Gully Cricket Scorer is a scoring app for your own cricket matches.Use it for street cricket , school cricket or league cricket or T20 matches and save the hassles of maintaining a scoring paper.Its easy for umpires to use the app after each ball to maintain scores while umpiring. With just a click on the ball decide whats the outcome of the ball.

In paid app, unlimited overs target can be set, organise match and send invites to players over email and facebook, add more number of teams.
* Maintain list of Teams and Team Players
* Add new teams and player on the fly , no initial setup setup needed. Click "New Game" and you are good to go.
* Match details is saved after every ball,so continue your pending game at any time. * View pending match details and completed match details.
* Maintain ball-by-ball scoring details.
* Means to adjust scores after scoring the ball in case of a scoring error.
* Post the completed match scorecard to facebook.
###############################################################

Sunday, January 8, 2012

Instant Share - Share current location to twitter, facebook, SMS



Instant share help you share you current location and you status to twitter and facebook instantly from home screen widget.

* Provides 2x2, 4x2 home screen widgets, which keeps updating your current location with a static google map.
* You can turn ON/OFF whether widget needs to keep track of you movement and updating the google map.
* Clicking on the google map launches a small screen which lets you navigate the current location in google mapview.
* Basically zoom in / zoom out the current location, pan around the current location.
* Gives options to share current location to you TWITTER, FACEBOOK accounts.
* Also share the current location to yours friends through SMS.
* Prodives a tiny url in update status message to see in more detailed mapview to all your friends where you are currently located.
* Widgets are handly and quite useful. 2x2 and 4x2 gives you an option to keep your widgets compact at necessary place in workspace.

Please let me know your feedbacks and if any improvements.




Thursday, January 5, 2012

How to write custom CheckBox View?

Many would be interested in writing custom Checkbox in aligning to the theme of the application. For instance changing the checkbox background color and tick color.

You can do in many ways, one usual way is to define a drawables for different states and use selector resource to pick the right image for different states of checkbox.
and set the selector resource as background drawable to CheckBox.In this you need to have different sets of images.

This implementation is about having only two states, checked and not checked. ( basically meaning, how this widget behaves touched and touched again). My requirement was to have tick mark extending outside the checkbox square. Something like this.



So i planned to write a custom view, doing this job for me.

This implementation doesnt include flexible width, height for the checkbox. If you want to do so, use AttributeSet in the constructor and take the height and width from XML attributes and use those values in setMeasuredDimension().

- Written a custom View, a class extending 'View' class and drawing necessary things required to bring the checkbox effect.
- Since I needed 'tick' mark to cross the boundary of checkbox square, i have drawn the checkbox rectangle within View's boundary ( with rectangle width and height is set lesser than View's rectangle ), after drawing the checkbox rectangle then drawn the tick mark image which was positioned in such a way to occupy the entire View rectangle.

View Rect and CheckBox square Rect:



Tick Mark:




- I have given harcoded values of 48,48 for checkboxView,you can change this by gettin g values from xml.
- Overriden onTouchEvent() to know when to draw the tickmark and when not to draw the tick mark. Its a simple check with boolean variable.

- Provided a interface onCheckedChange() to let users listen for checkbox change events.

public interface onCheckedChange {
void onCheckClick(View v);
}

public void setChecklistener(onCheckedChange );

checkBoxView.java
--------------------



import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;

public class CheckBoxView extends View{

public interface onCheckedChange {
void onCheckClick(View v);
}
boolean isTouchDown = false;
Bitmap mTick;
Rect mViewRect;
Rect mCheckboxRect;
Paint mPaint;
int mHeight;

public CheckBoxView(Context context) {
super(context);
}

public CheckBoxView(Context context,AttributeSet attrs) {
super(context,attrs);
mTick = BitmapFactory.decodeResource(context.getResources(), R.drawable.tick);
DisplayMetrics metrics = new DisplayMetrics();
((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metrics);
mHeight = metrics.heightPixels;
if(mHeight == 320 || mHeight == 240) {
mViewRect = new Rect(0,0,32,32);
mCheckboxRect = new Rect(0,12,25,32);
} else {
mViewRect = new Rect(0,0,48,48);
mCheckboxRect = new Rect(0,20,38,48);
}
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.rgb(0x60,0x33,0x11));
}

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
if(mHeight == 320 || mHeight == 240)
setMeasuredDimension(32,32);
else
setMeasuredDimension(48,48);
}

public boolean isChecked() {
return isCheckDrawn;
}

public void setCheckBox(boolean draw) {
isCheckDrawn = draw;
invalidate();
}
private onCheckedChange mCB = null;
public void setChecklistener(onCheckedChange aCB) {
mCB = aCB;
}

int currX;
boolean isMovementDetected = false;
boolean isCheckDrawn = false;

public boolean onTouchEvent(MotionEvent event) {

int pointerX = (int) event.getX();
int pointerY = (int) event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(mCheckboxRect.contains(pointerX, pointerY) == true)
isTouchDown = true;
break;
case MotionEvent.ACTION_MOVE:
currX = (int) event.getX();
int deltaX = Math.abs(currX - pointerX);

if(deltaX > ViewConfiguration.getTouchSlop())
{
isMovementDetected = true;
}

break;
case MotionEvent.ACTION_UP:
if(isMovementDetected == false && isTouchDown == true) {
if(isCheckDrawn == false) {
isCheckDrawn = true;
} else {
isCheckDrawn = false;
}
if(mCB != null)
mCB.onCheckClick(this);
invalidate();
isTouchDown = false;
}
isMovementDetected = false;
break;
}
return true;
}

public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(mRect1, mPaint);
if(isCheckDrawn == true) {
canvas.drawBitmap(mTick, null, mRect, null);
}
}
}



Example usage of checkBoxView:
-------------------------------

Wednesday, November 30, 2011

how to write app Widgets - Home screen widgets ? How to implement different sized home screen widgets?

Recently i gave a presentation in google office singapore for gtug-ph-sg android community about Layouts and Home screen widgets.

http://gtug-ph-sg.blogspot.com/2011/11/android-talk-update.html

So i wished to share more details about how to write home screen widgets.
Also when i attended a google dev talk here happened on nov27th, the key steps to keep a user engaged in keeping your application is

1 - Write home screen widget and keep the user bsy in refreshing the data on widget
2 - Push notifications then and there so that user has not forgotten your application.

So we home screen widget is one way you can keep user bsy with your application. Lets go into the details.

* What is an AppWidget ?

* AppWidget framework

* Steps for creating an AppWidget

* Example demonstrating widget showing google static map of location as home screen widget.


AppWidget:

- AppWidget is a android techinical terminology for "Home screen widgets". What is said in developers guide is "App Widgets are miniature application views that can be embedded in other applications (such as the Home screen) and receive periodic updates."
-AppWidget is a representation of an Android application on the home screen. The application can decide, what representative information it publishes on the home screen



- Home screen widgets are quick glimpse of the fully functional apps like calendar,music,weather applicaiton. Users can quickly get live data from an application.Live data i mean, widgets can keep refreshing the data based on location,time basis, or per schedule input from user.

- Widgets let users interact with the widgets like slide the images like in gallery, scroll the weather data, play,pause songs..etc.






RemoteViews and Launcher:

Before diving into how to implement app widgets, we should be aware of how the appWidgets mechanism works and what are remoteviews ?

How does Launcher (i.e Home screen provider) able to show a view created by another application in its UI ? Functionality and design of the widget is defined by one application but UI of the widget is hosted in another application (Launcher). What would help us achieving this ? Basically we need an IPC mechanism here. Inter process communication. One process sending the UI data to another process Launcher to display in it.

Remoteviews helps in solving this and is the key behind appwidget framework. Remoteviews are parcelable data strucutre that holds information about a view hierarchy and can be transferred from one process to another. Any process can recieve this RemoteView instance via IPC and get a "View" instance from it and add to its Layout and be part of receving process. The creator of remoteview can define actions for the elements in remoteview like what should happen when a button is pressed. Receiving process cannot change these properties, they can only get a view instance and host it.

So who sends remoteviews and how does Launcher communicates with creator.

- AppWidgets framework includes implementing AppWidgetProvider class which is a broadcast receiver which would receive events of when an AppWidget is added to homescreen or deleted from homescreen.

- Launcher is the guy who sends these broadcasts when the appWidgets are added to the home screen with an AppWidgetID

- AppWidgetProvider then sends an RemoteView with the AppWidgetId, which would be then be received by Launcher and Launcher updates the corresponding appWidget with that remoteView.




AppWidget FrameWork

Now lets see the four necessary things involved in creating appWidgets.

* App Widget Provider Metadata XML file

* AppWidgetProvider class

* View layout

* App Widget configuration Activity (Optional)


App Widget Provider Metadata XML file

* Describes the metadata for an App Widget, such as minimum width, minimum height, update frequency, the AppWidgetProvider class.
* It also references App widget's layout file
* This should be defined in res/xml folder.

AppWidgetProvider class

* Defines the basic methods that allow you to programmatically interface with the App Widget, based on broadcast events. (AppWidgetProvider class is a child class of BroadcastReceiver class.)
* Through it, you will receive broadcasts when the ApWidget is updated, enabled, disabled and deleted

View layout

* Intial layout to be displayed when the appWidget is added to the homescreen. It is defined in metadata XML file.

App Widget configuration Activity

* This is an optional activity which users can define to show to the users before adding the appWidget to homescreen.Usually useful in collecting some values required for your appWidget settings.

Building an AppWidget

* Declare an AppWidgetProvider in the Manifestfile

* Create the App Widget Provider Info Metadata XML file

* Create the App Widget Layout XML file

* Write the AppWidgetProvider Class

1 - Declare AppWidgetProvider in Manifest





android:resource="@xml/example_appwidget_info"/>



2 - Create App Widget Provider Info Metadata XML file


xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"  --> Every one day
android:initialLayout="@layout/example_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigure" >



Some of the attributes are added newly in android 3.0
previewImage --> Added in android 3.0
android:previewImage="@drawable/preview"

More details take look at http://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo.html

3 - Create App Widget Layout

* App Widget layouts are based on RemoteViews,which do not support every kind of layout or view widget.

* A RemoteViews object (and, consequently, an App Widget) can support the following layouts and Widget classes
FrameLayout, LinearLayout, RelativeLayoyt
AnalogClock, Button, Chronometer, ImageButton,
ImageView, ProgressBar, TextView

* Android 3.0 supports additional widgets
ListView
GridView
StackView
AdapterViewFlipper

4 - Write AppWidgetProvider Class

* The AppWidgetProvider class extends BroadcastReceiver to handle the App Widget broadcasts. The AppWidgetProvider receives only the event broadcasts that are relevant to this App Widget, such as when the App Widget is updated, deleted, enabled, and disabled. 

Methods to override

onUpdate(Context, AppWidgetManager, int[]) - called
when each App Widget is added to a host (unless you use a configuration Activity), Typically the onlymethod that needs to be present

onDeleted(Context, int[])

onEnabled(Context)

onDisabled(Context)

onReceive(Context, Intent)

Screenshot showing demo of adding Digital and analog clock in Home screen:





AppWidget provider - onUpdate

There are certain few points about AppWidget Provider behaviour we need to know.

* First is , android:updatePeriodMillis="86400000" which defines the frequency when the appWidget will be updates. Meaning on this schedule, onUpdate on AppWidget Provider class will be called. The restriction with this timing is the minimum period is 30mins. You cannot give 10000 and except the onUpdate() to be called every 10 secs. Minimum time period is 30 mins.

* Because AppWidgetProvider is an extension of BroadcastReceiver, your process is not guaranteed to keep running after the callback methods returns i.e onUpdate,onEnabled.
So in case, you need to perform some network communication to fetch some data

* Consider starting a Service in the onUpdate() method. And delegate the network communication work to a asynchronous task and update the widget with the result.

* To update an appWidget all you need to know is AppWidgetId and have AppWidgetManager instance. So ideally pass all the appWidgetIds to "service" i.e whenever onUpdate() is triggered call startService() with appWidgetIds as intent data and ask the service to update the widgets with data fetched from network.
appWidgetManager.updateAppWidget(appWidgetId, views);

Now how to do we change the updatePeriodMillis to trigger onUpdate before 30mins.

* Use AlarmManager to update.In onUpdate() when the first time appWidget is added, set a setRepeating alarm for the schedule you wish and pass an pendingIndent to launch the service. In service you can update the appWidgets with appWidgetids and remoteview.


final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
final Intent intent = new Intent(context, MyService.class);  
if (service == null)  
{  
service = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
}  
m.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 1000 * 60, service); 


More details take a look at this post
http://www.parallelrealities.co.uk/2011/09/using-alarmmanager-for-updating-android.html

Multiple sized widgets :

- How do we support multiple sized widgets ? 4x1,4x2,2x1 there are maximum of 4 rows and 4 columns. 4x4 in handsets and tablets support upto 8x7.
Here is one of the way you can achieve this.

- Declare as many AppWidgetProviderInfo metafiles required
2x2 :
android:minWidth="147dp"
android:minHeight="142dp"
4x2 :
android:minWidth="294dp"
android:minHeight="142dp"

- Define corresponding Appwidget classes.

- Declare corresponding AppWidget Broadcast receivers in AndroidManifest.xml


For more details on the cells calculation, minWidth,minHeight please chk in this link.
http://developer.android.com/guide/practices/ui_guidelines/widget_design.html

Snapshot showing four types of appWidgets for the demo application



Things to keep in mind

* Frequency of update should not be high. ex. every 5 mins.It will reduce the battery life of the phone.

* Handled badly your widget could end up making the phone completely unresponsive. Pushing updates to onscreen widgets is a somewhat costly process.

* Avoid nesting of layouts within a layout.

* Give proper padding. As it might collide with adjacent widget. No boundary seperation would be seen.

* Use a nine patch image as background to support multiple sized widgets

* Offload any webrequest through a service to avoid ANRs.


Demo example of widget showing google static map of location as home screen widget.

Quick points of implementation.

* onEnabled() -> Start a service

* onUpdate() -> Get the appWidgetId and appWidgetType and pass to the service.

* onDeleted() -> Get the appWidgetId and pass to the service.

* Service -> Listens for movement change using PhoneStateListener and fetches current location using GPS or Wifi and downloads the static map as Bitmap  and updates the widgets 2x2 and 4x2.

I am not giving in detail explanation of the code. Please go through this block diagram which will give you high level overview. You can go through the code for more details Any queries u can drop me a comment..!!

Implementation overview:







http://code.google.com/apis/maps/documentation/staticmaps/

Demo code:
The entire source code for the demo can be downloaded from the below link.
http://www.4shared.com/get/_FeDVgpD/HomescreenWidget.html

Sunday, November 20, 2011

LocalGuide - A map application with home screen widget.

Spent a bit of my free time in finishing a app named localguide..I have uploaded in market....!! It is there in OVI store as well.( it was quite old).

if u like the description and preview ...Please buy it :) and give ur feedbacks/comments :) if any improvements i will make sure ur issues are addressed over updates...!!

https://market.android.com/details?id=com.mani.localguide

http://www.youtube.com/watch?v=4-C_rK2lrow&feature=feedu

And if u felt useful... plss fwd to ur friends...!!

Description:
How many times we get stuck in a new place and call our friends to get directions to pubs, restaurants nearby and still be in an endless search.
Localguide puts an end to all this endless searches.

* LocalGuide takes two short keywords and directs you to the place you want to go with detailed map directions.
* It provides you the complete addresses, phone numbers, maps location. It identifies your location using GPS or Wifi.
* Make a call instantly.
* Send SMS/message the result to your friends right away.
* Update twitter,facebook status with the result informing (where you are presently ).
* Get directions to the place with neat and simple step by step instructions with clear paths shown using google map view.
* Bookmark your favourite Places and store them for fast consultation when in offline usage

A LITTLE ANIMATIONS are added during screen transitions.

Home Screen Widgets:

Localguide provides one of the interesting additional features is home screen widgets which has

* Support for 4x1 and 4x2 resolutions. Please see the previews.
* Provides instant results of your interested categories around your current location in home screen.
* Widgets has the capability to keep listening for your movement and detects the location automatically and refreshes the results.
* If in case you dont want to scan for your location movement, you quickly turn of the MOVEMENT DETECTION button on the widget.
* Multiple widgets can be added to display results for different categories.
EX: One widgets collects results for restuarants, one collects for theatres.
* Widgets provides an one button click option for calling and sharing through sms.
* Also provided favorite button which takes you to the favorites page to quickly get to your favorite destination.

Widgets are handly and quite useful. 4x1 and 4x2 gives you an option to keep your widgets compact at necessary place in workspace.

Any improvements pls mail me - smanikandan14@gmail.com











Friday, July 8, 2011

How to perform entry animations for listview.

From my work related learnings, i would like to share the three ways of doing entry animation for listview elements.


1 - LayoutAnimation Controller
This controller is viewgroup animation controller means, it will apply animation to each of the child added to a view group. When this controller is set to the listview
it animates each listviews items. So that you can have entry animation for listview.

But the drawback is this controller will apply the animation to the listview items only for very first time this layout is drawn/shown. The next time when you do
hide / show the layout, you cannot expect the listview to have its element animated.

2 - So the second approach i tried is over riding the onvisibilitychanged() api of Layout class where your listview is added.check for visibility,if someone made the layout visible then this the right place to perform the animation on each views of listview. Use getChildAt() api to get the listview items and start a animation on each view. So you get a entry animation for listview whenever, this layout is made visible. You can also write a exit animation and start when visibility == INVISIBLE


protected void onVisibilityChanged (View changedView, int visibility)
{
super.onVisibilityChanged(changedView,visibility);
if(visibility == View.VISIBLE) {
startEnterAnimation();
}
}

public void startEnterAnimation() {

Animation animation;
int offsetTime=0;
for(int i=0;i View view = list.getChildAt(i);
animation = new AlphaAnimation(0.0f,1.0f);
animation.setFillAfter(true);
animation.setDuration(100);
animation.setStartOffset( i * 100);

if(view != null)
{
view.startAnimation(animation);
}
}
}


There is also a limitation in the second approach. Scenario is, what happens before u perform the animation on the listview,there is a change in the data, where in you need to call the notifydatasetchanged api, then u wanted to start the entry animation.
But by the time you start performing the entry animation, notifydatasetchagned api would have layouted out the listview elements.

So we need to start the animation as and when listview items are drawn on the screen. how do we do this ??

Third approach solves this issue.

3 - In the adapter's getview() api, as and when we return the convertView to the framework, start the animation that instance by checiking for a flag,
which will be set to true for the first time listview is shown. Approach looks good, but how do u know when the listview has finished calling all its getview
and drawn its child so that you can make the flag false ??. Here is the solution i have tried, as soon as notifydatasetchanged api is called,

UI thread will have tasks in its messagequeue to perform getview for the count returned by getCount() adapter.so after notifydatasetchanged api is called,
get the handler of listview(which is nothing but UI thread handler) and post a runnable to make the boolean flag false, So that this runnable will be
executed after all the getview() calls are finished for all its child elements. So We know when to make the boolean false at the right instance.


protected void onVisibilityChanged (View changedView, int visibility)
{
super.onVisibilityChanged(changedView,visibility);
if(visibility == View.VISIBLE) {
// Suppose your data is upadted.
mListAdapter.notifyDataSetChanged();
isInitialLayout = true;
listview.getHandler().post(new Runnable() {
public void run() {
isInitialLayout = false;
}
});
}
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.title);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}

holder.title.setText(mData.get(position));

/* Start the animation for this item for the position */
if(isInitialLayout == true ) {
Animation animation = new AlphaAnimation(0.0f,1.0f);
animation.setFillAfter(true);
animation.setDuration(100);
animation.setStartOffset(position * 100);
convertView.startAnimation(animation);
}

return convertView;
}


If there are any other ways of performing the entry animation for a listview in a layout, please let me/everybody know :)

Friday, June 24, 2011

How to calculate lsitview's total element's height

Sometimes we would be interested in finding height of the listview including all the child's height.(including the child which are not visible )

Usually the api listview.getChildCount() returns the count of number of elements which can be seen in the listview's height. But what i am insisting now is finding the height of all the childs of listview a collective height.

we will see how can we find the collective height of all child.

- Get the adapter instance from the listview.
- Get the count of adapter.
- And use adapter's getView(int position,View view,ViewGroup parent) api to get the view instance of all child
elements.
- Then use the measure api of View to measure the height of the view as below. I used here UNSPECIFIED to find out how big the view is.
- This api measures the widht and height. And use the getMeasuredHeight() api to find
the Measured Height.

private int getTotalHeightofListView() {
ListAdapter mAdapter = listview.getAdapter();
int listviewElementsheight = 0;
for(int i =0;i View mView = mAdapter.getView(i, null, listview);
mView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
listviewElementsheight+= mView.getMeasuredHeight();
}
return listviewElementsheight;
}


For additional information on MeasureSpec, taken from
http://developer.android.com/reference/android/view/View.html

MeasureSpecs are used to push requirements down the tree from parent to child. A MeasureSpec can be in one of three modes:

UNSPECIFIED: This is used by a parent to determine the desired dimension of a child view. For example, a LinearLayout may call measure() on its child with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how tall the child view wants to be given a width of 240 pixels.
EXACTLY: This is used by the parent to impose an exact size on the child. The child must use this size, and guarantee that all of its descendants will fit within this size.
AT_MOST: This is used by the parent to impose a maximum size on the child. The child must gurantee that it and all of its descendants will fit within this size."