Pages

Thursday 22 October 2015

Android sql prepared statements, how to prevent sql injection

Generally do not use query directly as string.
Android have default classes so we can use those function to prevent sql injection.

For ex,

To get records from db and suppose you have joins or sub query so default 'query' may no use in such case we will use following funcitons.

String sql = "select *,(select type from table 2 where table2.type=? limit 1) as type from table1 where table1.name like ?";

DatabaseHelper databaseHelper = new DatabaseHelper(getApplicationContext());
SQLiteDatabase sqLiteDatabase = databaseHelper.getWritableDatabase();

Cursor c = sqLiteDatabase.rawQuery(sql, new String[]{"car","m%"});


If we have "IN" clause in sql statement then we may use it following way.

String[] names = { "name1", "name2" }; // do whatever is needed first
String query = "SELECT * FROM table"
    + " WHERE name IN (" + TextUtils.join(",", Collections.nCopies(names.length, "?"))  + ")";
Cursor cursor = mDb.rawQuery(query, names); 


For insert,update and delete we may use default following functions

insert (String table, String nullColumnHack, ContentValues values) ;

update (String table, ContentValues values, String whereClause, String[] whereArgs); 

delete(String table, String whereClause, String[] whereArgs)

query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) // we may use it for simple SELECT query

Monday 12 October 2015

Android play video programmatically

Use following code to play video.

vvVideo = (VideoView) findViewById(R.id.vvVideo);
// use this to play video from raw resource
  vvVideo.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.main));
// use this to play video from url (streaming)
  vvVideo.setVideoURI(Uri.parse("http://..."));
// if possible do not use height to match_parent. It may create problem. I am not sure about this.
// play video from asset
  vvVideo.setVideoURI(Uri.parse("file:///android_asset/path/to/your.mp4"));
// play video from sdcard
  vvVideo.setVideoURI(Uri.fromFile(new File("/sdcard/cats.jpg")));


  vvVideo.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
   @Override
   public void onCompletion(MediaPlayer mp) {
    // video play complete
   }
  });

  vvVideo.start();

use following xml

<VideoView
        android:id="@+id/vvVideo"
        android:layout_width="match_parent"
        android:layout_height="488dp"
        android:layout_centerInParent="true"
        />

add read external storage permission
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>

Monday 5 October 2015

Android add contact intent with save and cancel action

Use following code to open Add contact screen.

Intent i = new Intent(Intent.ACTION_INSERT);
i.setType(ContactsContract.Contacts.CONTENT_TYPE);
if (Integer.valueOf(Build.VERSION.SDK_INT) > 14)
 i.putExtra("finishActivityOnSaveCompleted", true); // Fix for 4.0.3 +
startActivityForResult(i, ADD_CONTACT_REQUEST);

in On activityResult we will get added contact URI .

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == ADD_CONTACT_REQUEST) {

   if (resultCode == RESULT_OK) {
    Log.i("contact ", "Added successfully");
    Log.i("data", data.toString() + ",   uri : " + data.getData().toString());
   } else {
    Log.i("contact ", "contact add cancelled ");
   }
  }
 }

Saturday 3 October 2015

How to generate push notification using compat v7 and manage backstack

Benefit : we no need to worry about android's version. It will automatically handle version relevant changes.

Following code to generate push-notification


public Notification notification;
public NotificationCompat.Builder notificationBuilder;

PendingIntent pIntent;
String message;
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra("from_notification", true);
pIntent = PendingIntent.getActivity(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Bitmap image = BitmapFactory.decodeResource(context.getResources(), R.mipmap.icon);
notificationBuilder = new NotificationCompat.Builder(context)
      .setContentTitle(context.getString(R.string.app_name))
      .setTicker(message)
      .setContentText(message)
      .setStyle(new NotificationCompat.BigTextStyle().bigText(message))
      .setSmallIcon(R.mipmap.icon)
      .setLargeIcon(image)
      .setColor(context.getResources().getColor(R.color.white))
      .setContentIntent(pIntent)
      .setAutoCancel(true);

notification = notificationBuilder.build();
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(id, notification);

Note : if you want to update notification just use notificationBuilder.

notificationBuilder
      .setTicker(message)
      .setContentText(message)
      .setStyle(new NotificationCompat.BigTextStyle().bigText(message))
      .setContentIntent(pIntent)
      .setNumber(totalMessages);
notification = notificationBuilder.build();
notificationManager.notify(id, notification);

id must be same as time of creation.


Manage backstack from push-notification :
For example you are developing chat app.
Suppose You got message from friend as push-notification. And assume that app is not running. Now if you click on notification it will redirect to chat-detail screen. And if you click back button it should go back to Friend list instead of close app . For this we need to manage task backstack using following code.

1) Suppose ChatMessageActivity is child activity and ChatActivity is parent activity. So by click on push we will open ChatMessageActivity and press back we will redirect to ChatActivity. Add parent and child activity in manifest file.


<activity
    android:name=".ChatActivity"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateAlwaysHidden|adjustPan"/>
<!-- Add child activity -->
<activity
    android:name=".ChatMessageActivity"
    android:launchMode="singleTask"
    android:parentActivityName=".ChatActivity"
    android:screenOrientation="portrait">
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.app.ChatActivity"/>
</activity>

1) Create object of TaskStackBuilder.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
 
2) Adds the back stack
stackBuilder.addParentStack(ChatMessageActivity.class);
 
3) Adds the Intent to the top of the stack
stackBuilder.addNextIntent(intent); // Here intent is point to activity which we want to open
 
4) get pending intent from stack builder and use that in above code.
pIntent = stackBuilder.getPendingIntent(id, PendingIntent.FLAG_UPDATE_CURRENT);

Thursday 1 October 2015

Set TextView style (bold or italic) programmatically

use following code to change style

textView.setTypeface(null, Typeface.BOLD_ITALIC);
textView.setTypeface(null, Typeface.BOLD);
textView.setTypeface(null, Typeface.ITALIC);
textView.setTypeface(null, Typeface.NORMAL);


change null to textView.getTypeface() to preserve current typeface

Android date and time formate

Following is example of date and time formate from timeMillis.

Date date = new Date(time millis here);
SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
String receivedTime = formatter.format(date); // hh:mm a format
// it may return like 06:55 PM

SimpleDateFormat dateformatter = new SimpleDateFormat("dd-MM-yyyy");
String receivedDate = dateformatter .format(date);
// it may return like 22-09-2015 


Following link have more format char.
http://developer.android.com/reference/java/text/SimpleDateFormat.html

How do I make links in a TextView clickable?

I'm using only android:autoLink="web" and it works fine. A click on the link opens the browser and shows the correct page.

How to Copy Text to Clip Board in Android?

Use this class to copy text to clipboard

package com.dedoc.app.utils;

import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.util.Log;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created by hb on 01-Oct-15.
 */
public class MyClipboardManager {

 @SuppressLint("NewApi")
 @SuppressWarnings("deprecation")
 public static boolean copyToClipboard(Context context, String text) {
  try {
   int sdk = android.os.Build.VERSION.SDK_INT;
   if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
    android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context
      .getSystemService(context.CLIPBOARD_SERVICE);
    clipboard.setText(text);
   } else {
    android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context
      .getSystemService(context.CLIPBOARD_SERVICE);
    android.content.ClipData clip = android.content.ClipData
      .newPlainText("", text);
    clipboard.setPrimaryClip(clip);
   }
   return true;
  } catch (Exception e) {
   return false;
  }
 }

 @SuppressLint("NewApi")
 public static  String readFromClipboard(Context context) {
  int sdk = android.os.Build.VERSION.SDK_INT;
  if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
   android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context
     .getSystemService(context.CLIPBOARD_SERVICE);
   return clipboard.getText().toString();
  } else {
   ClipboardManager clipboard = (ClipboardManager) context
     .getSystemService(Context.CLIPBOARD_SERVICE);

   // Gets a content resolver instance
   ContentResolver cr = context.getContentResolver();

   // Gets the clipboard data from the clipboard
   ClipData clip = clipboard.getPrimaryClip();
   if (clip != null) {

    String text = null;
    String title = null;

    // Gets the first item from the clipboard data
    ClipData.Item item = clip.getItemAt(0);

    // Tries to get the item's contents as a URI pointing to a note
    Uri uri = item.getUri();

    // If the contents of the clipboard wasn't a reference to a
    // note, then
    // this converts whatever it is to text.
    if (text == null) {
     text = coerceToText(context, item).toString();
    }

    return text;
   }
  }
  return "";
 }

 @SuppressLint("NewApi")
 public static CharSequence coerceToText(Context context, ClipData.Item item) {
  // If this Item has an explicit textual value, simply return that.
  CharSequence text = item.getText();
  if (text != null) {
   return text;
  }

  // If this Item has a URI value, try using that.
  Uri uri = item.getUri();
  if (uri != null) {

   // First see if the URI can be opened as a plain text stream
   // (of any sub-type). If so, this is the best textual
   // representation for it.
   FileInputStream stream = null;
   try {
    // Ask for a stream of the desired type.
    AssetFileDescriptor descr = context.getContentResolver()
      .openTypedAssetFileDescriptor(uri, "text/*", null);
    stream = descr.createInputStream();
    InputStreamReader reader = new InputStreamReader(stream,
      "UTF-8");

    // Got it... copy the stream into a local string and return it.
    StringBuilder builder = new StringBuilder(128);
    char[] buffer = new char[8192];
    int len;
    while ((len = reader.read(buffer)) > 0) {
     builder.append(buffer, 0, len);
    }
    return builder.toString();

   } catch (FileNotFoundException e) {
    // Unable to open content URI as text... not really an
    // error, just something to ignore.

   } catch (IOException e) {
    // Something bad has happened.
    Log.w("ClippedData", "Failure loading text", e);
    return e.toString();

   } finally {
    if (stream != null) {
     try {
      stream.close();
     } catch (IOException e) {
     }
    }
   }

   // If we couldn't open the URI as a stream, then the URI itself
   // probably serves fairly well as a textual representation.
   return uri.toString();
  }

  // Finally, if all we have is an Intent, then we can just turn that
  // into text. Not the most user-friendly thing, but it's something.
  Intent intent = item.getIntent();
  if (intent != null) {
   return intent.toUri(Intent.URI_INTENT_SCHEME);
  }

  // Shouldn't get here, but just in case...
  return "";
 }

}