Implement SwipeRefreshLayout in Android

You might have experienced SwipeRefreshLayout in the last few updates of Chrome browser. You need to swipe from top to halfway and one circle came down with arrow rotating in it. Once you swipe enough it will start refreshing the page and disappear once the page is updated.

It’s SwipeRefreshLayout provided in android-sdk support library v4. Now we see the implementation part for this.

First you have to wrap the element you want to swipe like if you want ListView, GridView or any other view to refresh on swipe, enclose it in SwipeRefreshLayout as below.

<android.support.v4.widget.SwipeRefreshLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/swipe_refresh_layout"
  android:layout_width="match_parent"
  android:layout_height="wrap_content">

  <ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:horizontalSpacing="10dp"
    android:verticalSpacing="10dp" />
</android.support.v4.widget.SwipeRefreshLayout>

Now from the the .java file make the following changes to implement it.

mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
mList = (ListView) findViewById(R.id.list);

mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
  @Override
  public void onRefresh() {
    mSwipeRefreshLayout.setRefreshing(true);
    ( new Handler()).postDelayed(new Runnable() {
      @Override
      public void run() {
        mSwipeRefreshLayout.setRefreshing(false);
      }
    }, 3000);
  }
});

Please leave the comments if you find any problem in above code.

Admob banner ad integration in Andriod Studio

Admob integration becomes very easy with the Android Studio. No need to include .jar file or google play service lib like in Eclipse. Follow the steps to include admob banner to your app.

 

  1. Make sure you’ve updated the “Extra” part of your android sdk. Because we need here Google Repository. Now add the following line to dependencies area of your app’s gradle file.
    compile 'com.google.android.gms:play-services-ads:7.8.0'
    

    After pasting this line, check the bottom part of the android studio where it will suggest you to change the version of google play service ads. Because it might be possible that there will be new version of google play service ads. Now click on “sync now” at the top of android studio and you are ready to go.

  2. Now open the AndroidManifest.xml file and include following in different part of the file. First add two permission in the <manifest> tag and out side of <application> tag.
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    Now add meta data in your <application> tag.

    <meta-data 
    android:name="com.google.android.gms.version" 
    android:value="@integer/google_play_services_version" />

    Now add admob activity in application tag same as meta data.

    <activity 
    android:name="com.google.android.gms.ads.AdActivity" 
    android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" 
    android:theme="@android:style/Theme.Translucent" />
  3. Then add the below xml code in your xml layout file where you want to display ad. It’s a good practice to surround your ad with relative layout. So that you can easily hide the ad until it’s load without affecting the rest of your layout.
    <RelativeLayout 
      xmlns:ads="http://schemas.android.com/apk/res-auto"
      android:id="@+id/rl_ad" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_alignParentBottom="true">
        <com.google.android.gms.ads.AdView 
          android:id="@+id/adView" 
          android:layout_width="wrap_content" 
          android:layout_height="wrap_content" 
          android:layout_centerHorizontal="true" 
          android:layout_alignParentBottom="true" 
          android:visibility="gone" 
          ads:adSize="BANNER" 
          ads:adUnitId="YOUR_AD_UNIT_ID">
        </com.google.android.gms.ads.AdView>
    </RelativeLayout>

    Make sure that you set the visibility of the ad to “gone” in xml file. Because we will hide the ad until it loads completely or there will be blank white space until the ad loads from server and it looks bad. Do not forget to replace YOUR_AD_UNIT_ID with your actual Ad unit id created from admob dashboard.

  4. And finally add the following code in your respective Activity file and that’s it! The ad should be loaded.
    final AdView mAdView = (AdView) findViewById(R.id.adView);
    AdRequest adRequest = new AdRequest.Builder().build();
    mAdView.loadAd(adRequest);
    mAdView.setAdListener(new AdListener() {
      @Override
      public void onAdLoaded() {
        super.onAdLoaded();
        mAdView.setVisibility(View.VISIBLE);
      }
    });

    It will display the ad once it loaded completely.

 
You can check the detailed explanation of everything in this tutorial as well as other information about integration here on Google Developers site and download sample app from there.

If you have any issues in the above code, please write them below in comment section. Thank you.
 

Pick image from gallery before and after KITKAT version in Android

In the android application, we need to pick any image from our gallery. For that android provides some in-built intent action that can fetch us image from gallery. After Android Kitkat, Google made few changes so that we can pick image from different applications.

Screenshot_2016-04-25-00-20-37

The following code will open Default Picker app for KitKat, Lollipop, Marshmallow and Android N users and Gallery app for before Kitkat users to pick image.

Update:
The previous code sometimes failed to get image from external sdcard, Google Drive or sometime from internal storage too. So I did some research and integrate few answers from Stackoverflow and come up with a new solution which able to pick image from every things from that Default Picker App after Kitkat devices displayed in the image.

if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
  intent.addCategory(Intent.CATEGORY_OPENABLE);
  intent.setType("image/*");
  startActivityForResult(Intent.createChooser(intent, "Select Picture"), 1);
} else {
  Intent intent = new Intent();
  intent.setType("image/*");
  intent.setAction(Intent.ACTION_GET_CONTENT);
  startActivityForResult(Intent.createChooser(intent, "Select Picture"), 1);
}

Now after selecting image, we need to handle it properly to display it to ImageView or we need to get it’s path if we want to do any other operation on it. Here is the code for onActivityResult.

@TargetApi(19)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (data != null && data.getData() != null && resultCode == RESULT_OK) {
    boolean isImageFromGoogleDrive = false;
    Uri uri = data.getData();

    if (isKitKat && DocumentsContract.isDocumentUri(TestActivity.this, uri)) {
      if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
        String docId = DocumentsContract.getDocumentId(uri);
        String[] split = docId.split(":");
        String type = split[0];

        if ("primary".equalsIgnoreCase(type)) {
          imgPath = Environment.getExternalStorageDirectory() + "/" + split[1];
        }
        else {
          Pattern DIR_SEPORATOR = Pattern.compile("/");
          Set<String> rv = new HashSet<>();
          String rawExternalStorage = System.getenv("EXTERNAL_STORAGE");
          String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
          String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET");
          if(TextUtils.isEmpty(rawEmulatedStorageTarget))
          {
            if(TextUtils.isEmpty(rawExternalStorage))
            {
              rv.add("/storage/sdcard0");
            }
            else
            {
              rv.add(rawExternalStorage);
            }
          }
          else
          {
            String rawUserId;
            if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
            {
              rawUserId = "";
            }
            else
            {
              String path = Environment.getExternalStorageDirectory().getAbsolutePath();
              String[] folders = DIR_SEPORATOR.split(path);
              String lastFolder = folders[folders.length - 1];
              boolean isDigit = false;
              try
              {
                Integer.valueOf(lastFolder);
                isDigit = true;
              }
              catch(NumberFormatException ignored)
              {
              }
              rawUserId = isDigit ? lastFolder : "";
            }
            if(TextUtils.isEmpty(rawUserId))
            {
              rv.add(rawEmulatedStorageTarget);
            }
            else
            {
              rv.add(rawEmulatedStorageTarget + File.separator + rawUserId);
            }
          }
          if(!TextUtils.isEmpty(rawSecondaryStoragesStr))
          {
            String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
            Collections.addAll(rv, rawSecondaryStorages);
          }
          String[] temp = rv.toArray(new String[rv.size()]);
          for (int i = 0; i < temp.length; i++)   {
            File tempf = new File(temp[i] + "/" + split[1]);
            if(tempf.exists()) {
              imgPath = temp[i] + "/" + split[1];
            }
          }
        }
      }
      else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
        String id = DocumentsContract.getDocumentId(uri);
        Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

        Cursor cursor = null;
        String column = "_data";
        String[] projection = { column };
        try {
          cursor = TestActivity.this.getContentResolver().query(contentUri, projection, null, null,
null);
          if (cursor != null && cursor.moveToFirst()) {
            int column_index = cursor.getColumnIndexOrThrow(column);
            imgPath = cursor.getString(column_index);
          }
        } finally {
          if (cursor != null)
            cursor.close();
        }
      }
      else if("com.android.providers.media.documents".equals(uri.getAuthority())) {
        String docId = DocumentsContract.getDocumentId(uri);
        String[] split = docId.split(":");
        String type = split[0];

        Uri contentUri = null;
        if ("image".equals(type)) {
          contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        } else if ("video".equals(type)) {
          contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        } else if ("audio".equals(type)) {
          contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        }

        String selection = "_id=?";
        String[] selectionArgs = new String[]{ split[1] };

        Cursor cursor = null;
        String column = "_data";
        String[] projection = { column };

        try {
          cursor = TestActivity.this.getContentResolver().query(contentUri, projection, selection, selectionArgs, null);
          if (cursor != null && cursor.moveToFirst()) {
            int column_index = cursor.getColumnIndexOrThrow(column);
            imgPath = cursor.getString(column_index);
          }
        } finally {
          if (cursor != null)
            cursor.close();
        }
      }
      else if("com.google.android.apps.docs.storage".equals(uri.getAuthority()))   {
        isImageFromGoogleDrive = true;
      }
    }
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
      Cursor cursor = null;
      String column = "_data";
      String[] projection = { column };

      try {
        cursor = TestActivity.this.getContentResolver().query(uri, projection, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
          int column_index = cursor.getColumnIndexOrThrow(column);
          imgPath = cursor.getString(column_index);
        }
      }
      finally {
        if (cursor != null)
          cursor.close();
      }
    }
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
      imgPath = uri.getPath();
    }

    if(isImageFromGoogleDrive)  {
      try {
        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
        img.setImageBitmap(bitmap);
      }
      catch (Exception e) {
        e.printStackTrace();
      }
    }
    else    {
      File f = new File(imgPath);
      BitmapFactory.Options bmOptions = new BitmapFactory.Options();
      Bitmap bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(),bmOptions);
      img.setImageBitmap(bitmap);
    }
  }
  super.onActivityResult(requestCode, resultCode, data);
}

Here, images from Google Drive may not be on our device so we directly us InputStream of that image from the Google Drive and show it in the ImageView without getting it’s path. You can save it in your storage if you need to use it for any further requirement.

Please comments below if you find any mistake or having problem in implementing this code.

Download Source Code: https://github.com/dakshbhatt21/a-computer-engineer

Resize image during decode from file to Bitmap in android

java.lang.OutOfMemoryError is the nightmare for any android developer. During image operation we may get this out of memory exception any time because our app uses all the memory allocated by android system to that app so it will give you out of memory error.

We encounter this error when we try to decode larger image using its path of sdcard to Bitmap. So we can skip this error by decoding image to smaller size.

We can avoid this problem or better to say restrict it to a level by creating Bitmap of required size and not the actual size.

Images taken from camera now a days are of more than 3000 and 4000 in resolution. So if we want to display them in GridView or ListView, we have to sample them down so it won’t create OOM or does not hang the UI.

For that we will use sample size to BitmapFactory.Options while decoding the image. It will load your image in smaller size compare to the original image and save your memory.

Google suggest that sample size should be in power of 2 so the below code contains the logic of creating sample size according to the maximum size you provide and then it will load your image with the resolution near to that maximum size.

Here is the direct function I create that you can use in your project by providing the file path of your image. You can find out how get the file path of any image from this article: Pick image from gallery before and after Kitkat version in Android

private Bitmap decodeFile(String imgPath)
{
  Bitmap b = null;
  int max_size = 1000;
  File f = new File(imgPath);
  try {
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    FileInputStream fis = new FileInputStream(f);
    BitmapFactory.decodeStream(fis, null, o);
    fis.close();
    int scale = 1;
    if (o.outHeight > max_size || o.outWidth > max_size)
    {
      scale = (int) Math.pow(2, (int) Math.ceil(Math.log(max_size / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
    }
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    fis = new FileInputStream(f);
    b = BitmapFactory.decodeStream(fis, null, o2);
    fis.close();
  }
  catch (Exception e)
  {
  }
  return b;
}

Share your views in comments!

How to draw Canvas on ImageView and save Canvas as Bitmap and store in sdcard in Android

In some of the application we draw image, text and line on Canvas object in Android. Canvas is the basic component in android for drawing objects on it.

#1 Create Canvas and display it in ImageView.
Now we create a Canvas and display its content in ImageView.

  public class MyCanvas extends View {
    public MyCanvas(Context context) {
      super(context);
      // TODO Auto-generated constructor stub
    }

    @Override
    protected void onDraw(Canvas canvas) {
      // TODO Auto-generated method stub
      super.onDraw(canvas);
      Paint pBackground = new Paint();
      pBackground.setColor(Color.WHITE);
      canvas.drawRect(0, 0, 512, 512, pBackground);
      Paint pText = new Paint();
      pText.setColor(Color.BLACK);
      pText.setTextSize(20);
      canvas.drawText("Sample Text", 100, 100, pText);
    }
  }

Now set this canvas to your ImageView using following code.

  View v = new MyCanvas(getApplicationContext());
  Bitmap bitmap = Bitmap.createBitmap(500/*width*/, 500/*height*/, Bitmap.Config.ARGB_8888);
  Canvas canvas = new Canvas(bitmap);
  v.draw(canvas);
  ImageView iv = (ImageView) findViewById(R.id.iv);
  iv.setImageBitmap(bitmap);

You can see “Sample Text” in ImageView.

#2 Save canvas bitmap to sdcard.
We will save this bitmap to sdcard so all your drawing on canvas will be stored as image.

Bitmap b = null;

//create directory if not exist
File dir = new File("/sdcard/tempfolder/");
if (!dir.exists()) {
  dir.mkdirs();
}

File output = new File(dir, "tempfile.jpg");
OutputStream os = null;

try {
  os = new FileOutputStream(output);
  b.compress(Bitmap.CompressFormat.JPEG, 100, os);
  os.flush();
  os.close();

  //this code will scan the image so that it will appear in your gallery when you open next time
  MediaScannerConnection.scanFile(this,	new String[] { output.toString() }, null,
    new MediaScannerConnection.OnScanCompletedListener() {
      public void onScanCompleted(String path, Uri uri) {
        Log.d("appname", "image is saved in gallery and gallery is refreshed.");
      }
    }
  );
} catch (Exception e) {
}

If you find any problem or doubt, please mention in comments. Do not forget to share!

Download Source Code: https://github.com/dakshbhatt21/a-computer-engineer

Draw circle shape in ImageView in Android

It is better practice to use less number of images in your android project to generate small apk file. This tutorial will help you to draw a circle of your size and set it to your ImageView or to any other View. We will use ShapeDrawable for this purpose.

Now we create ShapeDrawable of OvalShape by writing following line.

ShapeDrawable sd = new ShapeDrawable(new OvalShape());

Now we set height and width parameters of ShapeDrawable object.

sd.setIntrinsicHeight(100);
sd.setIntrinsicWidth(100);

The last thing is to set color to ShapeDrawable object.

sd.getPaint().setColor(Color.parseColor("#abcd123"));

You are ready to set this circle image to your Imageview.

ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setBackground(sd);

Here is the full code.

ShapeDrawable sd = new ShapeDrawable(new OvalShape());
sd.setIntrinsicHeight(100);
sd.setIntrinsicWidth(100);
sd.getPaint().setColor(Color.parseColor("#abcd123"));
ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setBackground(sd);

Add speech recognition to EditText in Android

Now a days many android application has the microphone icon on the right side of EditText. When you click on it, it will ask you to speak the words you want to enter into the EditText. After you speak the word to that dialog it will automatically enter those words into the EditText. Here is the screenshot for that.

speech recognition in android
speech recognition in android

Now to open this dialog, you need to add the below code to your any of the button’s click listener.

int REQUEST_CODE = 1;
String DIALOG_TEXT = "Speech recognition demo";
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, DIALOG_TEXT);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
                   RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, REQUEST_CODE);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US");
startActivityForResult(intent, requestCode);

Now when you click the button this dialog will be open and you can speak to it. Then it will store your speech and return it to you in onActivityResult method as String. Check the following code for it.

String resultSpeech = "";
@Override
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
    super.onActivityResult(requestCode, resultcode, intent);
    ArrayList<String> speech;
    if (resultcode == RESULT_OK) {  
        if (requestCode == REQUEST_CODE) {
            speech = intent.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
            resultSpeech = speech.get(0);
            //you can set resultSpeech to your EditText or TextView
        }
    }
}

Post your queries or questions in comment.

Add “Share Image to Whatsapp” button in Android

In android we can use the default share intent to share our image to the app installed in our app(code is given below), but many times we only need specific application like whatsapp, Facebook, twitter, gmail, etc. So for that we need to do little modification in default intent for sharing.

Default sharing intent in android

    Intent share = new Intent(Intent.ACTION_SEND);
    share.setType("image/jpeg");
    share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/path-to-your-image.jpg"));
    startActivity(Intent.createChooser(share, "Share Image"));

Now if we want to share this image only to any specific app like here is whatsapp, then we need to add filter that provides package name of the app. See the code below.

Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/jpeg");
share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/path-to-your-image.jpg"));
share.setPackage("com.whatsapp");//package name of the app
startActivity(Intent.createChooser(share, "Share Image"));

Now you can set package name of any app that can able to share image like Facebook, twitter, gmail, etc.

Download Source Code: https://github.com/dakshbhatt21/a-computer-engineer

Add “Rate This App” button to your Android App

Many time in out Android app, we need to open our page on Google Play Store within the app. And it is also helpful to encourage people to rate our application. So we can put a button or dialog in our app that user can use to rate our app on Google Play Store.

For that first we check that if the user device has the play store installed in their device or not. Because many device and tablets does not have play store app in their device. So we will use try catch here so if the Play Store is not available we can open the app in browser from catch part.

try {
  startActivity(new Intent(Intent.ACTION_VIEW, 
      Uri.parse("market://details?id=" + getPackageName())));
} 
catch (android.content.ActivityNotFoundException anfe) {
  startActivity(new Intent(Intent.ACTION_VIEW, 
      Uri.parse("http://play.google.com/store/apps/details?id=" + getPackageName())));
}

Now if the device has the play store, we will directly open our app in play store app. If the play store are not found in the device it will open in browser. If you have more than one browser, it will prompt you to choose one.

startActivity(new Intent(Intent.ACTION_VIEW, 
      Uri.parse("http://play.google.com/store/apps/details?id=" + getPackageName())));

Here is the full code that you can use in your button onClick event.

btnRateApp.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    try {
      startActivity(new Intent(Intent.ACTION_VIEW, 
        Uri.parse("market://details?id=" + getPackageName())));
    } 
    catch (android.content.ActivityNotFoundException anfe) {
      startActivity(new Intent(Intent.ACTION_VIEW, 
        Uri.parse("http://play.google.com/store/apps/details?id=" + getPackageName())));
    }
  }
});

I also make a function that you can include in your file and call it from any onClick event of button, make sure you pass the package name as argument.

public void rateApp(String packageName) {
  try {
    startActivity(new Intent(Intent.ACTION_VIEW, 
      Uri.parse("market://details?id=" + packageName)));
  } 
  catch (android.content.ActivityNotFoundException anfe) {
    startActivity(new Intent(Intent.ACTION_VIEW, 
      Uri.parse("http://play.google.com/store/apps/details?id=" + packageName)));
  }
}