Sunday, October 20, 2013

Open URL, Linkify text and Spannable string in Android

In this post I will be going to describe how to open URL in Android and how to link text in different ways using default methods and spannable string.
Below are the different methods to linking text with URL:

1.Android's default method to link text with URL:
Here I added one text box :
<TextView android:id="@+id/text1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/link"/>

For this I am using below string :
 <string name="link"><a href="http://android2011dev.blogspot.com">Go to Android-Dev blog page.</a> </string>

and now will call this string on click of text view:
private void linkWithWeb()
{
TextView text1 = (TextView)findViewById(R.id.text1);
text1.setMovementMethod(LinkMovementMethod.getInstance());
}

It will look like this on device :


Here complete text is linked with URL.

2.In this second option I will link some part of string with URL and make the link text bold.
Add the text box:
<TextView android:id="@+id/text2"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/bold_link"/>

Here is the bold_link string :
    <string name="bold_link">
Go to
<a STYLE="text-decoration:none" href="http://android2011dev.blogspot.com">
<b>Android Dev Blog</b>
</a> page.
</string>

Here we will be going to initialize text box and on click of text box app will launch above URL in web browser. Call below method on click of text box.

private void linkWithBoldWeb() {
TextView text2 = (TextView)findViewById(R.id.text2);
text2.setMovementMethod(LinkMovementMethod.getInstance());
}

It will look like this on device :



3. Change the text font and color of linking text
Text box:
<TextView android:id="@+id/text3" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/link"/>  
Here is the string:
<string name="custom_link_pre">Go to </string>
<string name="custom_link_end">Android Dev Blog </string>
<string name="custom_link_end_text">page.</string>
Here I used three strings, text before link text, link text and finally text after link.

Here is the method to build third text box:

String linkBlog = "http://android2011dev.blogspot.com";
private void cutomizeLink(){
TextView text3 = (TextView)findViewById(R.id.text3);
text3.setMovementMethod(LinkMovementMethod.getInstance());
String strLeading = getXMLString(this, R.string.custom_link_pre);
String strTrailing = getXMLString(this, R.string.custom_link_end);
String strTrailingEnd = getXMLString(this, R.string.custom_link_end_text);

SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
stringBuilder.append(strLeading);
stringBuilder.append(" " + strTrailing);
stringBuilder.append(" " + strTrailingEnd);

stringBuilder.setSpan(new NonUnderlinedClickableSpan() {

@Override
public void onClick(View widget) {

Intent browse = new Intent(Intent.ACTION_VIEW, Uri.parse(linkBlog));
startActivity(browse);
}
}, strLeading.length(), strLeading.length() + strTrailing.length()+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

text3.setText(stringBuilder);
text3.setMovementMethod(LinkMovementMethod.getInstance());

}

getXMLString method is used for int to string conversion.
public static String getXMLString(Context context, int stringID) {

Resources res = context.getResources();
return res.getString(stringID);

}

NonUnderlinedClickableSpan class will be used to change the text color from default blue to megenta and removed underline from lined text.
public class NonUnderlinedClickableSpan extends ClickableSpan {
@Override
public void updateDrawState(TextPaint ds) {

ds.setColor(Color.MAGENTA);
ds.setUnderlineText(false);
ds.setTypeface(Typeface.DEFAULT_BOLD);

}

@Override
public void onClick(View v) {

}
}

It will look like this on device :


4. Here we will see how to multiple links in same string along with I will change the text font and color of linking text same as third option.
Add text box:
<TextView android:id="@+id/text4" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textSize="20sp"
    android:text="@string/custom_link_text"
    android:padding="15dip"/>

Then add string:
<string name="custom_link_text">Go to Google search page and Blog page.</string>

And now initialize and build the text box as per requirement:

String link = "http://www.google.com";
String linkBlog = "http://android2011dev.blogspot.com";

private void customLink(){
TextView text4 = (TextView)findViewById(R.id.text4);
text4.setMovementMethod(LinkMovementMethod.getInstance());
String customStr = getXMLString(this, R.string.custom_link_text);
String strLeading = customStr.substring(0, customStr.indexOf("Google"));
String strTrailing = customStr.substring(customStr.indexOf("Google"), (customStr.indexOf("search") - 1));
String strTrailingEnd = customStr.substring(0, (customStr.indexOf("Blog")));
String strTrailingEnd1 = customStr.substring((customStr.lastIndexOf("page")));
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
stringBuilder.append(customStr);

stringBuilder.setSpan(new NonUnderlinedClickableSpan() {

@Override
public void onClick(View widget) {

Intent browse = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
startActivity(browse);
}
},strLeading.length(), 
strLeading.length() + strTrailing.length()+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

stringBuilder.setSpan(new NonUnderlinedClickableSpan() {

@Override
public void onClick(View widget) {

Intent browse = new Intent(Intent.ACTION_VIEW, Uri.parse(linkBlog));
startActivity(browse);
}
},strTrailingEnd.length(), 
strTrailingEnd.length() + strTrailingEnd1.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

text4.setText(stringBuilder);
text4.setMovementMethod(LinkMovementMethod.getInstance());

}
Here is the result :

On click of  'Google' app will navigate to "http://www.google.com" page and on click 'Blog' navigate to "http://android2011dev.blogspot.com" page.

That's it
Here is the complete source code :
Activity file:
public class SpannableStringActivity extends Activity {

String link = "http://www.google.com";
String linkBlog = "http://android2011dev.blogspot.com";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
linkWithWeb();
linkWithBoldWeb();
cutomizeLink();
customLink();
}
/*
* Used to linking with web
*/
private void linkWithWeb() {
TextView text1 = (TextView)findViewById(R.id.text1);
text1.setMovementMethod(LinkMovementMethod.getInstance());
}

/*
* Link with bold font
*/
private void linkWithBoldWeb() {
TextView text2 = (TextView)findViewById(R.id.text2);
text2.setMovementMethod(LinkMovementMethod.getInstance());
}

/*
* Change the text font and color of linking text
*/
private void cutomizeLink(){
TextView text3 = (TextView)findViewById(R.id.text3);
text3.setMovementMethod(LinkMovementMethod.getInstance());
String strLeading = getXMLString(this, R.string.custom_link_pre);
String strTrailing = getXMLString(this, R.string.custom_link_end);
String strTrailingEnd = getXMLString(this, R.string.custom_link_end_text);

SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
stringBuilder.append(strLeading);
stringBuilder.append(" " + strTrailing);
stringBuilder.append(" " + strTrailingEnd);

stringBuilder.setSpan(new NonUnderlinedClickableSpan() {

@Override
public void onClick(View widget) {

Intent browse = new Intent(Intent.ACTION_VIEW, Uri.parse(linkBlog));
startActivity(browse);
}
}, strLeading.length(), strLeading.length() + strTrailing.length()+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

text3.setText(stringBuilder);
text3.setMovementMethod(LinkMovementMethod.getInstance());
}
/*
*  Change the text font and color of linking text. Add multiple links in to the single sentence.
*/
private void customLink(){
TextView text4 = (TextView)findViewById(R.id.text4);
text4.setMovementMethod(LinkMovementMethod.getInstance());
String customStr = getXMLString(this, R.string.custom_link_text);
String strLeading = customStr.substring(0, customStr.indexOf("Google"));
String strTrailing = customStr.substring(customStr.indexOf("Google"), (customStr.indexOf("search") - 1));
String strTrailingEnd = customStr.substring(0, (customStr.indexOf("Blog")));
String strTrailingEnd1 = customStr.substring((customStr.lastIndexOf("page")));
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
stringBuilder.append(customStr);
stringBuilder.setSpan(new NonUnderlinedClickableSpan() {

@Override
public void onClick(View widget) {

Intent browse = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
startActivity(browse);
}
},strLeading.length(), 
strLeading.length() + strTrailing.length()+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

stringBuilder.setSpan(new NonUnderlinedClickableSpan() {

@Override
public void onClick(View widget) {

Intent browse = new Intent(Intent.ACTION_VIEW, Uri.parse(linkBlog));
startActivity(browse);
}
},strTrailingEnd.length(), 
strTrailingEnd.length() + strTrailingEnd1.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

text4.setText(stringBuilder);
text4.setMovementMethod(LinkMovementMethod.getInstance());
}

public class NonUnderlinedClickableSpan extends ClickableSpan {
@Override
public void updateDrawState(TextPaint ds) {

ds.setColor(Color.MAGENTA);
ds.setUnderlineText(false);
ds.setTypeface(Typeface.DEFAULT_BOLD);
}

@Override
public void onClick(View v) {

}
}

public static String getXMLString(Context context, int stringID) {

Resources res = context.getResources();
return res.getString(stringID);
}
}

main.xml file :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView android:id="@+id/text1" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textSize="20sp"
    android:text="@string/link"
    android:padding="15dip"/>

<TextView android:id="@+id/text2" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textSize="20sp"
     android:text="@string/bold_link"
    android:padding="15dip"/>
    
<TextView android:id="@+id/text3" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textSize="20sp"
    android:text="@string/link"
    android:padding="15dip"/>  
    
    
 <TextView android:id="@+id/text4" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textSize="20sp"
    android:text="@string/custom_link_text"
    android:padding="15dip"/>       
</LinearLayout>

string.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, SpannableStringActivity!</string>
    <string name="app_name">SpannableString</string>
    <string name="link"><a href="http://android2011dev.blogspot.com">Go to Android-Dev blog page.</a> </string>
    <string name="bold_link">
Go to 
<a STYLE="text-decoration:none" href="http://android2011dev.blogspot.com">
<b>Android Dev Blog</b>
</a> page.
</string>
<string name="custom_link_pre">Go to </string>
<string name="custom_link_end">Android Dev Blog </string>
<string name="custom_link_end_text">page.</string>
<string name="custom_link_text">Go to Google search page and Blog page.</string>
</resources>

Monday, October 14, 2013

Outgoing SMS details

In my previous post you can find how to read incoming SMS content programmatically.
In this post I will give you information about how to read outgoing SMS content. It's same as incoming SMS data reading, just need use different URI to read outgoing SMS content.
To read outgoing SMS content first add user permission:
 <uses-permission android:name="android.permission.READ_SMS"/>

Then call below method :

public StringBuffer getOutgoingSMSContent() {

ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://sms/sent/");
StringBuffer messagedata = new StringBuffer();
int count = 0;

Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor.getCount() != 0) {
if (cursor.moveToFirst()) {
do {
messagedata.append("Outgoing message count: " + (count +1) + "\n");
for (int m = 0; m < cursor.getColumnCount(); m++) {
if (cursor.getColumnName(m).equalsIgnoreCase("address")
|| cursor.getColumnName(m).equalsIgnoreCase("date")
|| cursor.getColumnName(m).equalsIgnoreCase("body")
|| cursor.getColumnName(m).equalsIgnoreCase("type"))
{
messagedata.append(cursor.getColumnName(m) + "  : "
+ cursor.getString(m));
messagedata.append("\n");
}
}
messagedata.append("\n");
count++;
} while (cursor.moveToNext());
}
}
cursor.close();
cursor = null;
return messagedata;
}

This method will return list of all outgoing SMS content.

Result will look something like this :


Here 'address' is mobile number of receiver.
'date' is message sent time in milliseconds.
'type' is message type incoming/outgoing. 2 is outgoing message type.
'body' is message text.











Incoming SMS details

Using Android API's user can read incoming SMS message content programmatically.
To get SMS content first add below user permission in manifest file:
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>

Then call below method from activity class:

public StringBuffer getIncomingSMSContent() {

ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://sms/inbox/");
StringBuffer messagedata = new StringBuffer();
int count = 0;
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor.getCount() != 0) {
if (cursor.moveToFirst()) {
do {
messagedata.append("Incoming message count: " + (count +1) + "\n");
for (int m = 0; m < cursor.getColumnCount(); m++) {
if (cursor.getColumnName(m).equalsIgnoreCase("address")
|| cursor.getColumnName(m).equalsIgnoreCase("date")
|| cursor.getColumnName(m).equalsIgnoreCase("body")
|| cursor.getColumnName(m).equalsIgnoreCase("type"))
{
messagedata.append(cursor.getColumnName(m) + "  : "
+ cursor.getString(m));
messagedata.append("\n");
}
}
messagedata.append("\n");
count++;
} while (cursor.moveToNext());
}
}
cursor.close();
cursor = null;
return messagedata;
}

This method will return list of all incoming message content from inbox.

Here is the result :


In above result screen, 
address : mobile number from which device received message
date : message received time in milliseconds
type : message type incoming/outgoing. Type 1 indicates as incoming message type
body : message text

Saturday, August 20, 2011

Get Android phone call history/log programmatically

To get call history programmatically first add read conact permission in Manifest file :
<uses-permission android:name="android.permission.READ_CONTACTS" />

Create xml file. Add the below code in xml file :

<Linearlayout android:layout_height="fill_parent"
 android:layout_width="fill_parent"
android:orientation="vertical">
<Textview android:id="@+id/call"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
</Textview>
</Linearlayout>

Now call the getCallDetails() method in java class :

private void getCallDetails() {

StringBuffer sb = new StringBuffer();
Cursor managedCursor = managedQuery( CallLog.Calls.CONTENT_URI,null, null,null, null);
int number = managedCursor.getColumnIndex( CallLog.Calls.NUMBER );
int type = managedCursor.getColumnIndex( CallLog.Calls.TYPE );
int date = managedCursor.getColumnIndex( CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex( CallLog.Calls.DURATION);
sb.append( "Call Details :");
while ( managedCursor.moveToNext() ) {
String phNumber = managedCursor.getString( number );
String callType = managedCursor.getString( type );
String callDate = managedCursor.getString( date );
Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = managedCursor.getString( duration );
String dir = null;
int dircode = Integer.parseInt( callType );
switch( dircode ) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;

case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;

case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
sb.append( "\nPhone Number:--- "+phNumber +" \nCall Type:--- "+dir+" \nCall Date:--- "+callDayTime+" \nCall duration in sec :--- "+callDuration );
sb.append("\n----------------------------------");
}
managedCursor.close();
call.setText(sb);
}

Using this application user can access his call history. It show call number,call type i.e. incoming/outgoing/missed call, call date-time and call duration.
Here is the output where user can see all details :







Thursday, July 28, 2011

Delete contacts from Android device

We can delete the contacts from android device programmatically.

Declare the permissions in manifest file:



Using Android 1.6 :
getContentResolver().delete(Contacts.People.CONTENT_URI,null,null);

Using Android 2.0 and above:
getContentResolver().delete(ContactsContract.RawContacts.CONTENT_URI,null,
null);

Wednesday, June 22, 2011

Installed application information in Android

Using PackageManager we can get the all installed application details in Android device like package name,version code,version info,class name etc.

Code snippet:

PackageManager pckMgr;
pckMgr = getPackageManager();
List appInfo = pckMgr.getInstalledPackages(PackageManager.GET_ACTIVITIES);
Log.i("Number of Applications are installed " ,":"+ appInfo.size());
for ( int cnt=0; cnt < appInfo.size(); cnt++){

Log.i("Package name ",":"+appInfo.get(cnt).packageName);
Log.i("Application name ",":"+appInfo.get(cnt).applicationInfo.loadLabel(getPackageManager()));
Log.i("Version code ",":"+appInfo.get(cnt).versionCode);
Log.i("Version name ",":"+appInfo.get(cnt).versionName);

}

Tuesday, February 2, 2010

Android based Acer Liquid Launched in India

Acer Liquid launcehed in India with Android1.6 high defination smartphone.
It is VGA smartphone with latest Android1.6 OS.
Features :
multimidia
web browsing
video streaming
smart integration of Facebook, Twitter, Youtube, Picasa and Flickr in the address book
MP3 (MP3/WAV/WMA/eAAC+ player)
MP4 (MP4/WMV/H.264/H.263 player)
messaging (SMS (threaded view), MMS, Email, Instant Messaging)
browser (HTML)
memory of 256MB RAM
512MB ROM
microSD card slot of up to 32GB.
3.5mm audio jack
vibration
WAV ringtones
3G (HSDPA 7.2 Mbps, HSUPA 2.0 Mbps) enabled phone
weighs 135g with 115 x 62.5 x 12.5 mm dimensions
5-megapixel camera
GPS
HSDPA connectivity
RS.24,990 with 2GB micro-SD