Sunday, June 12, 2011

Handling Screen Orientation - Part 2


How to handle rotation?
Now if you choose to rotate your activity with display either specifying “rotate as sensor” or using “orientation setting” you must handle the steps that are taken when the display is rotated.
Whenever the window rotates, your activity is destroyed and recreated, and “onCreate(Bundle)” is executed again.
You may need to save the activity state before this happens. To achieve that you can override the
public void onSaveInstanceState(Bundle outState)
For Example: You may want to save the Value of a String array before screen orientation change restarts your activity.
To do this override the onSaveInstanceState method of Activity class like this:
public class SampleActivity extends Activity{
      String[] testArray = null;
      public static final String TEST_ARRAY = “KEY_FOR_ARRAY”;

      @Override
      public void onCreate(Bundle State){
            if(State != null){
testArray =
State.getStringArray(SampleActivity.TEST_ARRAY);
            }
            else{
                  testArray = new String[6];
}
      }

      @Override
public void onSaveInstanceState(Bundle outstate){
outstate.putStringArray(SampleActivity.TEST_ARRAY,
      testArray);
}
}

Otherwise your activity will use the default implementation of this function which saves some amount of state.
Some of the values that you can save before orientation change are as follows:
  • Serializable and its subclasses.
  • String
  • Parcelable and its Subclasses
  • boolean, int, float.
  • Arrays etc.

However you may not want to store the values because this may slow down your application you can attain faster screen orientation by caching the data before orientation changes.
Your activity can cache data before rotation this can be accomplished by overriding
public Object onRetainNonConfigurationInstance()
Let’s take the above example again but instead of saving the String array we’ll cache the data and retrieve reference to that after restart.
public class SampleActivity extends Activity{
      String[] testArray = null;
      public static final String TEST_ARRAY = “KEY_FOR_ARRAY”;

      @Override
      public void onCreate(Bundle State){
testArray = (String[])getLastNonConfigurarionInstance();
if(testArray == null)
      testArray = new String[6];
      }

      @Override
public Object onRetainNonConfigurationInstance(){
      return testArray;
}
}
Change orientation at runtime
You can use Activity.setRequestedOrientation() from your activity to set that orientation
e.g. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
if you do not use this the default value is SCREEN_ORIENTATION_UNSPECIFIED and you must not specify any orientation in Applications manifest XML. And each time orientation is changed the activity is stopped and restarted.
Check orientation settings
You can query the orientation settings for device using
public static int myOrient;
myOrient = this.getResources().getConfiguration().orientation;

this function will return either of the following values:
ORIENTATION_LANDSCAPE or ORIENTATION_PORTRAIT, it can also return ORIENTATION_SQUARE on a square device.

<<Handling Screen Orientation - Part 1

Cheers!!
Vivek Jain
Hello Everyone, I came across an application which allowed me to produce nice effects on Images that are in my phone and Images that I take from my phones camera, its available here, 
 

Handling Screen Orientation - Part 1

Sometimes or I may say many times user will want to rotate the screen – this may be because user wants to view the app in landscape mode, or user wants to type something using on-screen keyboard.
If user rotates the device from portrait to landscape, your app must rotate with it or must handle the change elegantly, but the question is how??
So let’s begin exploring the answer to this question….
First of all let us understand the concept of rotation and how you can set the behavior in your Android powered device.
On your device’s home screen go to press “MENU” key and go to “SETTINGS” menu and then go to “DISPLAY SETTINGS” You will see the “Orientation/ Auto-rotate screen” option somewhat like this.
 
Note: Location may change based on the Android OS version.

When this option is unchecked, then screen display changes from portrait to landscape if the on – screen keyboard is open and back to portrait when it is closed but nothing happens when user actually rotates the device.
With this setting on screen display always changes when keyboard is open and when user changes the device orientation.
Now let’s see how you can handle this change in your application, there are three things that you must do in your application:
  1. 1.       You should always create layouts that can handle orientation and should always create separate layouts for portrait and landscape modes; we’ll see how you can do this later.
  1. 2.       Then set the orientation behavior in the Application’s manifest file.
  1. 3.       Then handle the rotation by handling appropriate events in your code.
Now let’s start with these points.

Creating layouts that can handle rotation
Now with this I mean that your layout should be able to adjust itself whenever some change like this happens, it’ll be better if your application can provide different layouts for different orientations.
Wherever possible choose from the layouts which adjust to the orientation changes:
LinearLayout, RelativeLayout, or TableLayouts are some of the layouts that that adjust for screen changes, but it might not be a good way because the screen designed for portrait mode might not work for landscape mode and vice versa, so, it’s better to have different layouts for both the modes.
These specialized layouts for Portrait and Landscape modes go in Separate specialized folders “res/layout” for Portrait mode and “res/layout-land” for landscape mode, you can also on similar lines have separate folders for drawables as well.
Setting rotation behavior in Application’s manifest file
This only involves adding one parameter “android:screenOrientation” in <activity> tag in your manifest XML for each activity that must handle rotation.
If you omit this parameter default will be whatever you have set in “DISPLAY SETTINGS” i.e.whatever is “Auto-rotate screen/Orientation” setting. This actually has some benefits listed as below:
1.       If your application uses intents to call some other application views, then, using Orientation settings your app user will not have to turn device to move to that view and turn back to move to your app.
2.       User is free to choose orientation behavior, more preferable by most users.
3.       Makes your app more compatible with wide array of Android devices.
Setting this parameter as “android:screenOrientation=”unspecified”” or “android:screenOrientation=”user” will also have the same effect as not specifying at all
If you set this parameter as “android:screenOrientation=”sensor”” this will mean that display will always rotate when the device is turned or the on-screen keyboard is opened or closed, irrespective of “Orientation” settings.
If you set this parameter as “android:screenOrientation=”portrait”” or “landscape” your activity will remain in one orientation even if the device is rotated or on-screen keyboard is opened or closed. You’ll also not have to worry about layouts that adjust to orientation changes or handle roation in your code.

Handling Screen Orientation - Part 2 >> 
Cheers!!
Vivek Jain
Hello Everyone, I came across an application which allowed me to produce nice effects on Images that are in my phone and Images that I take from my phones camera, its available here, 

Saturday, May 21, 2011

WebView - Part 4 Handling Cookies in WebView


Handling Cookies in WebView

Actually this is very simple, as we mentioned in Part 1 of this series, that for security reasons, your application will have its own cache and its own cookie store i.e. it doesn’t share the Browser’s application data, cookies are also managed in separate thread which means that those operations which are for managing cookies (e.g. building index) will not block your application’s UI thread.

Now, we use “android.webkit.CookieSyncManager” class to manage cookies particularly to synchronize the browser cookies between RAM and permanent storage. To get maximum efficiency cookies are stored in RAM and a separate thread is used to save cookies this thread is driven by timer, sync interval is of 5 Minutes.

To use CookieSyncManager all you have to do is add these three lines in your code
Call this when the application starts.
 
CookieSyncManager.createInstance(context);
 
To set up sync call in Activity.onResume()
 
CookieSyncManager.getInstance().startSync();
 
and lastly, call this in Activity.onPause()
 
CookieSyncManager.getInstance().stopSync();
 
To get sync instantly without waiting for the timer to trigger, host can call
 
CookieSyncManager.getInstance().sync();
 
But be aware that this sync also happens asynchronously, so don’t do it just as your activity is shutting down.

<<WebView - Part 3 How to customize WebView?




Cheers!!
Vivek Jain
Hello Everyone, I came across an application which allowed me to produce nice effects on Images that are in my phone and Images that I take from my phones camera, its available here, 

WebView - Part 3 How to customize WebView?


WebViews can be customized in Variety of ways, where you can add your own behaviour; this can be done in following ways:

1.      Overriding “android.webkit.WebChromeClient” class we can override the UI behaviour, because this class or subclass of this class is called when something that may effect the UI happens, e.g. progress update and Javascript Alerts
2.      Overriding “android.webkit.WebViewClient” class we can override page loading behaviour; because this class or its subclass is called whenever something that can impact page rendering happens e.g. errors or form submissions. You can also intercept URLs here.
3.      You can also modify the “android.webkit.WebSettings” class e.g. you can enable JavaScript with setJavaScriptEnabled() method.
4.      You can also add JavaScript to Java interfaces with the addJavaScriptInterface(Object, String) method. This method lets you bind Java Object into the WebView so that they can be controlled by web pages JavaScript

Here we’ll discuss all of them one by one.

Handling UI State with WebChromeClient Class:

Here in this sample we are overriding the Progress of page loading for this we’ll override WebChromeClient.onProgressChanged method this sample will also explain the way of getting the Settings for your WebView and setting some of the settings e.g. enabling JavaScript.

So, here’s the Sample code that you can use in your activity:

browser = (WebView)findViewById(R.id.webbrowser);
           
getWindow().requestFeature(Window.FEATURE_PROGRESS);
browser.getSettings().setJavaScriptEnabled(true);
           
browser.setWebChromeClient(new WebChromeClient(){
      public void onProgressChanged(WebView View, int progress){
                        WebBrowser.this.setProgress(progress * 1000);
                  }
});

So, here in first line we are getting reference to WebView widget that we have specified in XML in this layout.
Then we request FEATURE_PROGRESS feature of this activity’s Window this will display the progress in Title bar of the window and progress will automatically disappear when it reaches 100%.

Then we call getSettings() method of WebView this method returns the reference to WebSettings class’s object associated with this WebView object. When a WebView is first created, it obtains a set of default settings. These default settings will be returned from any getter call. A WebSettings object obtained from WebView.getSettings() is tied to the life of the WebView. If a WebView has been destroyed, any method call on WebSettings will throw an IllegalStateException.

We use this reference to enable JavaScript on this WebView object.

Next, we are setting a new object for WebChromeClient of WebView and overriding its onProgressChanged method, this method tells the host application about the progress of loading the page.

Handling page loading behaviour using WebViewClient class:

browser.setWebViewClient(new WebViewClient(){
public void onRecievedError(WebView View, int errorCode,
String description, String failingURL){
            AlertDialog.Builder dlg = new
                        AlertDialog.Builder(WebBrowser.this);
            dlg.setMessage(description);
            dlg.setTitle(R.string.app_name);
            dlg.setPositiveButton(R.string.ok_button, new
DialogInterface.OnClickListener() {                   public void onClick(DialogInterface
arg0, int arg1) {
                                   
                              }
                  });
            }
      });

Here, we are setting a new object for WebViewClient of WebView and overriding its onRecievedError method, this method is called whenever there is some error in loading the page.
Similar to this approach you can override the

public boolean shouldOverrideUrlLoading(WebView view, String url)

method of WebViewClient; this method returns “true” if it is overriding the Url Loading otherwise “false

Adding Javascript to Java interfaces

final Context myApp = this;
/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface {
@SuppressWarnings("unused")
public void showHTML(String html) {
new AlertDialog.Builder(myApp)
.setTitle("HTML")
.setMessage(html)
.setPositiveButton(android.R.string.ok, null) .setCancelable(false)
.create()
.show();
}
}

final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */ browser.getSettings().setJavaScriptEnabled(true);

/* Register a new JavaScript interface called HTMLOUT */ browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");

/* WebViewClient must be set BEFORE calling loadUrl! */ browser.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) {

/* This call inject JavaScript into the page which just finished loading. */ browser.loadUrl("javascript:window.HTMLOUT.showHTML('<head>'+document.getElementsBy
TagName('html') [0].innerHTML+'</head>');"); } });

/* load a web page */
browser.loadUrl("someUrl");

  • First, a class called MyJavaScriptInterface is defined. It implements a single public method showHTML() which displays a dialog with the HTML it receives as a parameter.
  • Then, an instance of this class is registered as a JavaScript interface called HTMLOUT. The showHTML() method can now be accessed from JavaScript like this: window.HTMLOUT.showHTML(‘…’)
  • In order to call showHTML() when the page finishes loading, a WebViewClient instance which overrides onPageFinished() is added to the WebView. When the page finishes loading, this method will inject a piece of JavaScript code into the page, using the method I described in an earlier post.
  • Finally, a web page is loaded.

showHTML method can also be called from other Javascript that may get loaded into your browser control, so, use carefully.


Cheers!!
Vivek Jain
Hello Everyone, I came across an application which allowed me to produce nice effects on Images that are in my phone and Images that I take from my phones camera, its available here, 

Thursday, May 19, 2011

WebView - Part 2 Accesing Files on Device and in APK itself

Accessing files in Android device using WebView

For using WebView you must have the permissions to access INTERNET and to request permission to access INTERNET just add the following line in your application's manifest just under </application> tag  i.e. make it a child of manifest tag.

     <uses-permission android:name="android.permission.INTERNET"/>

Create the following HTML either programmatically using code in String format or create the file and save that in /res/value/string.xml and name it as <somename>
            <html>
          <head><title>Test File Loading</title></head>
          <body>
Here we are loading the image file in HTML
To display:<br>
<img height=”100” width=”100” src=file:///yourimagefilepath></img>
          </body>
     </html>

To reference the file in <img> tag, you have to use the file URI pointing to the location where the file is saved.

Here’s the Java code to load this HTML into a WebKit component:
            WebView web = (WebView)findViewById(R.id.web_view);
            final String mimeType = “text/html”;
     final String encoding = “UTF-8”;
String htmldata =
          getResources().getString(R.string.<somename>);
     if(htmldata != null){
          web.loadData(html,
                        mimeType,
                        encoding);
     }
else{
web.loadData(“<html><body>Failed</body></html>”
     ,mimeType, encoding);
}

Now, you should be able to see image in your WebView

Accessing resources bundled with APK
Create the following HTML either programmatically using code in String format or create the file and save that in /res/value/string.xml and name it as <somename>
            <html>
          <head><title>Test File Loading</title></head>
          <body>
Here we are loading the image file in HTML
To display:<br>
<img height=”100” width=”100” src=file:///android_asset/imagename></img>
          </body>
     </html>
To reference the file in <img> tag, you have to use the file URI pointing to the /android_asset/imagename.


Here’s the Java code to load this HTML into a WebKit component:
            WebView web = (WebView)findViewById(R.id.web_view);
            final String mimeType = “text/html”;
     final String encoding = “UTF-8”;
String htmldata =
          getResources().getString(R.string.<somename>);
     if(htmldata != null){
          web.loadData(html,
                        mimeType,
                        encoding);
     }
else{
web.loadData(“<html><body>Failed</body></html>”
     ,mimeType, encoding);
}

Now, you should be able to see image in your WebView.

<<WebView – Part 1 Capabilities and Limitations  

WebView - Part 3 How to customize WebView?>>


Cheers!!
Vivek Jain
Hello Everyone, I came across an application which allowed me to produce nice effects on Images that are in my phone and Images that I take from my phones camera, its available here, 

Wednesday, May 18, 2011

WebView – Part 1 Capabilities and Limitations

WebView is actually a WebKit canvas for Android platform, WebKit is open source browser engine which is also being used in Apple’s Safari.
This blog outlines many things if not everything about WebView.
Capabilities
  1. It is possible to intercept the events in the WebView to overload many of the default behaviour e.g. we can overload the behaviour when Page loading is completed, similarly, loads of other events can be overloaded to customize the behaviour of WebView in specific circumstances.
  2. Assets like Videos and Images can be referenced from HTML running in WebView; even the Assets from APK file can be loaded.
  3. Assets can also be downloaded over internet and saved into Android device then these Assest can be loaded in HTML.
  4. This Widget can be used to load and display HTML’s over the network just like normal web browser.
  5. HTML’s that are saved on Android device can also be loaded in WebView.
  6. HTML can also be dynamically generated and viewed in WebView, e.g. we can generate HTML based on certain parameter that depends on Time elapsed like we can use GPS and Time elapsed to calculate the distance covered and then display the results in format of Dynamically generated HTML into WebView.
  7. HTML code can also be presented in Application resources inside the APK file, this approach can be used to display predetermined data in a formatted way using HTML and WebView
Limitations
  1. Its not easy to intercept the events generated by WebView component
  2. There are many events that cannot be intercepted, and there is limitation in what behaviours can be overloaded, which limits the customization of this component and changing the default behaviour of this component difficult.
  3. By default, a WebView provides no browser-like widgets, does not enable JavaScript and web page errors are ignored. If your application has such requirements it better to invoke Browser application than using WebView like this:
        Uri uri = Uri.parse("http://www.example.com");
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        startActivity(intent);
4.      By default, requests by the HTML to open new windows are ignored.
5.      By default, requests by the HTML to open new windows are ignored
Cookie and Window Management
For security reasons, your application has its own cache, cookie store – it doesn’t share browser data. Cookies will be managed in separate thread so that heavy operations related to cookies can’t block UI thread. “CookieSyncManager” is used to synchronize cookies between RAM and permanent storage, so this class must be used if you want to use cookies in your application.
By default, requests by the HTML to open new windows are ignored, no matter if the link is being opened by Javascript or by the target attribute on a link. You can customize your WebChromeClient to provide your own behaviour for opening multiple windows
You can set your activity to handle orientation and keyboardHidden changes WebView will automatically re-orient it.

Building web pages to support different screen densities

By default, WebView scales a web page so that it is drawn at a size that matches the default appearance on a medium density screen. So, it applies 1.5x scaling on a high density screen (because its pixels are smaller) and 0.75x scaling on a low density screen (because its pixels are bigger). Starting with API Level 5 (Android 2.0), WebView supports DOM, CSS, and META tag features to help you (as a web developer) target screens with different screen densities.
Here's a summary of the features you can use to handle different screen densities:
  • The window.devicePixelRatio DOM property. The value of this property specifies the default scaling factor used for the current device. For example, if the value of window.devicePixelRatio is "1.0", then the device is considered a medium density (mdpi) device and default scaling is not applied to the web page; if the value is "1.5", then the device is considered a high density device (hdpi) and the page content is scaled 1.5x; if the value is "0.75", then the device is considered a low density device (ldpi) and the content is scaled 0.75x. However, if you specify the "target-densitydpi" meta property (discussed below), then you can stop this default scaling behavior.
  • The -webkit-device-pixel-ratio CSS media query. Use this to specify the screen densities for which this style sheet is to be used. The corresponding value should be either "0.75", "1", or "1.5", to indicate that the styles are for devices with low density, medium density, or high density screens, respectively. For example:
  rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1.5)" href="hdpi.css" />
The hdpi.css stylesheet is only used for devices with a screen pixel ration of 1.5, which is the high density pixel ratio.
  • The target-densitydpi property for the viewport meta tag. You can use this to specify the target density for which the web page is designed, using the following values:
    • device-dpi - Use the device's native dpi as the target dpi. Default scaling never occurs.
    • high-dpi - Use hdpi as the target dpi. Medium and low density screens scale down as appropriate.
    • medium-dpi - Use mdpi as the target dpi. High density screens scale up and low density screens scale down. This is also the default behavior.
    • low-dpi - Use ldpi as the target dpi. Medium and high density screens scale up as appropriate.
    • - Specify a dpi value to use as the target dpi (accepted values are 70-400).
Here's an example meta tag to specify the target density:
 name="viewport" content="target-densitydpi=device-dpi" />
If you want to modify your web page for different densities, by using the -webkit-device-pixel-ratio CSS media query and/or the window.devicePixelRatio DOM property, then you should set the target-densitydpi meta property to device-dpi. This stops Android from performing scaling in your web page and allows you to make the necessary adjustments for each density via CSS and JavaScript.
It is always best to let the WebView take the full space available in parent’s ViewGroup object, because WebView component doesn’t know about it’s size until it loads HTML into it. So its best to set size of WebView while placing it into a ViewGroup, and then load HTML into it. Otherwise there are issues with WebView.



WebView - Part 2 Accesing Files on Device and in APK itself



Cheers!!
Vivek Jain
Hello Everyone, I came across an application which allowed me to produce nice effects on Images that are in my phone and Images that I take from my phones camera, its available here, 

Tuesday, May 17, 2011

PROVIDING LAUNCHER SHORTCUT – Android

In this article we'll discuss how to provide facility to add shortcut to your activity to the launcher
Contents:
Adding shortcut to launcher
An activity actually handles two stages of launcher shortcut's life cycle.
1. Activity must provide the shortcuts to the launcher. That is, when the user installs a shortcut, your activity must generate the actual shortcut and returns it to the launcher along with the shortcut name and icon which will be displayed to user.
2. Whenever user clicks on your applications icon, intent is sent. Your activity typically handles this intent as necessary

Now let’s see how we can handle the stage 1.
Your application simply creates an "Intent" that the launcher will use to create the shortcut.A more interactive way such as a User interface can be provided to user to make a more customizable shortcut.For example, Your User Interface may provide the way to select the specific nature of the shortcut, i.e. contact, picture, URL, media item etc.

//This function creates a shortcut and returns it to the caller. There are actually two
//intents that you will send back.
private void setupShortcut() {
// First, set up the shortcut intent. For this example, we simply create an intent that
// will bring us directly back to this activity. A more typical implementation would use a
// data Uri in order to display a more specific result, or a custom action in order to
// launch a specific operation.

Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
shortcutIntent.setClassName(this, this.getClass().getName());
shortcutIntent.putExtra(SHTCT_KEY, "Example Shortcut provided");

// Then, set up the container intent (the response to the caller)

Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Name");
Parcelable iconResource = Intent.ShortcutIconResource.fromContext(
this, R.drawable.icon);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);

// Now, return the result to the launcher

setResult(RESULT_OK, intent);
}

This function provides the Intent that will be returned to launcher in the container Intent .

Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
shortcutIntent.setClassName(this, this.getClass().getName());
shortcutIntent.putExtra(SHTCT_KEY, "Example Shortcut provided");

This is the intent that will be sent to your activity when user clicks Shortcut Icon.
First we are setting up the shortcut intent. Here in this example we are telling launcher that we need to handle “ACTION_MAIN” Action i.e. this intent will bring us directly back to this activity. However you can use data Uri with Action as “ACTION_VIEW” to display more specific result, or, a custom action to launch a specific operation provided your Activity handles that Action which you must specify in “AndroidManifest.xml” in “intent-filter” tag of “activity” tag.


Second we are setting up the class to call; in this case we are setting the class name for current activity but any other “class name” will also work provided that class can handle the Action specified in the intent.




Next we’ll create the container Intent that will have the Shortcut specific information.

// Then, set up the container intent (the response to the caller)

Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Name");
Parcelable iconResource = Intent.ShortcutIconResource.fromContext(
this, R.drawable.icon);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);

Here, in second line we are specifying the Intent that will be sent back to the activity when user clicks the shortcut Icon.

Next we specify the name i.e. the text that’ll be displayed with the Icon.


And then the Icon itself
.

Now, set the results for launcher to use
.

// Now, return the result to the launcher

setResult(RESULT_OK, intent);

Now write the following code in onCreate method of your Activity

// Resolve the intent
final Intent intent = getIntent();
final String action = intent.getAction();

// If the intent is a request to create a shortcut, we'll do that and exit

if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
setupShortcut();
finish();
return;
}

Intent.ACTION_CREATE_SHORTCUT is sent to your activity by launcher when user has requested to create the Shortcut .
So, in response to this Intent we set up the intent and finish the activity and return.
With this your process of adding Activity shortcut to Launcher is finished.
Cheers!!
Vivek Jain
Hello Everyone, I came across an application which allowed me to produce nice effects on Images that are in my phone and Images that I take from my phones camera, its available here,