mytechead

Android & Wordpress Help center

Archive for the month “February, 2014”

Android: Share via installed email clients ONLY!

Came across this very easy and clean way of showing users ONLY email clients to choose from while sharing anything via email.

So here goes the code:-

/**
* Displays a dialog to share via email
*
* @param mailTo
* @param mailSubject
* @param mailBody
* @param context
*/
private void shareViaEmail(String mailTo, String mailSubject,
String mailBody, Context context) {
// To ensure that only email clients show up in the chooser menu, we are using mailto string
StringBuilder builder = new StringBuilder("mailto:" + Uri.encode(mailTo));
if (mailSubject != null) {
builder.append("?subject=" + Uri.encode(Uri.encode(mailSubject)));
}
if (mailBody != null) {
builder.append("&body=" + Uri.encode(Uri.encode(mailBody)));
}
String uri = builder.toString();
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
context.startActivity(intent);

}

Android: WebView, enable / disable navigation buttons

A very convenient way of changing the state of navigation buttons [forward / back button] of a webview as enabled and disabled as per the availability of next and previous pages is to add this function in your code, and call it from onPageFinished() method of your WebViewClient class.

Code snippet:

mWebView.setWebViewClient(new MyWebViewClient());

public class MyWebViewClient extends WebViewClient{
   @Override
   public void onPageFinished(WebView view, String url) {
         super.onPageFinished(view, url);

         enableDisableNavigationButtons();
   }

   @Override
   public void onPageStarted(WebView view, String url, Bitmap favicon) {
     super.onPageStarted(view, url, favicon);
   }

   @Override
   public void onReceivedError(WebView view, int errorCode,
     String description, String failingUrl) {
     super.onReceivedError(view, errorCode, description, failingUrl);
   }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
      return super.shouldOverrideUrlLoading(view, url);
    }
}

 

/**
* Changes state of navigation buttons – Disable / Enable as per
* the availability of previous / next pages.
*/
public void enableDisableNavigationButtons(WebView mWebView) {
// if has previous page, enable the back button

if(mWebView.canGoBack()){
  backButton.setImageDrawable(getResources().getDrawable(R.drawable.back));
}else{
  backButton.setImageDrawable(getResources().getDrawable(R.drawable.back_disabled));
}
// if has next page, enable the next button

if(mWebView.canGoForward()){
  forwardButton.setImageDrawable(getResources().getDrawable(R.drawable.forward));
}else{
  forwardButton.setImageDrawable(getResources().getDrawable(R.drawable.forward_disabled));
}
}

Android: WebView quick settings

A very quick code fragment to load a webview with almost all the required settings, users can skip / edit any of the settings as per their needs

mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setDatabaseEnabled(true);
mWebView.getSettings().setAppCacheEnabled(false);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setPluginState(WebSettings.PluginState.ON);
mWebView.setWebViewClient(new MyWebViewClient());
mWebChromeClient = new MyWebChromeClient();
mWebView.setWebChromeClient(mWebChromeClient);

mWebView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
mWebView.getSettings().setPluginState(android.webkit.WebSettings.PluginState.ON_DEMAND);

mWebView.getSettings().setBuiltInZoomControls(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setLoadWithOverviewMode(true); //load url completely zoomed out

Android: Set device orientation

Android has introduced two more orientation modes for devices with API 8+: ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT & ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE. You can set the screen orientation to these modes by using the following code in you Activity class:

try {
    if(Integer.valueOf(android.os.Build.VERSION.SDK_INT) >= 8){
        if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
            // setting the orientation as per the device orientation for API level 8+
            if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_0){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
       }else if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_180){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
       }else if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_90){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
       }else if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_270){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
       }
     }else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
          if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_0){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
          }else if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_180){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
          }else if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_90){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
          }else if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_270){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
          }
    }
}else if(Integer.valueOf(android.os.Build.VERSION.SDK_INT) < 8){
      // setting the orientation as per the device orientation for API level below 8
      if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
      }else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
      }

}
} catch (Exception e1) {
e1.printStackTrace();
}

Please note that the above code will set you in infinite loop of orientation changes if we don’t add few more pieces of code:-
1) In android manifest file:- 
<activity android:name=”activity_name” android:label=”@string/app_name” android:configChanges=”orientation|screenSize”>
…………
…………
</activity>

2) Add following code to catch orientation changes:-
@Override

public void onConfigurationChanged(Configuration newConfig){
     super.onConfigurationChanged(newConfig);
}

The entry in manifest file tells the system that I will handle the orientation changes myself and OnCreate should not be called. onConfigurationChanged method is called instead when orientation changes and we can add in here any code we want to execute when the orientation changes.

Android: Updates to handling screen orientation changes

Beginning with Android 3.2 (API level 13), the “screen size” also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the “screenSize” value in addition to the “orientation” value. That is, you must decalare android:configChanges=”orientation|screenSize” in your android manifest file.

However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).

Android: Gracefully handle nested scrollbars

Since the time I started android development, having nested scrollbars intercept their touch listeners for a smooth, even and intended scrolling has always been a pain in my ass. But thank god, finally I got the courage to face this and developed a listener which can handle nested scrollbars gracefully.

So here is the source code of my nested scroll listener class:

import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

/**
* Class enables touch events of a double nested scrollviews / scrollbars
*
* Usage: Set this touchlistener to childview of the nested scrollviews
*
* e.g.
*
* NestedScrollHelper nestedScrollHelper = new NestedScrollHelper();
*
* public boolean onTouch(View v, MotionEvent event){
* // Touch listener of child view
* // Do all the stuff you want to do in this touchlistener of child view
* // Additionally…..
* // Add the listener to handle nested scrollviews
* nestedScrollHelper.onTouch(v, event);
* return false;
* }
*
* @author shoaib
*
*/
public class NestedScrollHelper implements OnTouchListener{

@Override
public boolean onTouch(View v, MotionEvent event) {

// get the event action
int action = event.getAction();

// For each of the action DOWN/UP/MOVE
// disallow touch intercept to parent
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_MOVE:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
}

// Handle childview’s touch events.
v.onTouchEvent(event);
return true;
}
}

Now once you have this class, inside your Activity you can add this listener something like this:

public class MainActivity extends Activity implements OnTouchListener{

ListView myListView;
NestedScrollHelper nestedScrollHelper = new NestedScrollHelper();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

myListView = (ListView) findViewById(R.id.listview_id);
myListView.setOnTouchListener(this);

}

public boolean onTouch(View v, MotionEvent event){
// Touch listener of child view
// Do all the stuff you want to do in this touchlistener of child view
// Additionally…..
// Add the listener to handle nested scrollviews
nestedScrollHelper.onTouch(v, event);
return false;
}

}

This is it. You can handle the touch event how ever you want inside this onTouch method and by just calling the nestedScrollHelper.onTouch(v, event); inside this method [onTouch] scrolling will work perfectly smooth.

Hope it helps!

 

PS: Special thanks to my office colleague who helped me in this.

Post Navigation