Monday, 12 August 2013

Efficient android image downloader to over come error java.lang.OutOfMemoryError: bitmap size exceeds VM budget

ImageDownloader :

public class ImageDownloader {

Map<String,Bitmap> imageCache;
private Bitmap defaultIcon;

public ImageDownloader(){
imageCache = new HashMap<String, Bitmap>();

}

//download function
public void download(String url, ImageView imageView,Bitmap defaultImg) {
    if (cancelPotentialDownload(url, imageView)) {
   
    this.defaultIcon=defaultImg;
    //Caching code right here
    String filename = String.valueOf(url.hashCode());
    File f = new File(getCacheDirectory(imageView.getContext()), filename);

     // Is the bitmap in our memory cache?
    Bitmap bitmap = null;
   
     bitmap = (Bitmap)imageCache.get(f.getPath());
   
     if(bitmap == null){
   
     bitmap = BitmapFactory.decodeFile(f.getPath());
   
     if(bitmap != null){
     imageCache.put(f.getPath(), bitmap);
     }
   
     }
     //No? download it
     if(bitmap == null){
     BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
   
     DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task,null,defaultImg);
     imageView.setImageDrawable(downloadedDrawable);
     imageView.setBackgroundDrawable(null);
     task.execute(url);
     }else{
     //Yes? set the image
     imageView.setImageBitmap(bitmap);
     imageView.setBackgroundDrawable(null);
     }
    }
}

//cancel a download (internal only)
private static boolean cancelPotentialDownload(String url, ImageView imageView) {
   BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

   if (bitmapDownloaderTask != null) {
       String bitmapUrl = bitmapDownloaderTask.url;
       if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
           bitmapDownloaderTask.cancel(true);
       } else {
           // The same URL is already being downloaded.
           return false;
       }
   }
   return true;
}

//gets an existing download if one exists for the imageview
private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
   if (imageView != null) {
       Drawable drawable = imageView.getDrawable();
       if (drawable instanceof DownloadedDrawable) {
           DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
           return downloadedDrawable.getBitmapDownloaderTask();
       }
   }
   return null;
}

//our caching functions
// Find the dir to save cached images
private static File getCacheDirectory(Context context){
String sdState = android.os.Environment.getExternalStorageState();
File cacheDir;
   
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = android.os.Environment.getExternalStorageDirectory();

//TODO : Change your diretcory here
cacheDir = new File(sdDir,"data/tac/images");
}
else
cacheDir = context.getCacheDir();

if(!cacheDir.exists())
cacheDir.mkdirs();
return cacheDir;
}

private void writeFile(Bitmap bmp, File f) {
 FileOutputStream out = null;

 try {
   out = new FileOutputStream(f);
   bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
 } catch (Exception e) {
   e.printStackTrace();
 }
 finally {
   try { if (out != null ) out.close(); }
   catch(Exception ex) {}
 }
}
///////////////////////

//download asynctask
    public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
    private String url;
        private final WeakReference<ImageView> imageViewReference;

        public BitmapDownloaderTask(ImageView imageView) {
            imageViewReference = new WeakReference<ImageView>(imageView);
   
        }

        @Override
        // Actual download method, run in the task thread
        protected Bitmap doInBackground(String... params) {
             // params comes from the execute() call: params[0] is the url.
        url = (String)params[0];
             return downloadBitmap(params[0]);
        }

        @Override
        // Once the image is downloaded, associates it to the imageView
        protected void onPostExecute(Bitmap bitmap) {
            if (isCancelled()) {
                bitmap = null;
            }

            if (imageViewReference != null) {
                ImageView imageView = imageViewReference.get();
                BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
                // Change bitmap only if this process is still associated with it
                if (this == bitmapDownloaderTask) {
                    imageView.setImageBitmap(bitmap);
                   
                    //cache the image
                   
                   
                    String filename = String.valueOf(url.hashCode());
            File f = new File(getCacheDirectory(imageView.getContext()), filename);
           
            imageCache.put(f.getPath(), bitmap);
           
                    writeFile(bitmap, f);
                }
            }
        }
       
       
    }
   
//    static class DownloadedDrawable extends ColorDrawable {
//        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
//
//        public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
//          super(Color.TRANSPARENT);
//            bitmapDownloaderTaskReference =
//                new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
//        }
//
//        public BitmapDownloaderTask getBitmapDownloaderTask() {
//            return bitmapDownloaderTaskReference.get();
//        }
//    }
   
    private static class DownloadedDrawable extends BitmapDrawable {
        private final WeakReference<BitmapDownloaderTask>
           bitmapDownloaderTaskReference;

        private DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask,
           Resources resources, Bitmap bitmap) {
            super(resources, bitmap); // you'll have to provide these
            bitmapDownloaderTaskReference =
                new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
        }

        public BitmapDownloaderTask getBitmapDownloaderTask() {
            return bitmapDownloaderTaskReference.get();
        }
    }
   
    //the actual download code
    static Bitmap downloadBitmap(String url) {
    url=url.replace(" ", "%20");
    HttpParams params = new BasicHttpParams();
    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
    HttpClient client = new DefaultHttpClient(params);
        final HttpGet getRequest = new HttpGet(url);

        try {
            HttpResponse response = client.execute(getRequest);
            final int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
                return null;
            }
           
            final HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = null;
                try {
                    inputStream = entity.getContent();
                    final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    return bitmap;
                } finally {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                    entity.consumeContent();
                }
            }
        } catch (Exception e) {
            // Could provide a more explicit error message for IOException or IllegalStateException
            getRequest.abort();
            Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString());
        } finally {
            if (client != null) {
                //client.close();
            }
        }
        return null;
    }
}

How to use:


ImageDownloader downloader = new ImageDownloader();

downloader.download(stringUrl,
imageViewProfile, defaultImgBitmap);

Android interview questions




  • What is Android?

    Android is a software stack for mobile devices that includes an operating system, middleware and key applications. The application runs in its own process and its own instance of Dalvik virtual machine. Many virtual machines are efficiently by a DVM device. DVM run Java bytecode languages ​​which later turns into. DEX files format.

    History


    Android, Inc. was founded in Palo Alto, California in October 2003 by Andy Rubin (co-founder of Danger), Rich Miner (co-founder of Wildfire Communications, Inc.), Nick Sears (once VP at T-Mobile), and Chris White (headed design and interface development at WebTV) to develop, in Rubin's words "smarter mobile devices that are more aware of its owner's location and preferences". The early intentions of the company were to develop an advanced operating system for digital cameras, when it was realised that the market for the devices was not large enough, and diverted their efforts to producing a smartphone operating system to rival those of Symbian and Windows Mobile (Apple's iPhone had not been released at the time). Despite the past accomplishments of the founders and early employees, Android Inc. operated secretly, revealing only that it was working on software for mobile phones. That same year, Rubin ran out of money. Steve Perlman, a close friend of Rubin, brought him $10,000 in cash in an envelope and refused a stake in the company .

     Android Architecture?

    Android Architecture is made up of 4 key components:
    - Linux Kernel
    - Libraries
    - Android Framework
    - Android Applications

    Describe Activities.

    Activities are what you refer to as the window to a user interface. Just as you create windows in order to display output or to ask for an input in the form of dialog boxes, activities play the same role, though it may not always be in the form of a user interface.

    What are the core components under the Android application architecture?

    There are 5 key components under the Android application architecture:
    - services
    - intent
    - resource externalization
    - notifications
    - content providers

    What are Intents?

    Intents displays notification messages to the user from within the Android enabled device. It can be used to alert the user of a particular state that occurred. Users can be made to respond to intents.

    What are the core components under the Android application architecture?

    There are 5 key components under the Android application architecture:
    - services
    - intent
    - resource externalization
    - notifications
    - content providers

     Differentiate Activities from Services.

    Activities can be closed, or terminated anytime the user wishes. On the other hand, services are designed to run behind the scenes, and can act independently. Most services run continuously, regardless of whether there are certain or no activities being executed.

     What items are important in every Android project?

    These are the essential items that are present each time an Android project is created:
    - AndroidManifest.xml
    - build.xml
    - bin/
    - src/
    - res/
    - assets/

    What is ANR?

    ANR is short for Application Not Responding. This is actually a dialog that appears to the user whenever an application have been unresponsive for a long period of time.

     How can the ANR be prevented?

    One technique that prevents the Android system from concluding a code that has been responsive for a long period of time is to create a child thread. Within the child thread, most of the actual workings of the codes can be placed, so that the main thread runs with minimal periods of unresponsive times.

     When does ANR occur?

    The ANR dialog is displayed to the user based on two possible conditions. One is when there is no response to an input event within 5 seconds, and the other is when a broadcast receiver is not done executing within 10 seconds.

    What is AIDL?

    AIDL, or Android Interface Definition Language, handles the interface requirements between a client and a service so both can communicate at the same level through interprocess communication or IPC. This process involves breaking down objects into primitives that Android can understand. This part is required simply because a process cannot access the memory of the other process.

    What data types are supported by AIDL?

    AIDL has support for the following data types:
    -string
    -charSequence
    -List
    -Map

    -all native Java data types like int,long, char and Boolean

Wednesday, 31 July 2013

Detect Android ACTION_SCREEN_OFF ,ACTION_SCREEN_ON and ACTION_USER_PRESENT

1.MainActivity

To start service


public class MainActivity extends Activity {

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

startService(new Intent(getApplicationContext(), LockService.class));


   }
}

2.Lock service 

   To run receiver 
public class LockService extends Service {

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
final BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
return super.onStartCommand(intent, flags, startId);
}
public class LocalBinder extends Binder {
LockService getService() {
return LockService.this;
}
}
}

3.Screen lock receiver 


public class ScreenReceiver extends BroadcastReceiver {

    public static boolean wasScreenOn = true;

    @Override
    public void onReceive(final Context context, final Intent intent) {
    Log.e("test","onReceive");
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            // do whatever you need to do here
            wasScreenOn = false;
            Log.e("test","wasScreenOn"+wasScreenOn);
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            // and do whatever you need to do here
            wasScreenOn = true;
            Log.e("test","wasScreenOn"+wasScreenOn);
        }else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)){
            Log.e("test","userpresent");
        }
    }
}

4.Manifest file


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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.screenlock.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="com.example.screenlock.LockService" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </service>
    </application>

Friday, 14 June 2013

Call REST webservices with header parameter in android async task

1.Async task 

public static class CurrentUserTask extends AsyncTask<Void, Void, Object> {
private String TAG = "User Profile";
private UserListener userListener;
private Context context;

public CurrentUserTask(Context context, UserListener listener) {
this.context = context;
this.userListener = listener;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
}

@Override
protected Object doInBackground(Void... params) {

try {

//Create constants for URL and content type 


HttpGet httpGet = new HttpGet(Constants.BASE_URL
+ Constants.USER_URL);
Log.d(TAG, "Profile URL" + Constants.BASE_URL
+ Constants.USER_URL);

httpGet.setHeader(Constants.CONTENT_TYPE,
Constants.CONTENT_TYPE_JSON);
httpGet.setHeader(Constants.AUTHORIZATION,
PreferenceManager.getAuthorization(context));

DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResponse = httpClient.execute(httpGet);

String response = IOUtils.streamToString(httpResponse
.getEntity().getContent(), null);
Log.d(TAG, "response:" + response);
switch (httpResponse.getStatusLine().getStatusCode()) {
case HttpStatus.SC_OK:
case HttpStatus.SC_CREATED:
Gson gson = new Gson();
JSONObject jsonObject = new JSONObject(response);
Profile contact = gson.fromJson(jsonObject.toString(),
Profile.class);
PreferenceManager.setCurrentUser(context, response);
return contact;

case HttpStatus.SC_INTERNAL_SERVER_ERROR:
return null;
case HttpStatus.SC_UNAUTHORIZED:
return null;
default:
return null;
}

} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
return null;
} catch (ClientProtocolException ex) {
ex.printStackTrace();
return null;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}

@Override
protected void onPostExecute(Object contact) {
super.onPostExecute(contact);
try {
if (contact == null)
userListener.onError();
else {
userListener.onSuccess((Profile) contact);
}
} catch (Exception e) {
e.printStackTrace();
userListener.onError();
}
}

}


2.Create pojo class for Profile (entity class)
 with getter and setter methods

eg.
public class Profile implements Serializable {

private static final long serialVersionUID = 1L;
private String email;
private String dateOfBirth;

//getter and setter methods here......

}

3.Custom error message class 

public class ErrorMessages extends Exception {

public ErrorMessages(String message) {
super(message);
}

public static String MESSAGE_NETWORK="Please check network connection.";
public static String MESSAGE_INTERNAL_SERVER_ERROR="Error occurred at server, please try again.";
}


4.static method to convert stream to string. 


public static String streamToString(InputStream is, Charset cs)
throws IOException, Exception {
BufferedReader br;
if (cs == null) {
br = new BufferedReader(new InputStreamReader(is));
} else {
br = new BufferedReader(new InputStreamReader(is, cs));
}
StringBuffer sb = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
return sb.toString();
}

5.Custom interface to handel response call back

public static interface UserListener {
public void onSuccess(Profile profile);

public void onUnauthorized();

public void onError();
}

6.call sync task into activity

//show progress dialog here... 

new UserTask.CurrentUserTask(context, userListener).execute();

//call back method into activity (methods of Interface)


/**
* current user listener
*/

UserListener userListener = new UserListener() {

@Override
public void onUnauthorized() {
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();

Toast.makeText(context, R.string.msg_error, Toast.LENGTH_SHORT)
.show();
}

@Override
public void onSuccess(Profile profile) {

if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();

//Success 

}

@Override
public void onError() {
Log.d(TAG, "userListener on error");
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();
}
};

Splash activity or Welcome page in android

public class SplashActivity extends Activity {
private long time = 2000; //time
private Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_splash);

Handler handler = new Handler();

// run a thread after 2 seconds to start the home screen
handler.postDelayed(new Runnable() {

@Override
public void run() {
finish();
Intent intent = new Intent(context, LoginActivity.class);
context.startActivity(intent);
}

}, time);
}

}