Saturday 17 March 2012

In Android how to show error in EditText

To display input error on in edit text .



















Create a main.xml layout with a EditText box and a Button.
Main.xml
<?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">  
        <EditText android:id="@+id/editText1" 
                           android:layout_height="wrap_content"  
                           android:layout_width="match_parent" 
                           android:hint="Username"  
       / >  
        <Button android:id="@+id/button1" 
                        android:text="Register for Push Notification"  
                        android:layout_height="wrap_content" 
                        android:layout_width="wrap_content"
                  android:onClick="ErrorCheck"
                  android:text="Test It !!"
        />  
</LinearLayout> 







Now write a method in your activity "ErrorCheck" that is declired in main.xml file on Button Click .To display error you just need to check the error condition and editText.setError("your error message");
public class MainActivity extends Activity { 
EditText editText;
@Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        editText= (EditText) findViewById(R.id.editText1);
    }  
public void ErrorCheck(View v){
if(editText.getText().length()==0){
          editText.setError("Please input text");
        }
}
}






Enjoy.... 
Do post your doubts, queries or suggestions in this blog.

Saturday 3 March 2012

Implementing Push Notifications Client for Android with C2DM


Implementing your C2DM Client :

C2DM Client(Android):

First we are going to implement our client side. It will receive the message from Google server and show a notification on the status bar Currently this code will show a notification on the status bar . In the C2DM client we need to provide the registered eMail id to get the Registration key for the client .
Go to the link and register your e-mail id with your application Package name (Do remember the Package name its very important )
http://code.google.com/android/c2dm/signup.html

You will receive a mail from C2DM giving your C2DM account status.
The most important part is the AndroidManifest.xml be vary careful while making changes .

src/

C2DMRegistration.java

public class C2DMRegistration { public static final String EXTRA_SENDER = "sender"; public static final String EXTRA_APPLICATION_PENDING_INTENT = "app"; public static final String REQUEST_UNREGISTRATION_INTENT = "com.google.android.c2dm.intent.UNREGISTER"; public static final String REQUEST_REGISTRATION_INTENT = "com.google.android.c2dm.intent.REGISTER"; public static final String LAST_REGISTRATION_CHANGE = "last_registration_change"; public static final String BACKOFF = "backoff"; public static final String GSF_PACKAGE = "com.google.android.gsf"; public static final String TAG = "REGISTRATION FOR C2DM"; // package static final String PREFERENCE = "com.google.android.c2dm"; public static long DEFAULT_BACKOFF = 3000; /** * Initiate c2d messaging registration for the current application */ public static void register(Context context ) { String mailId=context.getString(R.string.email_id); Intent registrationIntent = new Intent(REQUEST_REGISTRATION_INTENT); registrationIntent.setPackage(GSF_PACKAGE); registrationIntent.putExtra(EXTRA_APPLICATION_PENDING_INTENT, PendingIntent.getBroadcast(context, 0, new Intent(), 0)); registrationIntent.putExtra(EXTRA_SENDER, mailId); context.startService(registrationIntent); // TODO: if intent not found, notification on need to have GSF } /** * Unregister the application. New messages will be blocked by server. */ public static void unregister(Context context) { Intent regIntent = new Intent(REQUEST_UNREGISTRATION_INTENT); regIntent.setPackage(GSF_PACKAGE); regIntent.putExtra(EXTRA_APPLICATION_PENDING_INTENT, PendingIntent.getBroadcast(context, 0, new Intent(), 0)); context.startService(regIntent); } /** * Return the current registration id. * * If result is empty, the registration has failed. * * @return registration id, or empty string if the registration is not complete. */ public static String getRegistrationId(Context context) { final SharedPreferences prefs = context.getSharedPreferences( PREFERENCE, Context.MODE_PRIVATE); String registrationId = prefs.getString("dm_registration", ""); return registrationId; } public static long getLastRegistrationChange(Context context) { final SharedPreferences prefs = context.getSharedPreferences( PREFERENCE, Context.MODE_PRIVATE); return prefs.getLong(LAST_REGISTRATION_CHANGE, 0); } static long getBackoff(Context context) { final SharedPreferences prefs = context.getSharedPreferences( PREFERENCE, Context.MODE_PRIVATE); return prefs.getLong(BACKOFF, DEFAULT_BACKOFF); } static void setBackoff(Context context, long backoff) { final SharedPreferences prefs = context.getSharedPreferences( PREFERENCE, Context.MODE_PRIVATE); Editor editor = prefs.edit(); editor.putLong(BACKOFF, backoff); editor.commit(); } // package static void clearRegistrationId(Context context) { final SharedPreferences prefs = context.getSharedPreferences( PREFERENCE, Context.MODE_PRIVATE); Editor editor = prefs.edit(); editor.putString("dm_registration", ""); editor.putLong(LAST_REGISTRATION_CHANGE, System.currentTimeMillis()); editor.commit(); } // package static void setRegistrationId(Context context, String registrationId) { final SharedPreferences prefs = context.getSharedPreferences( PREFERENCE, Context.MODE_PRIVATE); Editor editor = prefs.edit(); editor.putString("dm_registration", registrationId); editor.commit(); } }


C2DMBaseReceiver.java
public abstract class C2DMBaseReceiver extends IntentService { private static final String C2DM_RETRY = "com.google.android.c2dm.intent.RETRY"; public static final String REGISTRATION_CALLBACK_INTENT = "com.google.android.c2dm.intent.REGISTRATION"; private static final String C2DM_INTENT = "com.google.android.c2dm.intent.RECEIVE"; // Logging tag private static final String TAG = "C2DM"; // Extras in the registration callback intents. public static final String EXTRA_UNREGISTERED = "unregistered"; public static final String EXTRA_ERROR = "error"; public static final String EXTRA_REGISTRATION_ID = "registration_id"; public static final String ERR_SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE"; public static final String ERR_ACCOUNT_MISSING = "ACCOUNT_MISSING"; public static final String ERR_AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED"; public static final String ERR_TOO_MANY_REGISTRATIONS = "TOO_MANY_REGISTRATIONS"; public static final String ERR_INVALID_PARAMETERS = "INVALID_PARAMETERS"; public static final String ERR_INVALID_SENDER = "INVALID_SENDER"; public static final String ERR_PHONE_REGISTRATION_ERROR = "PHONE_REGISTRATION_ERROR"; // wakelock public static final String WAKELOCK_KEY = "C2DM_LIB"; public static PowerManager.WakeLock mWakeLock; public String senderId; /** * The C2DMReceiver class must create a no-arg constructor and pass the * sender id to be used for registration. */ public C2DMBaseReceiver(String senderId) { // senderId is used as base name for threads, etc. super(senderId); this.senderId = senderId; } /** * Called when a cloud message has been received. */ public abstract void onMessage(Context context, Intent intent); /** * Called on registration error. Override to provide better error messages. * * This is called in the context of a Service - no dialog or UI. */ public abstract void onError(Context context, String errorId); /** * Called when a registration token has been received. */ public void onRegistered(Context context, String registrationId) throws IOException { // registrationId will also be saved } /** * Called when the device has been unregistered. */ public void onUnregistered(Context context) { } @Override public final void onHandleIntent(Intent intent) { try { Context context = getApplicationContext(); if (intent.getAction().equals(REGISTRATION_CALLBACK_INTENT)) { handleRegistration(context, intent); } else if (intent.getAction().equals(C2DM_INTENT)) { onMessage(context, intent); } else if (intent.getAction().equals(C2DM_RETRY)) { C2DMRegistration.register(context); } } finally { // Release the power lock, so phone can get back to sleep. // The lock is reference counted by default, so multiple // messages are ok. // If the onMessage() needs to spawn a thread or do something else, // it should use it's own lock. mWakeLock.release(); } } /** * Called from the broadcast receiver. Will process the received intent, * call handleMessage(), registered(), etc. in background threads, with a * wake lock, while keeping the service alive. */ static void runIntentInService(Context context, Intent intent) { if (mWakeLock == null) { // This is called from BroadcastReceiver, there is no init. PowerManager pm = (PowerManager) context .getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); } mWakeLock.acquire(); // Use a naming convention, similar with how permissions and intents are // used. Alternatives are introspection or an ugly use of statics. //String receiver = "com.android.aspark.notification.C2DMReceiver"; String receiver = context.getPackageName() + ".C2DMReceiver"; intent.setClassName(context, receiver); context.startService(intent); } public void handleRegistration(final Context context, Intent intent) { final String registrationId = intent .getStringExtra(EXTRA_REGISTRATION_ID); String error = intent.getStringExtra(EXTRA_ERROR); String removed = intent.getStringExtra(EXTRA_UNREGISTERED); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "dmControl: registrationId = " + registrationId + ", error = " + error + ", removed = " + removed); } if (removed != null) { // Remember we are unregistered C2DMRegistration.clearRegistrationId(context); onUnregistered(context); return; } else if (error != null) { // we are not registered, can try again C2DMRegistration.clearRegistrationId(context); // Registration failed Log.e(TAG, "Registration error1 " + error); onError(context, error); if ("SERVICE_NOT_AVAILABLE".equals(error)) { long backoffTimeMs = C2DMRegistration.getBackoff(context); Log.d(TAG, "Scheduling registration retry, backoff = " + backoffTimeMs); Log.i(TAG, "Registration retrying "); Intent Intent = new Intent(C2DM_RETRY); PendingIntent PIntent = PendingIntent .getBroadcast(context, 0 /* requestCode */, Intent, 0 /* flags */); // AlarmManager am = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); Log.i(TAG, "Starting Alarm "); am.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+backoffTimeMs, PIntent); Log.e(TAG," allerm set on "+ backoffTimeMs); // // Next retry should wait longer. backoffTimeMs*=2; C2DMRegistration.setBackoff(context, backoffTimeMs); } } else { try { onRegistered(context, registrationId); C2DMRegistration.setRegistrationId(context, registrationId); } catch (IOException ex) { Log.e(TAG, "Registration error2 " + ex.getMessage()); } } } }


C2DMBroadcastReceiver.java
public class C2DMBroadcastReceiver extends BroadcastReceiver { @Override public final void onReceive(Context context, Intent intent) { // To keep things in one place. C2DMBaseReceiver.runIntentInService(context, intent); setResult(Activity.RESULT_OK, null /* data */, null /* extra */); } }

C2DMReceiver.java
public class C2DMReceiver extends C2DMBaseReceiver { public static String registrationID=null; public C2DMReceiver() { // Email address currently not used by the C2DM Messaging framework super("xxx"); } /* (non-Javadoc) * @see com.android.aspark.notification.C2DMBaseReceiver#onRegistered(android.content.Context, java.lang.String) */ @Override public void onRegistered(Context context, String registrationId) throws java.io.IOException { registrationID=registrationId; Log.e("C2DM", "Registration ID arrived: Fantastic!!!"); Log.e("C2DM", registrationId); //--------------------server call------------------------------------ String buildVersion = Build.VERSION.RELEASE; Log.i("device type", deviceType ); }; /* (non-Javadoc) * @see com.android.aspark.notification.C2DMBaseReceiver#onMessage(android.content.Context, android.content.Intent) */ @Override public void onMessage(Context context, Intent intent) { String action = intent.getAction(); // On Notification recived extract the Message // "Payload".............................. Log.w("C2DM", "Message Receiver called"); if ("com.google.android.c2dm.intent.RECEIVE".equals(action)) { Log.w("C2DM", "Received message"); // extracting the payload data with key value ........... final String payload = intent.getStringExtra("payload"); // expecting a unique notification id from server....................... final int notificationID=Integer.parseInt(intent.getStringExtra("notificationid")); } Log.d("C2DM", "dmControl: payload = " + payload); Log.d("C2DM", "dmControl: notificationID = " + notificationID); //Auto incrementing for testing // Note: Send this to my application server to get the real data // Lets make something visible to show that we received the message createNotification(context, payload,notificationID); } Log.e("C2DM", "Message Recived : Fantastic!!!"); } @Override public void onError(Context context, String errorId) { Log.e("C2DM", "Error occured!!!"); } /** * ---------------Displaying Notification on status bar --------------------- * @param context * @param payload */ public void createNotification(Context context, String payload,int notificationID) { String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); int icon = R.drawable.notification_icon; CharSequence tickerText = "New Message"; long when = System.currentTimeMillis(); Notification notification = new Notification(icon, tickerText, when); CharSequence contentTitle = ""; CharSequence contentText = payload; Intent notificationIntent = new Intent(this,OnMessageReceiveActivity.class); notificationIntent.putExtra("payload", payload); notificationIntent.putExtra("notificationid", ""+notificationID); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); mNotificationManager.notify(notificationID, notification); } }

OnMessageReceiveActivity.java
public class OnMessageReceiveActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.onmessagereceiveactivity); } }




RegisterActivity.java

public class RegisterActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void register(View view) { Log.e("Super", "Starting registration"); Toast.makeText(this, "Starting", Toast.LENGTH_LONG).show(); C2DMRegistration.register(this); } }




res/

onmessagereceiveactivity.xml

<?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"> <TextView android:id="@+id/editText1" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="You are in new activity" ></TextView> </LinearLayout>

main.xml

<?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"> <Button android:id="@+id/button1" android:text="Register for Push Notification" android:layout_height="wrap_content" android:onClick="register" android:layout_width="wrap_content"></Button> </LinearLayout>


AndroidManifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="YOUR_PACKAGE_NAME" android:versionCode="1" android:versionName="1.0" > <permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" /> <!-- Permissions --> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_CORSE_LOCATION"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".RegisterActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".OnMessageReceiveActivity"/> <service android:name=".C2DMReceiver" /> <!-- Only C2DM servers can send messages for the app. If permission is not set - any other app can generate it --> <receiver android:name=".C2DMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <!-- Receive the actual message --> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="YOUR_PACKAGE_NAME" /> </intent-filter> <!-- Receive the registration id --> <intent-filter> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="YOUR_PACKAGE_NAME" /> </intent-filter> </receiver> <receiver android:name=".C2DMBroadcastReceiver" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RETRY"/> <category android:name="YOUR_PACKAGE_NAME" /> </intent-filter> </receiver> </application> </manifest>

You need to declare few more things
Value ->
String :
<string name="email_id"></string> 

DRAWABLE:
1.notification_icon.png 




Now you can run your Android Client , in response you will get the auth KEY( hash value ) . Check your LogCat  .Do not change the permission and package name in manifest file.

*It will show the notifications on the status bar with a fixed message ,it will not show the message that is sent from the server side.
*for server side check my other post .C2DM Server.
*For C2DM details go to C2DM Push notification for Android
Enjoy.... 
Do post your doubts, queries or suggestions in this blog.




C2DM Push notification for Android


Cloud to device messaging
Android Cloud to Device Messaging (C2DM) is a service that helps developers send data from servers to their applications on Android devices. The service provides a simple, lightweight mechanism that servers can use to tell mobile applications to contact the server directly, to fetch updated application or user data. The C2DM service handles all aspects of queuing of messages and delivery to the target application running on the target device. In a C2DM you have three involved parties. The application server which wants to push messages to the Android device, Googles C2DM servers and the Android app. The program on the application server can be written in any programming language, e.g. Java, PHP, Python, etc
When the application server needs to push a message to the Android application, it sends the message via an HTTP POST to Google’s C2DM servers.
The C2DM servers route the message to the device. If the device is not online, the message will be delivered once the device is available. Once the message is received, an Broadcast Intent is created. The mobile app has registered an Intent Receiver for this Broadcast. The app is started and processes the message via the defined Intent Receiver.
C2DM messages are limited in size to 1024 bytes and are intended to inform the device about new data not to transfer it. The typical workflow is that Googles C2DM servers notify the Android app that new data is available. Afterwards the Android app fetches the data from a different server.
Android maintain an connection to the Android Marketplace. C2DM uses this existing connections to the Google servers. This connection is highly optimize to minimize bandwidth and battery consumption.
C2DM is currently still in beta and you need to apply to use it. C2DM applies a limit of approximately 200 000 messages per sender per day and is currently free of charge.
To start with C2DM you need to register a Gmail ID through which your notifications will be sent signup page

#  Polling  vrs. Push

Polling architectures, as pervasive as they are today, did not come about due to their efficiency. Whether you are maintaining a popular endpoint (Twitter), or trying to get near real-time news (RSS), neither side benefits from this architecture. Over the years we've built a number of crutches in the form of Cache headers, ETags, accelerators, but none have fundamentally solved the problem -because the client remains 'dumb' the burden is still always on the server. For that reason, it's worth paying attention to some of the technologies which are seeking to reverse this trend

PUSH architectures, are nothing more but a means to push information to the end-device without the end-device having to maintain a persistent connection with the server, thus lowering the bandwidth and resources of the solution. Live APPS Push architectures reduces the cost for Network Operators as end-devices does not need to maintain a persistent connection with the WAP Proxy.

#  Requirements

C2MD is available as of Android 2.2 and requires that Android Market application is installed on the device.
To use C2DM on the Android simulator you also need to use a Google device with API 8 or higher and to register with a Google account on the emulator via the Settings.

#  Permissions

To use C2DM in your application to have to register for the following permissions
·         com.google.android.c2dm.permission.RECEIVE
·         android.permission.INTERNET
Your application should also declare the permission "applicationPackage + ".permission.C2D_MESSAGE" with the "android:protectionLevel" of "signature" so that other applications cannot register and receive message for the application. [android:protectionLevel="signature" ] ensures that applications with request a permission must be signed with same certificate as the application that declared the permission.

#  Intent Receiver

Your application must register an intent receiver for the two intents:
·         com.google.android.c2dm.intent.REGISTRATION
·         com.google.android.c2dm.intent.RECEIVE
The receiver for "com.google.android.c2dm.intent.RECEIVE" will be called once a new message is received, while the receiver for "com.google.android.c2dm.intent.REGISTRATION" will be called once the registration code for the app is received.

Limitations

C2DM imposes the following limitations:
  • The message size limit is 1024 bytes.
  • Google limits the number of messages a sender sends in aggregate, and the number of messages a sender sends to a specific device. Please refer to the section on quotas for more information.


Enjoy.... 
Do post your doubts, queries or suggestions in this blog.