Monday, July 30, 2012

Android - Logs

Hello

Reading and Writing Logs

The Android logging system provides a mechanism for collecting and viewing system debug output. Logcat dumps a log of system messages, which include things such as stack traces when the emulator throws an error and messages that you have written from your application by using the Log class. 


The Log class


Log is a logging class that you can utilize in your code to print out messages to the LogCat. Common logging methods include:
For example:
Log.i("MyActivity", "MyClass.getView() — get item number " + position);
The LogCat will then output something like:
I/MyActivity( 1557): MyClass.getView() — get item number 1


Using LogCat



Filtering Log Output

Every Android log message has a tag and a priority associated with it.
  • The tag of a log message is a short string indicating the system component from which the message originates (for example, "View" for the view system).
  • The priority is one of the following character values, ordered from lowest to highest priority:
    • V — Verbose (lowest priority)
    • D — Debug
    • I — Info
    • W — Warning
    • E — Error
    • F — Fatal
    • S — Silent (highest priority, on which nothing is ever printed)
You can see output to Logcat via Eclipse

Export Logs

Log Collector - an app that can send the log on the device to your email,facebook, ...
Kyoro Logcat - an app that can send mail but more importantly can show you logs in REAL TIME !!


The following app was published using this post.


source - http://developer.android.com/tools/debugging/debugging-log.html

Nathan

Friday, July 27, 2012

Android - Services

Hello


1. Introduction

Service performs non UI tasks on the background indefinitely !!!!. It can perform network I/O , play music and etc.

Application can start a service, the service will continue running ever after the user has switched to another application


Service can take two forms :

Started 


  • service is started when an application component e.g. Activity perform startService. Once started it continue running indefinitely even if the component is destroyed
  • It is possible to stop the service (true for Service false for IntentService)


Bounded
  • A service is bounded when a component calls bindService
  • a bound service offers IPC
  • a bound service runs as long as it's bounded component runs


By default the service run on the hosting process main thread. You can create a thread and run the service on it's context


2. Basics
To create a service you subclass Service.

Important methods to override :

  • onStartCommand - called when startService is called
  • onBind - called when bindService is called
  • onCreate - called when the service is created. Called once
  • onDestroy - the system calls this when the service is no longer needed and is being destroyed. Use it for cleans up

Stoping service scenarios :
  • The system will stop service only when it's resources are running low and it need them for the application which are in user focus.
  • Bounded service have slim odds to be killed in case their bounded activity is in user focus.
  • If a service is declared to run in the foreground then most likely is will not  be killed
  • A service doing long operation will get lower position in the background list and is most likely be killed. It will be restarted as soon as system resources are available !!!


Manifest


You need to declare the service inside AndroidMwnifest.xml


<application
    ....
         <service android:name=".MyService" />

 </application>


Set the service attribue  android:exported to false in case you want that only your application will use it.


Create a started service


As pointed before it is done by calling startService.

The service can be stoped in two ways :

  • self stoping - calling stopSelf
  • stop by the app - stopService

startService pass Intent which is consumed by onStartCommand callback

CAUTION : Service runs in the same process in which it is declared and on the same main thread. Therefore, in case the service performs blocking operation it is recommended that the service will create a thread and run its work on it.

You can extend two classes :

Service
  • This is the base class for all services
  • It is important to create inside the service a thread which handles the service work in case the work blocks the main thread


IntentService
  • This is subclass of Service.
  • It uses a worker thread to do the work
  • All you need to do is implement onHandleIntent which is called per startService !!
  • The service stop itself when the work is done.
  • stopService does not work !!


Create a bounded Service


As pointed before it is done by calling bindService.
This post does not elaborate on this option.


Managing the life cycle of the service

Following is the life cycle of a service.





You can implement the callbacks. Unlike activity there is no need to call superclass

3. Source sample
TryService.zip

The sample show the use of
  • Service + worker thread
  • IntentService
The work is : send notification

MainActivity.java
The service is run using startService.
stopService works for Service not IntentService



package nathan.krasney.nynkmobile.tryservice;

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

public class MainActivity extends Activity {

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

public void myClickHandlerStart(View v)
    {
  RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radioGroupServices);
  int selectedId = radioGroup.getCheckedRadioButtonId();
  RadioButton radioButton = (RadioButton) findViewById(selectedId);
  
  if(radioButton.getText().equals("Service") )
  {
   service = new Intent(this, MyService.class);
  }
  else if(radioButton.getText().equals("IntentService"))
  {
   service = new Intent(this, MyIntentService.class);
  }

  if(service != null)
  {
  this.startService(service);
  }
    }


    public void myClickHandlerStop(View v)
    {
     boolean bRes = this.stopService(service);
     if(bRes){
     Toast.makeText(this, "stopService Success", Toast.LENGTH_SHORT).show();
     }
     else{
         Toast.makeText(this, "stopService Failure", Toast.LENGTH_SHORT).show();
     }
    }
    
    Intent service;
}

    

MyIntentService.java
InentService - onHandleIntent is called per startService


package nathan.krasney.nynkmobile.tryservice;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyIntentService extends IntentService {

 public MyIntentService()
 {
  super("MyIntentService");//name of class 
  
 }

 @SuppressWarnings("deprecation")
 @Override
 protected void onHandleIntent(Intent intent) {
  // Normally we would do some work here, like download a file.
       Toast.makeText(this, "onHandleIntent", Toast.LENGTH_SHORT).show();

  mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  
  Notification notification = CUtils.prepareNotification(mNotificationManager,
    getApplicationContext(),this,MyIntentService.class);
  
  
           synchronized (this) {
               try {
                   wait(5000);
                   mNotificationManager.notify(HELLO_ID, notification);
               } catch (Exception e) {
               }
           }
  
 }

 private static final int HELLO_ID = 1;
 NotificationManager mNotificationManager;
}



MyService.java

A worker thread is created to handle the work which otherwise will be done on the main thread. This is not must e.g. in case you have a listener and it's  work is perfomed in some async way then there is no need to create here a worker thread



package nathan.krasney.nynkmobile.tryservice;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;



public class MyService extends Service {
   @Override
   public void onCreate() {
     // Start up the thread running the service.  Note that we create a
     // separate thread because the service normally runs in the process's
     // main thread, which we don't want to block. 
    
    m_bshouldContinue=true;
    
    new Thread(new Runnable() {
          public void run() {
           int i=0;
           mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notification = CUtils.prepareNotification(mNotificationManager,
          getApplicationContext(), MyService.this.getBaseContext(),MyService.class);
        
        
             while (m_bshouldContinue) {
                 synchronized (this) {
                     try {
                         wait(5000);
                         mNotificationManager.notify(HELLO_ID, notification);
                     } catch (Exception e) {
                     }
                 }
             }
          }
      }).start();
   }

   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
       Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
       
       // If we get killed, after returning from here, restart
       return START_STICKY;
   }

   @Override
   public IBinder onBind(Intent intent) {
       // We don't provide binding, so return null
       return null;
   }
   
   @Override
   public void onDestroy() {
  m_bshouldContinue=false;
     Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); 
   }
   private static final int HELLO_ID = 1;
  NotificationManager mNotificationManager;
  boolean m_bshouldContinue; 
 }




Run the application to create


click the start after few second you will see the notification


Click Stop service and you will see a toast about success

Restart the application ,click on the radio button of IntentService then click Start Service



Click on Stop Service , you will get failure , that because stopService can not stop IntentService. The service stops when the work is finished



The following app was published using this post.

Nathan

Monday, July 16, 2012

Android - Supporting Different Devices

Hello



Android devices come in many shapes and sizes all around the world. With a wide range of device types, you have an opportunity to reach a huge audience with your app. In order to be as successful as possible on Android, your app needs to adapt to various device configurations. Some of the important variations that you should consider include different languages, screen sizes, and versions of the Android platform.
This post teaches you how to use basic platform features that leverage alternative resources and other features so your app can provide an optimized user experience on a variety of Android-compatible devices, using a single application package (APK).

This post will cover the following


Supporting Different Languages
Learn how to support multiple languages with alternative string resources.
Supporting Different Screens
Learn how to optimize the user experience for different screen sizes and densities.
Supporting Different Platform Versions
Learn how to use APIs available in new versions of Android while continuing to support older versions of Android.



1. Supporting Different Languages

It’s always a good practice to extract UI strings from your app code and keep them in an external file. Android makes this easy with a resources directory in each Android project.


If you created your project using the Android SDK Tools (read Creating an Android Project), the tools create a res/ directory in the top level of the project. Within this res/ directory are subdirectories for various resource types. There are also a few default files such as res/values/strings.xml, which holds your string values.

Create Locale Directories and String Files


To add support for more languages, create additional values directories inside res/ that include a hyphen and the ISO country code at the end of the directory name. For example, values-es/ is the directory containing simple resourcess for the Locales with the language code "es". Android loads the appropriate resources according to the locale settings of the device at run time.
Once you’ve decided on the languages you will support, create the resource subdirectories and string resource files. For example:
MyProject/
    res/
       values/
           strings.xml
       values-es/
           strings.xml
       values-fr/
           strings.xml
Add the string values for each locale into the appropriate file.
At runtime, the Android system uses the appropriate set of string resources based on the locale currently set for the user's device.
For example, the following are some different string resource files for different languages.
English (default locale), /values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">My Application</string>
    <string name="hello_world">Hello World!</string>
</resources>
Spanish, /values-es/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">Mi AplicaciĆ³n</string>
    <string name="hello_world">Hola Mundo!</string>
</resources>
French, /values-fr/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">Mon Application</string>
    <string name="hello_world">Bonjour le monde !</string>
</resources>
Note: You can use the locale qualifier (or any configuration qualifer) on any resource type, such as if you want to provide localized versions of your bitmap drawable. For more information, see Localization.


Use the String Resources


You can reference your string resources in your source code and other XML files using the resource name defined by the <string> element's name attribute.
In your source code, you can refer to a string resource with the syntax R.string.<string_name>. There are a variety of methods that accept a string resource this way.
For example:
// Get a string resource from your app's Resources
String hello = getResources().getString(R.string.hello_world);

// Or supply a string resource to a method that requires a string
TextView textView = new TextView(this);
textView.setText(R.string.hello_world);
In other XML files, you can refer to a string resource with the syntax @string/<string_name> whenever the XML attribute accepts a string value.
For example:
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />




2. Supporting Different Screens



Android categorizes device screens using two general properties: size and density. You should expect that your app will be installed on devices with screens that range in both size and density. As such, you should include some alternative resources that optimize your app’s appearance for different screen sizes and densities.
  • There are four generalized sizes: small, normal, large, xlarge
  • And four generalized densities: low (ldpi), medium (mdpi), high (hdpi), extra high (xhdpi)
To declare different layouts and bitmaps you'd like to use for different screens, you must place these alternative resources in separate directories, similar to how you do for different language strings.
Also be aware that the screens orientation (landscape or portrait) is considered a variation of screen size, so many apps should revise the layout to optimize the user experience in each orientation

You can create diffrent AVG using the AVG build in skins . This allow you to simulate different screens

Create Different Layouts


To optimize your user experience on different screen sizes, you should create a unique layout XML file for each screen size you want to support. Each layout should be saved into the appropriate resources directory, named with a -<screen_size> suffix. For example, a unique layout for large screens should be saved under res/layout-large/.
Note: Android automatically scales your layout in order to properly fit the screen. Thus, your layouts for different screen sizes don't need to worry about the absolute size of UI elements but instead focus on the layout structure that affects the user experience (such as the size or position of important views relative to sibling views).
For example, this project includes a default layout and an alternative layout for large screens:
MyProject/
    res/
        layout/
            main.xml
        layout-large/
            main.xml
The file names must be exactly the same, but their contents are different in order to provide an optimized UI for the corresponding screen size.
Simply reference the layout file in your app as usual:
@Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
}
The system loads the layout file from the appropriate layout directory based on screen size of the device on which your app is running. More information about how Android selects the appropriate resource is available in the Providing Resources guide.
As another example, here's a project with an alternative layout for landscape orientation:
MyProject/
    res/
        layout/
            main.xml
        layout-land/
            main.xml
By default, the layout/main.xml file is used for portrait orientation.
If you want a provide a special layout for landscape, including while on large screens, then you need to use both the large and land qualifier:
MyProject/
    res/
        layout/              # default (portrait)
            main.xml
        layout-land/         # landscape
            main.xml
        layout-large/        # large (portrait)
            main.xml
        layout-large-land/   # large landscape
            main.xml
Note: Android 3.2 and above supports an advanced method of defining screen sizes that allows you to specify resources for screen sizes based on the minimum width and height in terms of density-independent pixels. This lesson does not cover this new technique. For more information, read Designing for Multiple Screens.



Supporting Different Densities



One common pitfall you must avoid when designing your layouts is using absolute pixels to define distances or sizes. Defining layout dimensions with pixels is a problem because different screens have different pixel densities, so the same number of pixels may correspond to different physical sizes on different devices. Therefore, when specifying dimensions, always use either dp or sp units. A dp is a density-independent pixel that corresponds to the physical size of a pixel at 160 dpi. An sp is the same base unit, but is scaled by the user's preferred text size (it’s a scale-independent pixel), so you should use this measurement unit when defining text size (but never for layout sizes).
For example, when you specify spacing between two views, use dp rather than px:
<Button android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/clickme"
    android:layout_marginTop="20dp" />
When specifying text size, always use sp:
<TextView android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:textSize="20sp" />


Create Different Bitmaps


You should always provide bitmap resources that are properly scaled to each of the generalized density buckets: low, medium, high and extra-high density. This helps you achieve good graphical quality and performance on all screen densities.
To generate these images, you should start with your raw resource in vector format and generate the images for each density using the following size scale:
  • xhdpi: 2.0
  • hdpi: 1.5
  • mdpi: 1.0 (baseline)
  • ldpi: 0.75
This means that if you generate a 200x200 image for xhdpi devices, you should generate the same resource in 150x150 for hdpi, 100x100 for mdpi, and 75x75 for ldpi devices.
Then, place the files in the appropriate drawable resource directory:
MyProject/
    res/
        drawable-xhdpi/
            awesomeimage.png
        drawable-hdpi/
            awesomeimage.png
        drawable-mdpi/
            awesomeimage.png
        drawable-ldpi/
            awesomeimage.png
Any time you reference @drawable/awesomeimage, the system selects the appropriate bitmap based on the screen's density.
Note: Low-density (ldpi) resources aren’t always necessary. When you provide hdpi assets, the system scales them down by one half to properly fit ldpi screens.
For more tips and guidelines about creating icon assets for your app, see the Iconography design guide.


How to Test Your Application on Multiple Screens


How to Test Your Application on Multiple Screens



Figure 6. A set of AVDs for testing screens support.
Before publishing your application, you should thoroughly test it in all of the supported screen sizes and densities. The Android SDK includes emulator skins you can use, which replicate the sizes and densities of common screen configurations on which your application is likely to run. You can also modify the default size, density, and resolution of the emulator skins to replicate the characteristics of any specific screen. Using the emulator skins and additional custom configurations allows you to test any possible screen configuration, so you don't have to buy various devices just to test your application's screen support.
To set up an environment for testing your application's screen support, you should create a series of AVDs (Android Virtual Devices), using emulator skins and screen configurations that emulate the screen sizes and densities you want your application to support. To do so, you can use the AVD Manager to create the AVDs and launch them with a graphical interface.
To launch the Android SDK Manager, execute the SDK Manager.exe from your Android SDK directory (on Windows only) or execute android from the <sdk>/tools/ directory (on all platforms). Figure 6 shows the AVD Manager with a selection of AVDs, for testing various screen configurations.
Table 3 shows the various emulator skins that are available in the Android SDK, which you can use to emulate some of the most common screen configurations.
For more information about creating and using AVDs to test your application, see Managing AVDs with AVD Manager.
Table 3. Various screen configurations available from emulator skins in the Android SDK (indicated in bold) and other representative resolutions.
Low density (120), ldpiMedium density (160), mdpiHigh density (240), hdpiExtra high density (320), xhdpi
SmallscreenQVGA (240x320)480x640
NormalscreenWQVGA400 (240x400)
WQVGA432 (240x432)
HVGA (320x480)WVGA800 (480x800)
WVGA854 (480x854)
600x1024
640x960
LargescreenWVGA800** (480x800)
WVGA854** (480x854)
WVGA800* (480x800)
WVGA854* (480x854)
600x1024
Extra Largescreen1024x600WXGA (1280x800)
1024x768
1280x768
1536x1152
1920x1152
1920x1200
2048x1536
2560x1536
2560x1600
* To emulate this configuration, specify a custom density of 160 when creating an AVD that uses a WVGA800 or WVGA854 skin.
** To emulate this configuration, specify a custom density of 120 when creating an AVD that uses a WVGA800 or WVGA854 skin.
† This skin is available with the Android 3.0 platform
To see the relative numbers of active devices that support any given screen configuration, see the Screen Sizes and Densities dashboard.

Figure 7. Size and density options you can set, when starting an AVD from the AVD Manager.
We also recommend that you test your application in an emulator that is set up to run at a physical size that closely matches an actual device. This makes it a lot easier to compare the results at various sizes and densities. To do so you need to know the approximate density, in dpi, of your computer monitor (for instance, a 30" Dell monitor has a density of about 96 dpi). When you launch an AVD from the AVD Manager, you can specify the screen size for the emulator and your monitor dpi in the Launch Options, as shown in figure 7.
If you would like to test your application on a screen that uses a resolution or density not supported by the built-in skins, you can create an AVD that uses a custom resolution or density. When creating the AVD from the AVD Manager, specify the Resolution, instead of selecting a Built-in Skin.
If you are launching your AVD from the command line, you can specify the scale for the emulator with the -scale option. For example:
emulator -avd <avd_name> -scale 96dpi
To refine the size of the emulator, you can instead pass the -scale option a number between 0.1 and 3 that represents the desired scaling factor.
For more information about creating AVDs from the command line, see Managing AVDs from the Command Line

3. Supporting Different Platform Versions

While the latest versions of Android often provide great APIs for your app, you should continue to support older versions of Android until more devices get updated. 
The dashboard for Platform Versions is updated regularly to show the distribution of active devices running each version of Android, based on the number of devices that visit the Google Play Store. Generally, it’s a good practice to support about 90% of the active devices, while targeting your app to the latest version.
Tip: In order to provide the best features and functionality across several Android versions, you should use the Android Support Library in your app, which allows you to use several recent platform APIs on older versions

Specify Minimum and Target API Levels


The AndroidManifest.xml file describes details about your app and identifies which versions of Android it supports. Specifically, the minSdkVersion and targetSdkVersion attributes for the <uses-sdk element identify the lowest API level with which your app is compatible and the highest API level against which you’ve designed and tested your app.
For example:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ... >
    <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15" />
    ...
</manifest>
As new versions of Android are released, some style and behaviors may change. To allow your app to take advantage of these changes and ensure that your app fits the style of each user's device, you should set the targetSdkVersion value to match the latest Android version available.

The following app was published using this post.


Source :


Nathan

Sunday, July 15, 2012

Android - Connection to the internet 3

Hello



This post demonstrate client\server interaction using JSON.

The client is android app and the server is asp.net based.





1. Android Client

Java supports JSON in terms of the classes :

  • JSONArray
  • JSONObject


2. ASP.Net Server
.Net supports JSON in terms of DataContractJsonSerializer




3. Source Sample

JSONClient.zip
JSONWebSite.zip


This sample includes :


1. The client send GET request to an ASP.Net server


2. The server responds with JSON array :

 [ {UserId="John" ,Latitude = 33.33 , Longitude = 44.56 ,Location = "some place 1" },
    {UserId="Jim" ,Latitude = 44.33 , Longitude = 55.56 ,Location = "some place 2" }]
  which is written via  DataContractJsonSerializer and  Response.Write to the client


3. The client parse the JSON array via classes JSONArray and JSONObject and write it to a TextView





Client
uses HttpURLConnection as done in android-connection-to-internet-1

The new stuf here is the parsing of the JSON array

protected void onPostExecute(Object result) {
       try {
       String strOut="";
    JSONArray json = new JSONArray((String)result);
    
    for (int i = 0; i < json.length(); ++i) {
        JSONObject rec = json.getJSONObject(i);
        strOut += String.format("UserId : %s ,Latitude : %f ,Longitude : %f ,Location : %s\n", 
          rec.getString("UserId"),rec.getDouble("Latitude"),
          rec.getDouble("Longitude"),rec.getString("Location"));
       
    }
    textViewMessage.setText(strOut);
       }
    catch (JSONException e) {
    textViewMessage.setText(e.getMessage());
   }
            
       }

MainActivity.java
This is basically like  android-connection-to-internet-1 beside the JSON stuff


package com.example.jsonclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        urlText = (EditText) findViewById(R.id.editTextURL);
        textViewURL = (TextView) findViewById(R.id.textViewURL);
        textViewMessage = (TextView) findViewById(R.id.textViewMessage);
    }

    

    
   // When user clicks button, calls AsyncTask.
   // Before attempting to fetch the URL, makes sure that there is a network connection.
    public void myClickHandler(View view) {
        // Gets the URL from the UI's text field.
        String stringUrl = urlText.getText().toString();
        ConnectivityManager connMgr = (ConnectivityManager) 
            getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            new DownloadWebpageText().execute(stringUrl);
        } else {
            textViewMessage.setText("No network connection available.");
        }
    }

     // Uses AsyncTask to create a task away from the main UI thread. This task takes a 
     // URL string and uses it to create an HttpUrlConnection. Once the connection
     // has been established, the AsyncTask downloads the contents of the web page as
     // an InputStream. Finally, the InputStream is converted into a string, which is
     // displayed in the UI by the AsyncTask's onPostExecute method.
     private class DownloadWebpageText extends AsyncTask {
      @Override
      protected String doInBackground(Object... urls) {
              
            // params comes from the execute() call: params[0] is the url.
            try {
                return downloadUrl((String) urls[0]);
            } catch (IOException e) {
                return "Unable to retrieve web page. URL may be invalid.";
            }
        }
        // onPostExecute displays the results of the AsyncTask.
      @Override
      protected void onPostExecute(Object result) {
       try {
       String strOut="";
    JSONArray json = new JSONArray((String)result);
    
    for (int i = 0; i < json.length(); ++i) {
        JSONObject rec = json.getJSONObject(i);
        strOut += String.format("UserId : %s ,Latitude : %f ,Longitude : %f ,Location : %s\n", 
          rec.getString("UserId"),rec.getDouble("Latitude"),
          rec.getDouble("Longitude"),rec.getString("Location"));
       
    }
    textViewMessage.setText(strOut);
       }
    catch (JSONException e) {
    textViewMessage.setText(e.getMessage());
   }
            
       }
    }
  // Given a URL, establishes an HttpUrlConnection and retrieves
  // the web page content as a InputStream, which it returns as
  // a string.
  private String downloadUrl(String myurl) throws IOException {
      InputStream is = null;
      
           
      try {
          URL url = new URL(myurl);
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.setReadTimeout(10000 /* milliseconds */);
          conn.setConnectTimeout(15000 /* milliseconds */);
          conn.setRequestMethod("GET");
          conn.setDoInput(true);
          // Starts the query
          conn.connect();
          int response = conn.getResponseCode();
          Log.d(DEBUG_TAG, "The response is: " + response);
          is = conn.getInputStream();

          // Convert the InputStream into a string
          BufferedReader in = new BufferedReader(new InputStreamReader(is));
         String line;
         String page = "";
         line = in.readLine();
         String  contentAsString="";
         while (line != null)
         {
        contentAsString = contentAsString + line;
           line = in.readLine();
         }
          
          
          return contentAsString;
          
      // Makes sure that the InputStream is closed after the app is
      // finished using it.
      } finally {
          if (is != null) {
              is.close();
          } 
      }
  }
    
//Reads an InputStream and converts it to a String.
public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
   Reader reader = null;
   reader = new InputStreamReader(stream, "UTF-8");        
   char[] buffer = new char[len];
   reader.read(buffer);
   return new String(buffer);
}
  
    private static final String DEBUG_TAG = "HttpExample";
    private EditText urlText;
    private TextView textViewURL;
    private TextView textViewMessage;
}




Server

The server is ASP.Net based.
It create JSON array via DataContractJsonSerializer and send to the client using Response.Write .
The server uses helper class name JsonHelper 

main.aspx



CJsonHelper.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Web;
using System.IO;
using System.Text;  

/// 
/// Summary description for Class1
/// 
public class JsonHelper
{
    /// 
    /// JSON Serialization
    /// 
    public static string JsonSerializer<T>(T t)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        MemoryStream ms = new MemoryStream();
        ser.WriteObject(ms, t);
        string jsonString = Encoding.UTF8.GetString(ms.ToArray());
        ms.Close();
        return jsonString;
    }
    /// 
    /// JSON Deserialization
    /// 
    public static T JsonDeserialize<T>(string jsonString)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
        T obj = (T)ser.ReadObject(ms);
        return obj;
    }
}

CTableRow.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// 
/// Summary description for Class1
/// 
public class CTableRow
{
    public string UserId;
    public double Latitude;
    public double Longitude;
    public string Location;
}
Run the application to create :




Click the Get button to crete




These are the exact info inserted by the server


Nathan

Friday, July 13, 2012

Android - SQLite

Hello


Motivation



Android default Database engine is Lite. SQLite is a lightweight transactional database engine that occupies a small amount of disk storage and memory, so it's a perfect choice for creating databases on many mobile operating systems such as Android, iOS.



Class SQLiteDatabase




Exposes methods to manage a SQLite database.
SQLiteDatabase has methods to create, delete, execute SQL commands, and perform other common database management tasks.
Database names must be unique within an application, not across all applications.

In addition to SQLite's default BINARY collator, Android supplies two more, LOCALIZED, which changes with the system's current locale, and UNICODE, which is the Unicode Collation Algorithm and not tailored to the current locale.





Class SQLiteDatabase methods






openOrCreateDatabase : 

  • open \ create data base


execSQL



rawQuery

  • Runs the provided SQL and returns a Cursor over the result set.


close

  • Releases a reference to the object, closing the object if the last reference was released



Source sample


SQLite.zip

This sample illustrate :

  • DataBase and Table creation
  • Insert row into table
  • Delete all rows from table
  • Read all rows from data base


Data base : LocationDbName
Table_1 Schema :

  • VARCHAR, UserId
  • REAL - Longitude
  • REAL - Latitude
  • VARCHAR - Location
  • INTEGER- DateTime (time in milisecond sience1, 1970, 00:00:00 GMT)
remark :



SQLite.java

package com.example.sqllite;

import java.util.Date;


import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class SQLite extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textViewMessage = (TextView) findViewById(R.id.textViewMessage);
     try {
   m_locationDB =  openOrCreateDatabase(DB_NAME, MODE_PRIVATE, null);
  } catch (Exception e) {
         textViewMessage.setText(e.getMessage());
        if(m_locationDB!= null)
          m_locationDB.close();
  }
       }
    
    
    private void mFillDbsTable(){
         Date dt = new Date();
         m_locationDB.execSQL("INSERT INTO " +
       TABLE_NAME +
       " Values ('Yosi',33, 44,'Hyarkon 15 Tel Aviv Israel',0);");
         
         m_locationDB.execSQL("INSERT INTO " +
           TABLE_NAME +
           String.format(" Values ('John',11, 15,'Times Square New York U.S.A',%d);",dt.getTime()));
    }

   
    
    public void insertClick(View view)
    {
        try {
         String strSqlStatement;
         strSqlStatement = String.format("CREATE TABLE IF NOT EXISTS %s (%s VARCHAR , %s REAL, %s REAL,%s VARCHAR , %s INTEGER);",
           TABLE_NAME,Const.strUserIdKey,Const.strLongitudeKey,
           Const.strLatitudeKey,Const.strLocationKey,Const.strDateTimeKey);
         m_locationDB.execSQL(strSqlStatement);
         
         mFillDbsTable();
         } catch (Exception se ) {
          textViewMessage.setText(se.getMessage());
        }
        
        }
    
    public void deleteClick(View view)
    {
      try {
       m_locationDB.execSQL(String.format("DELETE FROM  %s;",TABLE_NAME));
          }
      catch (Exception se ) {
          textViewMessage.setText(se.getMessage());
        }
    }
    
    public void readClick(View view)
    {
      try {
       Cursor c = m_locationDB.rawQuery(String.format("SELECT *  FROM %s;",TABLE_NAME),null);
            Date dt = new Date();
            String strRow="";
           textViewMessage.setText("");
           
          if (c != null ) {
           if  (c.moveToFirst()) {
            do {
             String strUserId = c.getString(c.getColumnIndex(Const.strUserIdKey));
                double fLongitude = c.getDouble(c.getColumnIndex(Const.strLongitudeKey));
                double fLatitiud = c.getDouble(c.getColumnIndex(Const.strLatitudeKey));
                String strLocation = c.getString(c.getColumnIndex(Const.strLocationKey));
              dt.setTime(c.getLong(c.getColumnIndex(Const.strDateTimeKey)));
              
             strRow += (String.format("%s,%f,%f,%s,%s\n",
                strUserId,fLongitude,fLatitiud,strLocation,dt.toString()));
              
            }while (c.moveToNext());
            
            textViewMessage.setText(strRow);
           } 
          }
         } catch (Exception se ) {
          textViewMessage.setText(se.getMessage());
        }
    }
    

    private final String DB_NAME = "LocationDbName";
 private final String TABLE_NAME = "Table_1";
    SQLiteDatabase m_locationDB = null;
    TextView textViewMessage;
}


Run the application to create


Click on Insert then click Read :


Click on Delete then click Read :





The following app was published using this post.

Nathan