Mar 30, 2013

Android: Detect Global Touch Event

Sidebar and Glovebox Apps became popular overnight because of only one functionality. They provide global menu which can be opened from left or right edge of the mobile screen.  As a developer, when I show these apps, first thing that comes in my mind was "NDK".  Then, I started looking for the solution.  Logically, I figured out that if I can detect "Global onTouch Event" then it's posible to display side menu like sidebar or glovebox.


 


https://play.google.com/store/apps/details?id=com.fb.glovebox
https://play.google.com/store/apps/details?id=mohammad.adib.sidebar.lite

I was in search of detecting global onTouch event in Android and finally I got success because of Mr. YoungBin Han. He presented one technique to detect global touch event through sidepanel application. In this article, I am explaining simplified code of detecting global event in Android.

Problem 1: Detect Global Touch Event 
Problem 2: Display Sliding Menu.

Solution For Problem 1: 
1. Create service to detect touch event.
2. Fetch WindowManager object from system service
3. Create LinearLayout having 30 px width and fill_parent height
4. Add LinearLayout to WindowManager
5. Set LinearLayout on left edge of screen / window.

Q1 : Why I need to create Service ? 
We can't get event when activity goes in background or closes.

Q2 : What if I make LinearLayout width more then 30 px ?
The control or activity which displays in background will not get onTouch event.

Cyan color is used to make LinearLayout visible.

Let's jump to the code.

Step 1 : Create android project named "Global Touch Event"
Step 2 : Open activity_main.xml and add button to start the service.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:text="Start Touch Detection"
        android:onClick="buttonClicked" />
</RelativeLayout>
Step 3 : Open MainActivity.java and add buttonClicked event to start service.
package com.kpbird.globaltouchevent;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

 Intent globalService;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  globalService = new Intent(this,GlobalTouchService.class);
 }


 public void buttonClicked(View v){
  
  if(v.getTag() == null){
   startService(globalService);
   v.setTag("on");
   Toast.makeText(this, "Start Service", Toast.LENGTH_SHORT).show();
  }
  else{
   stopService(globalService);
   v.setTag(null);
   Toast.makeText(this, "Stop Service", Toast.LENGTH_SHORT).show();
  }
  
 }
}

Step 4 : Create new java class named "GlobalTouchService" which extends Service and implements OnTouchListener. Now create LinearLayout and add it into WindowManager, when user touch on left edge of screen this LinearLayout will detect event. If you want to view LinearLayout just set any color in background or uncomment setBackgroundColor line in following source code.
package com.kpbird.globaltouchevent;

import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;

public class GlobalTouchService extends Service implements OnTouchListener{

 private String TAG = this.getClass().getSimpleName();
 // window manager 
 private WindowManager mWindowManager;
 // linear layout will use to detect touch event
 private LinearLayout touchLayout;
 @Override
 public IBinder onBind(Intent arg0) {
  return null;
 }
 @Override
 public void onCreate() {
  super.onCreate();
  // create linear layout
  touchLayout = new LinearLayout(this);
  // set layout width 30 px and height is equal to full screen
  LayoutParams lp = new LayoutParams(30, LayoutParams.MATCH_PARENT);
  touchLayout.setLayoutParams(lp);
  // set color if you want layout visible on screen
//  touchLayout.setBackgroundColor(Color.CYAN); 
  // set on touch listener
  touchLayout.setOnTouchListener(this);

  // fetch window manager object 
   mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
   // set layout parameter of window manager
   WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(
           30, // width of layout 30 px
           WindowManager.LayoutParams.MATCH_PARENT, // height is equal to full screen
                 WindowManager.LayoutParams.TYPE_PHONE, // Type Phone, These are non-application windows providing user interaction with the phone (in particular incoming calls).
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, // this window won't ever get key input focus  
                 PixelFormat.TRANSLUCENT);      
         mParams.gravity = Gravity.LEFT | Gravity.TOP;   
   Log.i(TAG, "add View");

      mWindowManager.addView(touchLayout, mParams);
  
 }
 

 @Override
 public void onDestroy() {
   if(mWindowManager != null) {
             if(touchLayout != null) mWindowManager.removeView(touchLayout);
         }
  super.onDestroy();
 }
 
 @Override
 public boolean onTouch(View v, MotionEvent event) {
  if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP)
   Log.i(TAG, "Action :" + event.getAction() + "\t X :" + event.getRawX() + "\t Y :"+ event.getRawY());
  
  return true;
 }

}

Step 5 : Open AndroidManifest.xml and register "GlobalTouchService", We also require SYSTEM_ALERT_WINDOW permission to add view in windowmanager.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kpbird.globaltouchevent"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name="GlobalTouchService" >
        </service>
    </application>
</manifest>

Step 6 : Ready to run the app.

Download or Fork Code from GitHub
I will address Problem 2 in my next article.

References
1. http://developer.android.com/reference/android/view/WindowManager.html 
2. http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html
3. https://github.com/sukso96100/SidePanel
4. http://stackoverflow.com/questions/6714020/how-can-a-service-listen-for-touch-gestures-events

continue reading Android: Detect Global Touch Event

Mar 21, 2013

Wish-list for Android 5.0 / Key Lime Pie


As Developer, This is my Wish List for Android 5.0 / Key Lime Pie.



1. File Manager
2. Video Processing API like cut, copy, merge and effects.
3. Image processing, effects, drawing, etc.
4. Video Call with SIP API
5. Slide-in / Fly-in menu
6. Integrated social network like Facebook, twitter and linkedin.
7. Gallery with Multiple File Selection or multi type file selection.
8. Improve Data Backup API for easy cloud storage integration.
9. Native App development using HTML5,CSS3 and JavaScript.
10. Document management API like open office, PDF, ms-office, etc.
11. Chips EditText i.e. Contact selection in Gmail
12. Staggered Grid View [http://www.androidviews.net/2013/01/pinterest-like-adapterview/]
13. Android Annotations [http://www.androidviews.net/2012/11/android-annotations/]
14. Color Picker Control
15. Validation Framework
16. Cards UI, like iOS has in PassBook app
17. Range SeekBar or double headed seek bar
18. Arc Menu - same as Path app
19. Chart API 
20. Improvement in ADK - Accessories development kit API
21. Improvement in DRM - Digital Rights Management API
22. Storyboards tool for fast development i.e. http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1
23. Better Approach for Universal App development (Smartphone & Tablet)
24. Google Cloud Print API should be integrated in OS.





continue reading Wish-list for Android 5.0 / Key Lime Pie

Mar 18, 2013

Android : Login with Facebook SDK 3.0


Introduction
The goal of this article is explain simplest way to use Facebook for Login and fetch user details including Email Address. 

The Facebook SDK for Android is the easiest way to integrate your Android app with Facebook's platform. 

What's new in Facebook SDK 3.0
  • Simplified user session management
  • Better Facebook APIs support
  • Ready-to-Use native UI views
  • Mobile install measurement
Prerequisite
1. Facebook Android SDK 3.0 - Download
2. Facebook API Key from Facebook Application - Detail
3. Hash Key of your debug certificate  - Detail


Step 1 : Create Android Project named "FacebookTest"
Step 2 : Import FacebookSDK in eclipse
Step 3 : Add Reference of Facebook SDK in FacebookTest Project



Step 4 : Add app_id in strings.xml, replace your facebook api key in following code.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">FacebookTest</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="app_id">YOUR_FACEBOOK_API_KEY</string>

</resources>

Step 5 : Add meta-date tag and LoginActivity in AndroidManifest.xml. In this demo I am using LoginButton provided by Facebook SDK, It is also possible to user our native Button for Login. We also require to register LoginActivity. LoginActivity & LoginButton are available in Facebook SDK.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kpbird.facebooktest"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.kpbird.facebooktest.MainActivity"
            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="com.facebook.LoginActivity"
           android:theme="@android:style/Theme.Translucent.NoTitleBar"
           android:label="@string/app_name" />
         <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/app_id"/>
    </application>
</manifest>

Step 6 : Add Facebook Login button in activity_main.xml, Main activity contains TextView and LoginButton. TextView will display user's email address.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

     <TextView
         android:id="@+id/lblEmail"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         android:layout_centerHorizontal="true"
         android:layout_marginTop="144dp"
         android:text="Email ID : "
         android:textAppearance="?android:attr/textAppearanceLarge" />

<com.facebook.widget.LoginButton
         android:id="@+id/authButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         android:layout_centerHorizontal="true"
         android:layout_marginTop="45dp" />

</RelativeLayout>

Step 7 : Open MainActivity.java and write following code. Following is very simple code, you just need to take few importent things 
  • Override onActivityResult to get LoginButton Events
  • Set permission as per your requirement
  • executeMe request to fetch user detail and email
  • fetch email address from user object
package com.kpbird.facebooktest;

import java.util.Arrays;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.facebook.FacebookException;
import com.facebook.Request;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.model.GraphUser;
import com.facebook.widget.LoginButton;
import com.facebook.widget.LoginButton.OnErrorListener;

public class MainActivity extends Activity {

 private String TAG = "MainActivity";
 private TextView lblEmail;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  lblEmail = (TextView) findViewById(R.id.lblEmail);
  
  LoginButton authButton = (LoginButton) findViewById(R.id.authButton);
  authButton.setOnErrorListener(new OnErrorListener() {
   
   @Override
   public void onError(FacebookException error) {
    Log.i(TAG, "Error " + error.getMessage());
   }
  });
  // set permission list, Don't foeget to add email
  authButton.setReadPermissions(Arrays.asList("basic_info","email"));
  // session state call back event
  authButton.setSessionStatusCallback(new Session.StatusCallback() {
   
   @Override
   public void call(Session session, SessionState state, Exception exception) {
    
    if (session.isOpened()) {
              Log.i(TAG,"Access Token"+ session.getAccessToken());
              Request.executeMeRequestAsync(session,
                      new Request.GraphUserCallback() {
                          @Override
                          public void onCompleted(GraphUser user,Response response) {
                              if (user != null) { 
                               Log.i(TAG,"User ID "+ user.getId());
                               Log.i(TAG,"Email "+ user.asMap().get("email"));
                               lblEmail.setText(user.asMap().get("email").toString());
                              }
                          }
                      });
          }
    
   }
  });
 }

 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
     super.onActivityResult(requestCode, resultCode, data);
     Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
 }
 

}


Change Login/Logout text of LoginButton.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fb="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.facebook.widget.LoginButton
         android:id="@+id/activity_login_facebook_btn_login"
         android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="15dp"
        fb:login_text="Login with Facebook"
     fb:logout_text="Logout"
         />

</RelativeLayout>

Read More



continue reading Android : Login with Facebook SDK 3.0

Mar 8, 2013

Android xxhdpi screens

The needle keeps moving forward with Android display sizes as nearly all of the prominent announcements featured screens at 4 inches or larger. Most now hover in the range of 4.5 inches to 5 inches, such has LG Optimus F5, Sony Z, Samsung Galaxy Grand. 

For the developer, We can support bigger screens with xxhdpi, It supports from Android API 16 ( OS 4.1.x ).

Changes requires to support xxhdpi.
continue reading Android xxhdpi screens