Wednesday, October 31, 2012

List Images with thumbnails, implementing custom SimpleCursorAdapter.

Last exercise demonstrate how to get Thumbnails. Now we can implement our custom SimpleCursorAdapter to list the Images in MediaStore.Images.Media with associated Thumbnail if exist.

List Images with thumbnails, implementing custom SimpleCursorAdapter.


Create a file, /res/layout/row.xml, to define the layout of the rows in the ListView.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    
    <ImageView
        android:id="@+id/thumb"
        android:layout_width="100dp"
        android:layout_height="100dp"/>
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>


Modify the code to implement MyAdapter class extends SimpleCursorAdapter.
package com.example.androidlistimages;

import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class MainActivity extends ListActivity {
 
 //define source of MediaStore.Images.Media, internal or external storage
 final Uri sourceUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
 final Uri thumbUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
 final String thumb_DATA = MediaStore.Images.Thumbnails.DATA;
 final String thumb_IMAGE_ID = MediaStore.Images.Thumbnails.IMAGE_ID;

 //SimpleCursorAdapter mySimpleCursorAdapter;
 MyAdapter mySimpleCursorAdapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        
        String[] from = {MediaStore.MediaColumns.TITLE};
        int[] to = {android.R.id.text1};

        CursorLoader cursorLoader = new CursorLoader(
          this, 
          sourceUri, 
          null, 
          null, 
          null, 
          MediaStore.Audio.Media.TITLE);
        
        Cursor cursor = cursorLoader.loadInBackground();
        
        mySimpleCursorAdapter = new MyAdapter(
          this, 
          android.R.layout.simple_list_item_1, 
          cursor, 
          from, 
          to, 
          CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        
        setListAdapter(mySimpleCursorAdapter);
        
        getListView().setOnItemClickListener(myOnItemClickListener);
    }
    
    OnItemClickListener myOnItemClickListener
    = new OnItemClickListener(){

  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position,
    long id) {
   Cursor cursor = mySimpleCursorAdapter.getCursor();
   cursor.moveToPosition(position);

   int int_ID = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media._ID));
   getThumbnail(int_ID);
  }};
 
 private Bitmap getThumbnail(int id){

  String[] thumbColumns = {thumb_DATA, thumb_IMAGE_ID};

  CursorLoader thumbCursorLoader = new CursorLoader(
          this, 
          thumbUri, 
    thumbColumns, 
    thumb_IMAGE_ID + "=" + id, 
    null, 
    null);
        
        Cursor thumbCursor = thumbCursorLoader.loadInBackground();
        
        Bitmap thumbBitmap = null;
        if(thumbCursor.moveToFirst()){
   int thCulumnIndex = thumbCursor.getColumnIndex(thumb_DATA);
   
   String thumbPath = thumbCursor.getString(thCulumnIndex);
   
   Toast.makeText(getApplicationContext(), 
     thumbPath, 
     Toast.LENGTH_LONG).show();
   
   thumbBitmap = BitmapFactory.decodeFile(thumbPath);
   
   //Create a Dialog to display the thumbnail
   AlertDialog.Builder thumbDialog = new AlertDialog.Builder(MainActivity.this);
   ImageView thumbView = new ImageView(MainActivity.this);
   thumbView.setImageBitmap(thumbBitmap);
   LinearLayout layout = new LinearLayout(MainActivity.this);
         layout.setOrientation(LinearLayout.VERTICAL);
         layout.addView(thumbView);
         thumbDialog.setView(layout);
         thumbDialog.show();
   
  }else{
   Toast.makeText(getApplicationContext(), 
     "NO Thumbnail!", 
     Toast.LENGTH_LONG).show();
  }
        
        return thumbBitmap;
 }
 
 public class MyAdapter extends SimpleCursorAdapter{
  
  Cursor myCursor;
     Context myContext;

  public MyAdapter(Context context, int layout, Cursor c, String[] from,
    int[] to, int flags) {
   super(context, layout, c, from, to, flags);
   
   myCursor = c;
      myContext = context;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   View row = convertView;
   if(row==null){
    LayoutInflater inflater=getLayoutInflater();
    row=inflater.inflate(R.layout.row, parent, false); 
   }
   
   ImageView thumbV = (ImageView)row.findViewById(R.id.thumb);
   TextView textV = (TextView)row.findViewById(R.id.text);
   
   myCursor.moveToPosition(position);
   
   int myID = myCursor.getInt(myCursor.getColumnIndex(MediaStore.Images.Media._ID));
   String myData = myCursor.getString(myCursor.getColumnIndex(MediaStore.Images.Media.DATA));
   textV.setText(myData);
   
   String[] thumbColumns = {thumb_DATA, thumb_IMAGE_ID};
   CursorLoader thumbCursorLoader = new CursorLoader(
     myContext, 
           thumbUri, 
     thumbColumns, 
     thumb_IMAGE_ID + "=" + myID, 
     null, 
     null);
   Cursor thumbCursor = thumbCursorLoader.loadInBackground();
   
   Bitmap myBitmap = null;
         if(thumbCursor.moveToFirst()){
    int thCulumnIndex = thumbCursor.getColumnIndex(thumb_DATA);
    String thumbPath = thumbCursor.getString(thCulumnIndex);
    myBitmap = BitmapFactory.decodeFile(thumbPath);
    thumbV.setImageBitmap(myBitmap);
   }
   
   return row;
  }
  
 }
}


download filesDownload the files.

Related:
- List MediaStore.Images.Thumbnails in GridView, with custom SimpleCursorAdapter.


Tuesday, October 30, 2012

Get thumbnails (in MediaStore.Images.Thumbnails) associated with MediaStore.Images.Media

Last exercise demonstrate how to "Get path of image in MediaStore.Images.Media from SimpleCursorAdapter". In this exercise, the associated thumbnails (in MediaStore.Images.Thumbnails) can be retrieved via the Cursor.

Get thumbnails (in MediaStore.Images.Thumbnails) associated with MediaStore.Images.Media


package com.example.androidlistimages;

import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class MainActivity extends ListActivity {
 
 //define source of MediaStore.Images.Media, internal or external storage
 final Uri sourceUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
 final Uri thumbUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
 final String thumb_DATA = MediaStore.Images.Thumbnails.DATA;
 final String thumb_IMAGE_ID = MediaStore.Images.Thumbnails.IMAGE_ID;

 SimpleCursorAdapter mySimpleCursorAdapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        
        String[] from = {MediaStore.MediaColumns.TITLE};
        int[] to = {android.R.id.text1};

        CursorLoader cursorLoader = new CursorLoader(
          this, 
          sourceUri, 
          null, 
          null, 
          null, 
          MediaStore.Audio.Media.TITLE);
        
        Cursor cursor = cursorLoader.loadInBackground();
        
        mySimpleCursorAdapter = new SimpleCursorAdapter(
          this, 
          android.R.layout.simple_list_item_1, 
          cursor, 
          from, 
          to, 
          CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        
        setListAdapter(mySimpleCursorAdapter);
        
        getListView().setOnItemClickListener(myOnItemClickListener);
    }
    
    OnItemClickListener myOnItemClickListener
    = new OnItemClickListener(){

  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position,
    long id) {
   Cursor cursor = mySimpleCursorAdapter.getCursor();
   cursor.moveToPosition(position);

   int int_ID = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media._ID));
   getThumbnail(int_ID);
  }};
 
 private Bitmap getThumbnail(int id){

  String[] thumbColumns = {thumb_DATA, thumb_IMAGE_ID};

  CursorLoader thumbCursorLoader = new CursorLoader(
          this, 
          thumbUri, 
    thumbColumns, 
    thumb_IMAGE_ID + "=" + id, 
    null, 
    null);
        
        Cursor thumbCursor = thumbCursorLoader.loadInBackground();
        
        Bitmap thumbBitmap = null;
        if(thumbCursor.moveToFirst()){
   int thCulumnIndex = thumbCursor.getColumnIndex(thumb_DATA);
   
   String thumbPath = thumbCursor.getString(thCulumnIndex);
   
   Toast.makeText(getApplicationContext(), 
     thumbPath, 
     Toast.LENGTH_LONG).show();
   
   thumbBitmap = BitmapFactory.decodeFile(thumbPath);
   
   //Create a Dialog to display the thumbnail
   AlertDialog.Builder thumbDialog = new AlertDialog.Builder(MainActivity.this);
   ImageView thumbView = new ImageView(MainActivity.this);
   thumbView.setImageBitmap(thumbBitmap);
   LinearLayout layout = new LinearLayout(MainActivity.this);
         layout.setOrientation(LinearLayout.VERTICAL);
         layout.addView(thumbView);
         thumbDialog.setView(layout);
         thumbDialog.show();
   
  }else{
   Toast.makeText(getApplicationContext(), 
     "NO Thumbnail!", 
     Toast.LENGTH_LONG).show();
  }
        
        return thumbBitmap;
 }
}


download filesDownload the files.


Next:
- List Images with thumbnails, implementing custom SimpleCursorAdapter.

More:
Insert the bitmap to MediaStore with title and List images title in MediaStore

Friday, October 26, 2012

Get path of image in MediaStore.Images.Media from SimpleCursorAdapter

The post "List images in MediaStore.Images.Media" demonstrate how to list images in MediaStore.Images.Media with SimpleCursorAdapter. It's modified to retrieve the path of the clicked item using Cursor.

Get path of image in MediaStore.Images.Media from SimpleCursorAdapter


package com.example.androidlistimages;

import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;
import android.app.ListActivity;
import android.database.Cursor;

public class MainActivity extends ListActivity {
 
 //define source of MediaStore.Images.Media, internal or external storage
 Uri sourceUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
 //Uri sourceUri = MediaStore.Images.Media.INTERNAL_CONTENT_URI;

 SimpleCursorAdapter mySimpleCursorAdapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        
        String[] from = {MediaStore.MediaColumns.TITLE};
        int[] to = {android.R.id.text1};

        CursorLoader cursorLoader = new CursorLoader(
          this, 
          sourceUri, 
          null, 
          null, 
          null, 
          MediaStore.Audio.Media.TITLE);
        
        Cursor cursor = cursorLoader.loadInBackground();
        
        mySimpleCursorAdapter = new SimpleCursorAdapter(
          this, 
          android.R.layout.simple_list_item_1, 
          cursor, 
          from, 
          to, 
          CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        
        setListAdapter(mySimpleCursorAdapter);
        
        getListView().setOnItemClickListener(myOnItemClickListener);
    }
    
    OnItemClickListener myOnItemClickListener
    = new OnItemClickListener(){

  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position,
    long id) {
   Cursor cursor = mySimpleCursorAdapter.getCursor();
   cursor.moveToPosition(position);
   String _id = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID));
   Uri selUri = Uri.withAppendedPath(sourceUri, _id);
   
   Toast.makeText(getApplicationContext(), 
     selUri.getPath(), 
     Toast.LENGTH_LONG).show();
   
  }};

}


download filesDownload the files.

Next:
- Get the associated thumbnails


Thursday, October 25, 2012

email send images exercise, with spinner of pre-defined subjects.

Refer to the last exercise "Start activity to send email with multiple images attached, with build-in MediaStore.Images.Media selector", it always send email with images attached. So I want to have a spinner with pre-defined email subjects for user to easy choice.

email send images exercise, with spinner of pre-defined subjects.

Create /res/values/array.xml to provide the pre-defined email subjects.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="subject">
    <item>My Photos</item>
    <item>Share with you</item>
    <item>Please check</item>
    <item>Hello Friend</item>
</string-array>
</resources>


Modify layout to replace EditText of email subject with a <Spinner>.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enter email address:"/>
    <EditText 
        android:id="@+id/email_address"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="textEmailAddress"/>
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Choice Subject:"/>
    <Spinner
        android:id="@+id/spinner_subject"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enter Text:"/>
    <EditText 
        android:id="@+id/email_text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    
    <Button
        android:id="@+id/send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send"/>
    <ListView
        android:id="@+id/filelist"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>


Modify the code:
package com.example.androidselectmultifiles;

import java.util.ArrayList;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Spinner;

public class MainActivity extends Activity {
 
 EditText edittextEmailAddress;
 Spinner spinnerSubject;
    EditText edittextEmailText;
 Button btnSend;
 ListView listViewFiles;
 
 ArrayList<Uri> arrayUri = new ArrayList<Uri>();
 ArrayAdapter<Uri> myFileListAdapter;
 
    final int RQS_SENDEMAIL = 1;
    
    SimpleCursorAdapter listAdapter;
    
    final Uri sourceUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    ListAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        edittextEmailAddress = (EditText)findViewById(R.id.email_address);
        edittextEmailText = (EditText)findViewById(R.id.email_text);
        
        btnSend = (Button)findViewById(R.id.send);
        btnSend.setOnClickListener(btnSendOnClickListener);

        listViewFiles = (ListView)findViewById(R.id.filelist);
        String[] from = {MediaStore.MediaColumns.TITLE};
        int[] to = {android.R.id.text1};

        CursorLoader cursorLoader = new CursorLoader(
          this, 
          sourceUri, 
          null, 
          null, 
          null, 
          MediaStore.Audio.Media.TITLE);
        
        Cursor cursor = cursorLoader.loadInBackground();
        listAdapter = new SimpleCursorAdapter(
          this, 
          android.R.layout.simple_list_item_multiple_choice, 
          cursor, 
          from, 
          to, 
          CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        
        listViewFiles.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        
        listViewFiles.setAdapter(listAdapter);
        
        //Prepare Spinner for subject
        spinnerSubject = (Spinner)findViewById(R.id.spinner_subject);
        ArrayAdapter<CharSequence> adapterSpinnerSubject = ArrayAdapter.createFromResource(this, R.array.subject, android.R.layout.simple_spinner_item);
        adapterSpinnerSubject.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerSubject.setAdapter(adapterSpinnerSubject);
    }
    
    private ArrayList<Uri> getSelectedFiles(){
     ArrayList<Uri> arrayU = new ArrayList<Uri>();
     
     SparseBooleanArray checkedArray = listViewFiles.getCheckedItemPositions();
     
     for(int i=0; i<checkedArray.size(); i++)
        {
      int pos = checkedArray.keyAt(i);
      Cursor cursor = listAdapter.getCursor();
      cursor.moveToPosition(pos);
      String _id = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID));
      Uri selUri = Uri.withAppendedPath(sourceUri, _id);
      arrayU.add(selUri);
        }
     
     return arrayU;
    }
  
 OnClickListener btnSendOnClickListener
 = new OnClickListener(){

  @Override
  public void onClick(View v) {
   
   arrayUri = getSelectedFiles();

   String emailAddress = edittextEmailAddress.getText().toString();
   
   //retrieve spinnerSubject selection
   String emailSubject = spinnerSubject.getSelectedItem().toString();
   
   String emailText = edittextEmailText.getText().toString();
   String emailAddressList[] = {emailAddress};
   
   Intent intent = new Intent();
   intent.putExtra(Intent.EXTRA_EMAIL, emailAddressList);  
   intent.putExtra(Intent.EXTRA_SUBJECT, emailSubject); 
   intent.putExtra(Intent.EXTRA_TEXT, emailText);
   
   if(arrayUri.isEmpty()){
    //Send email without photo attached
    intent.setAction(Intent.ACTION_SEND);
    intent.setType("plain/text"); 
   }else if(arrayUri.size() == 1){
    //Send email with ONE photo attached
    intent.setAction(Intent.ACTION_SEND); 
    intent.putExtra(Intent.EXTRA_STREAM, arrayUri.get(0));
       intent.setType("image/*");
   }else{
    //Send email with MULTI photo attached
    intent.setAction(Intent.ACTION_SEND_MULTIPLE);
    intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, arrayUri);
       intent.setType("image/*");
   }
   
   startActivity(Intent.createChooser(intent, "Choice App to send email:"));
  }};

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  super.onActivityResult(requestCode, resultCode, data);
  
  if (resultCode == RESULT_OK){
   switch(requestCode){
   case RQS_SENDEMAIL:
    break; 
   }
  }
 }

}


download filesDownload the files.


Wednesday, October 24, 2012

Start activity to send email with multiple images attached, with build-in MediaStore.Images.Media selector.

The previous post demonstrate how to "Start activity to send email with multi images attached" using Android's Gallery App select images one-by-one. And the post "List images in MediaStore.Images.Media, with multiple selection" demonstrate how to implement our own image files selector. They are merged to have our own images selector to attach images in email.

Start activity to send email with multiple images attached, with build-in MediaStore.Images.Media selector.


package com.example.androidselectmultifiles;

import java.util.ArrayList;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {
 
 EditText edittextEmailAddress;
 EditText edittextEmailSubject;
    EditText edittextEmailText;
 Button btnSend;
 ListView listViewFiles;
 
 ArrayList<Uri> arrayUri = new ArrayList<Uri>();
 ArrayAdapter<Uri> myFileListAdapter;
 
    final int RQS_SENDEMAIL = 1;
    
    SimpleCursorAdapter listAdapter;
    
    final Uri sourceUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    ListAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        edittextEmailAddress = (EditText)findViewById(R.id.email_address);
        edittextEmailSubject = (EditText)findViewById(R.id.email_subject);
        edittextEmailText = (EditText)findViewById(R.id.email_text);
        
        btnSend = (Button)findViewById(R.id.send);
        btnSend.setOnClickListener(btnSendOnClickListener);

        listViewFiles = (ListView)findViewById(R.id.filelist);
        String[] from = {MediaStore.MediaColumns.TITLE};
        int[] to = {android.R.id.text1};

        CursorLoader cursorLoader = new CursorLoader(
          this, 
          sourceUri, 
          null, 
          null, 
          null, 
          MediaStore.Audio.Media.TITLE);
        
        Cursor cursor = cursorLoader.loadInBackground();
        listAdapter = new SimpleCursorAdapter(
          this, 
          android.R.layout.simple_list_item_multiple_choice, 
          cursor, 
          from, 
          to, 
          CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        
        listViewFiles.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        
        listViewFiles.setAdapter(listAdapter);
    }
    
    private ArrayList<Uri> getSelectedFiles(){
     ArrayList<Uri> arrayU = new ArrayList<Uri>();
     
     SparseBooleanArray checkedArray = listViewFiles.getCheckedItemPositions();
     
     for(int i=0; i<checkedArray.size(); i++)
        {
      int pos = checkedArray.keyAt(i);
      Cursor cursor = listAdapter.getCursor();
      cursor.moveToPosition(pos);
      String _id = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID));
      Uri selUri = Uri.withAppendedPath(sourceUri, _id);
      arrayU.add(selUri);
        }
     
     return arrayU;
    }
  
 OnClickListener btnSendOnClickListener
 = new OnClickListener(){

  @Override
  public void onClick(View v) {
   
   arrayUri = getSelectedFiles();

   String emailAddress = edittextEmailAddress.getText().toString();
   String emailSubject = edittextEmailSubject.getText().toString();
   String emailText = edittextEmailText.getText().toString();
   String emailAddressList[] = {emailAddress};
   
   Intent intent = new Intent();
   intent.putExtra(Intent.EXTRA_EMAIL, emailAddressList);  
   intent.putExtra(Intent.EXTRA_SUBJECT, emailSubject); 
   intent.putExtra(Intent.EXTRA_TEXT, emailText);
   
   if(arrayUri.isEmpty()){
    //Send email without photo attached
    intent.setAction(Intent.ACTION_SEND);
    intent.setType("plain/text"); 
   }else if(arrayUri.size() == 1){
    //Send email with ONE photo attached
    intent.setAction(Intent.ACTION_SEND); 
    intent.putExtra(Intent.EXTRA_STREAM, arrayUri.get(0));
       intent.setType("image/*");
   }else{
    //Send email with MULTI photo attached
    intent.setAction(Intent.ACTION_SEND_MULTIPLE);
    intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, arrayUri);
       intent.setType("image/*");
   }
   
   startActivity(Intent.createChooser(intent, "Choice App to send email:"));
  }};

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  super.onActivityResult(requestCode, resultCode, data);
  
  if (resultCode == RESULT_OK){
   switch(requestCode){
   case RQS_SENDEMAIL:
    break; 
   }
  }
 }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enter email address:"/>
    <EditText 
        android:id="@+id/email_address"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="textEmailAddress"/>
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enter email Subject:"/>
    <EditText 
        android:id="@+id/email_subject"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="textEmailSubject"/>
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enter Text:"/>
    <EditText 
        android:id="@+id/email_text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    
    <Button
        android:id="@+id/send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send"/>
    <ListView
        android:id="@+id/filelist"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>


download filesDownload the files.

Next:
- email send images exercise, with spinner of pre-defined subjects.


Tuesday, October 23, 2012

List images in MediaStore.Images.Media, with multiple selection.

Last exercise how to "List images in MediaStore.Images.Media". It's modified to have multiple selection on the ListView.

List images in MediaStore.Images.Media, with multiple selection.


package com.example.androidlistimages;

import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.app.ListActivity;
import android.database.Cursor;

public class MainActivity extends ListActivity {
 
 //define source of MediaStore.Images.Media, internal or external storage
 Uri sourceUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
 //Uri sourceUri = MediaStore.Images.Media.INTERNAL_CONTENT_URI;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        
        String[] from = {MediaStore.MediaColumns.TITLE};
        int[] to = {android.R.id.text1};

        CursorLoader cursorLoader = new CursorLoader(
          this, 
          sourceUri, 
          null, 
          null, 
          null, 
          MediaStore.Audio.Media.TITLE);
        
        Cursor cursor = cursorLoader.loadInBackground();
        
        ListAdapter adapter = new SimpleCursorAdapter(
          this, 
          android.R.layout.simple_list_item_multiple_choice, 
          cursor, 
          from, 
          to, 
          CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        
        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        
        setListAdapter(adapter);
    }

}


download filesDownload the files.

Read the post "Start activity to send email with multiple images attached, with build-in MediaStore.Images.Media selector" to know how to retrieve the selected images.

List images in MediaStore.Images.Media

This exercise demonstrate how to list images in MediaStore.Images.Media.

List images in MediaStore.Images.Media


Modify MainActivity.java extends ListActivity.
package com.example.androidlistimages;

import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.widget.ListAdapter;
import android.app.ListActivity;
import android.database.Cursor;

public class MainActivity extends ListActivity {
 
 //define source of MediaStore.Images.Media, internal or external storage
 Uri sourceUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
 //Uri sourceUri = MediaStore.Images.Media.INTERNAL_CONTENT_URI;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        
        String[] from = {MediaStore.MediaColumns.TITLE};
        int[] to = {android.R.id.text1};

        CursorLoader cursorLoader = new CursorLoader(
          this, 
          sourceUri, 
          null, 
          null, 
          null, 
          MediaStore.Audio.Media.TITLE);
        
        Cursor cursor = cursorLoader.loadInBackground();
        
        ListAdapter adapter = new SimpleCursorAdapter(
          this, 
          android.R.layout.simple_list_item_1, 
          cursor, 
          from, 
          to, 
          CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        setListAdapter(adapter);
    }


}


download filesDownload the files.

Remark:
Compare with my old exercise, "List audio media in MediaStore.Audio.Media" and "Start activity to play MediaStore.Video.Media by intent with action of Intent.ACTION_VIEW", both managedQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) and SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) are deprecated. See how we use CursorLoader here.

Next:
- Get path of image in MediaStore.Images.Media from SimpleCursorAdapter
- List images in MediaStore.Images.Media, with multiple selection.

Compare with:
- Query Contacts database, display in ListView.

More:
Insert the bitmap to MediaStore with title and List images title in MediaStore

Start activity to send email with multi images attached, with action of ACTION_SEND_MULTIPLE.

The post "Send email with Image by starting activity using Intent of ACTION_SEND" demonstrate how to send SINGLE image. It's modified to send multi images with action of Intent.ACTION_SEND_MULTIPLE. The Uris of the attached images are stored in a ArrayList, and pass to intent via putParcelableArrayListExtra() method.

Start activity to send multi images attached


package com.example.androidselectmultifiles;

import java.util.ArrayList;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class MainActivity extends Activity {
 
 EditText edittextEmailAddress;
 EditText edittextEmailSubject;
    EditText edittextEmailText;
 Button btnAddFile, btnSend;
 ListView listViewFiles;
 
 ArrayList<Uri> arrayUri = new ArrayList<Uri>();
 ArrayAdapter<Uri> myFileListAdapter;
 
 final int RQS_LOADIMAGE = 0;
    final int RQS_SENDEMAIL = 1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        edittextEmailAddress = (EditText)findViewById(R.id.email_address);
        edittextEmailSubject = (EditText)findViewById(R.id.email_subject);
        edittextEmailText = (EditText)findViewById(R.id.email_text);
        
        btnAddFile = (Button)findViewById(R.id.addphoto);
        btnSend = (Button)findViewById(R.id.send);
        btnAddFile.setOnClickListener(btnAddFileOnClickListener);
        btnSend.setOnClickListener(btnSendOnClickListener);
        
        myFileListAdapter = new ArrayAdapter<Uri>(
          MainActivity.this,
          android.R.layout.simple_list_item_1,
          arrayUri);
        listViewFiles = (ListView)findViewById(R.id.filelist);
        listViewFiles.setAdapter(myFileListAdapter);
    }
    
    OnClickListener btnAddFileOnClickListener
    = new OnClickListener(){

  @Override
  public void onClick(View v) {
   Intent intent = new Intent(Intent.ACTION_PICK, 
     android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
   startActivityForResult(intent, RQS_LOADIMAGE);
   
  }};
  
 OnClickListener btnSendOnClickListener
 = new OnClickListener(){

  @Override
  public void onClick(View v) {
   String emailAddress = edittextEmailAddress.getText().toString();
   String emailSubject = edittextEmailSubject.getText().toString();
   String emailText = edittextEmailText.getText().toString();
   String emailAddressList[] = {emailAddress};
   
   Intent intent = new Intent();
   intent.putExtra(Intent.EXTRA_EMAIL, emailAddressList);  
   intent.putExtra(Intent.EXTRA_SUBJECT, emailSubject); 
   intent.putExtra(Intent.EXTRA_TEXT, emailText);
   
   if(arrayUri.isEmpty()){
    //Send email without photo attached
    intent.setAction(Intent.ACTION_SEND);
    intent.setType("plain/text"); 
   }else if(arrayUri.size() == 1){
    //Send email with ONE photo attached
    intent.setAction(Intent.ACTION_SEND); 
    intent.putExtra(Intent.EXTRA_STREAM, arrayUri.get(0));
       intent.setType("image/*");
   }else{
    //Send email with MULTI photo attached
    intent.setAction(Intent.ACTION_SEND_MULTIPLE);
    intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, arrayUri);
       intent.setType("image/*");
   }
   
   startActivity(Intent.createChooser(intent, "Choice App to send email:"));
   
  }};

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  // TODO Auto-generated method stub
  super.onActivityResult(requestCode, resultCode, data);
  
  if (resultCode == RESULT_OK){
   switch(requestCode){
   case RQS_LOADIMAGE:
    Uri imageUri = data.getData();
    arrayUri.add(imageUri);
    myFileListAdapter.notifyDataSetChanged();
    break; 
   case RQS_SENDEMAIL:
    break; 
   }
  }
 }


}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enter email address:"/>
    <EditText 
        android:id="@+id/email_address"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="textEmailAddress"/>
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enter email Subject:"/>
    <EditText 
        android:id="@+id/email_subject"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="textEmailSubject"/>
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enter Text:"/>
    <EditText 
        android:id="@+id/email_text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    
    <Button
        android:id="@+id/addphoto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add photo"/>
    <Button
        android:id="@+id/send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send"/>
    <ListView
        android:id="@+id/filelist"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>


download filesDownload the files.

Next:
- Start activity to send email with multiple images attached, with build-in MediaStore.Images.Media selector.

Monday, October 22, 2012

Search WOEID and query Yahoo Weather

In my old posts, demonstrate how to "Search WOEID from http://query.yahooapis.com/" and "Get weather info from Yahoo! Weather RSS Feed". This exercise merge both together.

Search WOEID and query Yahoo Weather

User enter location to be searched for WOEID, then clicked the WOEID to start another activity querying Yahoo for the weather.

And also, the code to read from internet have been moved to AsyncTask to prevent from NetworkOnMainThreadException.

Main activity, MainActivity.java.
package com.example.androidwoeidweather;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import android.app.Activity;
import android.content.Intent;

public class MainActivity extends Activity {
 
 //Example for "New York"
 //http://query.yahooapis.com/v1/public/yql?q=select*from geo.places where text="New York"&format=xml
 final String yahooPlaceApisBase = "http://query.yahooapis.com/v1/public/yql?q=select*from%20geo.places%20where%20text=";
 final String yahooapisFormat = "&format=xml";
 String yahooPlaceAPIsQuery;

 EditText place;
 Button search;
 ListView listviewWOEID;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        place = (EditText)findViewById(R.id.place);
        search = (Button)findViewById(R.id.search);
        listviewWOEID = (ListView)findViewById(R.id.woeidlist);

        search.setOnClickListener(searchOnClickListener);
    }
    
    Button.OnClickListener searchOnClickListener
    = new Button.OnClickListener(){

  @Override
  public void onClick(View arg0) {
   if(place.getText().toString().equals("")){
    Toast.makeText(getBaseContext(),
      "Enter place!",
      Toast.LENGTH_LONG).show();
   }else{
    new MyQueryYahooPlaceTask().execute();
   }
  }
    };
    
    private class MyQueryYahooPlaceTask extends AsyncTask<Void, Void, Void>{

     ArrayList<String> l;
     
  @Override
  protected Void doInBackground(Void... arg0) {
   l = QueryYahooPlaceAPIs();
   return null;
  }

  @Override
  protected void onPostExecute(Void result) {
   ArrayAdapter<String> aa = new ArrayAdapter<String>(
     getBaseContext(), android.R.layout.simple_list_item_1, l);
   listviewWOEID.setAdapter(aa);
   
   listviewWOEID.setOnItemClickListener(new OnItemClickListener(){

    @Override
    public void onItemClick(AdapterView<?> parent, View view,
      int position, long id) {
     
     String selWoeid = parent.getItemAtPosition(position).toString();
     
     /*
     Toast.makeText(getApplicationContext(), 
       selWoeid, 
       Toast.LENGTH_LONG).show();
     */
     
     Intent intent = new Intent();
              intent.setClass(MainActivity.this, GetWeather.class);
              Bundle bundle = new Bundle();
              bundle.putCharSequence("SEL_WOEID", selWoeid);
              intent.putExtras(bundle);
              startActivity(intent);
    }});
   
   super.onPostExecute(result);
  }
     
    }
    
    private ArrayList<String> QueryYahooPlaceAPIs(){
     String uriPlace = Uri.encode(place.getText().toString());
     
     yahooPlaceAPIsQuery = yahooPlaceApisBase
       + "%22" + uriPlace + "%22"
       + yahooapisFormat;
     
     String woeidString = QueryYahooWeather(yahooPlaceAPIsQuery);
     Document woeidDoc = convertStringToDocument(woeidString);
     return  parseWOEID(woeidDoc);
    }
    
    private ArrayList<String> parseWOEID(Document srcDoc){
     ArrayList<String> listWOEID = new ArrayList<String>();
     
     NodeList nodeListDescription = srcDoc.getElementsByTagName("woeid");
     if(nodeListDescription.getLength()>=0){
      for(int i=0; i<nodeListDescription.getLength(); i++){
       listWOEID.add(nodeListDescription.item(i).getTextContent()); 
      } 
     }else{
      listWOEID.clear(); 
     }
     
     return listWOEID;
    }
    
    private Document convertStringToDocument(String src){
     Document dest = null;
     
     DocumentBuilderFactory dbFactory =
       DocumentBuilderFactory.newInstance();
     DocumentBuilder parser;
     
     try {
      parser = dbFactory.newDocumentBuilder();
      dest = parser.parse(new ByteArrayInputStream(src.getBytes())); 
     } catch (ParserConfigurationException e1) {
      e1.printStackTrace(); 
     } catch (SAXException e) {
      e.printStackTrace(); 
     } catch (IOException e) {
      e.printStackTrace(); 
     }
     
     return dest; 
    }
    
    private String QueryYahooWeather(String queryString){
     String qResult = "";
     
     HttpClient httpClient = new DefaultHttpClient();
     HttpGet httpGet = new HttpGet(queryString);
     
     try {
      HttpEntity httpEntity = httpClient.execute(httpGet).getEntity();
      
      if (httpEntity != null){
       InputStream inputStream = httpEntity.getContent();
       Reader in = new InputStreamReader(inputStream);
       BufferedReader bufferedreader = new BufferedReader(in);
       StringBuilder stringBuilder = new StringBuilder();
       
       String stringReadLine = null;
       
       while ((stringReadLine = bufferedreader.readLine()) != null) {
        stringBuilder.append(stringReadLine + "\n"); 
       }
       
       qResult = stringBuilder.toString(); 
      } 
     } catch (ClientProtocolException e) {
      e.printStackTrace();; 
     } catch (IOException e) {
      e.printStackTrace(); 
     }
     
     return qResult; 
    }

}


Layout of the main activity, activity_main.xml.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <EditText
        android:id="@+id/place"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/search"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Search WOEID by place" />
    <ListView
        android:id="@+id/woeidlist"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>


The activity to query weather from Yahoo, GetWeather.java.
package com.example.androidwoeidweather;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class GetWeather extends Activity {
 
 TextView weather;
 
 class MyWeather{
  
  String description;
  String city;
  String region;
  String country;

  String windChill;
  String windDirection;
  String windSpeed;

  String sunrise;
  String sunset;

  String conditiontext;
  String conditiondate;
  
  public String toString(){
   
   String s;
   
   s = description + " -\n\n" + "city: " + city + "\n"
     + "region: " + region + "\n"
     + "country: " + country + "\n\n"
     + "Wind\n"
     + "chill: " + windChill + "\n"
     + "direction: " + windDirection + "\n"
     + "speed: " + windSpeed + "\n\n"
     + "Sunrise: " + sunrise + "\n"
     + "Sunset: " + sunset + "\n\n"
     + "Condition: " + conditiontext + "\n"
     + conditiondate +"\n";
   
   return s;
  }
 }

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
  setContentView(R.layout.layout_weather);
  weather = (TextView)findViewById(R.id.weather);
  
  Bundle bundle = this.getIntent().getExtras();
        String sel_woeid = (String)bundle.getCharSequence("SEL_WOEID");
        
        new MyQueryYahooWeatherTask(sel_woeid).execute();
        
        Toast.makeText(getApplicationContext(), 
          sel_woeid, 
    Toast.LENGTH_LONG).show();
 }
 
 private class MyQueryYahooWeatherTask extends AsyncTask<Void, Void, Void>{

  String woeid;
  String weatherResult;
  String weatherString;
  
  MyQueryYahooWeatherTask(String w){
   woeid = w;
  }
  
  @Override
  protected Void doInBackground(Void... arg0) {
   weatherString = QueryYahooWeather();
   Document weatherDoc = convertStringToDocument(weatherString);
   
   if(weatherDoc != null){
    weatherResult = parseWeather(weatherDoc).toString();
   }else{
    weatherResult = "Cannot convertStringToDocument!";
   }
   
   return null;
  }

  @Override
  protected void onPostExecute(Void result) {
   weather.setText(weatherResult);
   super.onPostExecute(result);
  }
  
  private String QueryYahooWeather(){
   String qResult = "";
     String queryString = "http://weather.yahooapis.com/forecastrss?w=" + woeid;
     
     HttpClient httpClient = new DefaultHttpClient();
     HttpGet httpGet = new HttpGet(queryString);
     
     try {
      HttpEntity httpEntity = httpClient.execute(httpGet).getEntity();
      
      if (httpEntity != null){
       InputStream inputStream = httpEntity.getContent();
       Reader in = new InputStreamReader(inputStream);
       BufferedReader bufferedreader = new BufferedReader(in);
       StringBuilder stringBuilder = new StringBuilder();
       
       String stringReadLine = null;
       
       while ((stringReadLine = bufferedreader.readLine()) != null) {
        stringBuilder.append(stringReadLine + "\n");  
       }
       
       qResult = stringBuilder.toString();  
      }  
     } catch (ClientProtocolException e) {
      e.printStackTrace(); 
     } catch (IOException e) {
      e.printStackTrace(); 
     }
     return qResult;   
  }
  
  private Document convertStringToDocument(String src){
   Document dest = null;
   
   DocumentBuilderFactory dbFactory =
     DocumentBuilderFactory.newInstance();
   DocumentBuilder parser;

   try {
    parser = dbFactory.newDocumentBuilder();
    dest = parser.parse(new ByteArrayInputStream(src.getBytes())); 
   } catch (ParserConfigurationException e1) {
    e1.printStackTrace(); 
   } catch (SAXException e) {
    e.printStackTrace(); 
   } catch (IOException e) {
    e.printStackTrace(); 
   }
   
   return dest; 
  }
  
  private MyWeather parseWeather(Document srcDoc){
   
   MyWeather myWeather = new MyWeather();
   
   //<description>Yahoo! Weather for New York, NY</description>
   NodeList descNodelist = srcDoc.getElementsByTagName("description");
   if(descNodelist != null && descNodelist.getLength() > 0){
    myWeather.description = descNodelist.item(0).getTextContent();
   }else{
    myWeather.description = "EMPTY";
   }

   //<yweather:location city="New York" region="NY" country="United States"/>
   NodeList locationNodeList = srcDoc.getElementsByTagName("yweather:location");
   if(locationNodeList != null && locationNodeList.getLength() > 0){
    Node locationNode = locationNodeList.item(0);
    NamedNodeMap locNamedNodeMap = locationNode.getAttributes();
    
    myWeather.city = locNamedNodeMap.getNamedItem("city").getNodeValue().toString();
    myWeather.region = locNamedNodeMap.getNamedItem("region").getNodeValue().toString();
    myWeather.country = locNamedNodeMap.getNamedItem("country").getNodeValue().toString();
   }else{
    myWeather.city = "EMPTY";
    myWeather.region = "EMPTY";
    myWeather.country = "EMPTY";
   }
   
   //<yweather:wind chill="60" direction="0" speed="0"/>
   NodeList windNodeList = srcDoc.getElementsByTagName("yweather:wind");
   if(windNodeList != null && windNodeList.getLength() > 0){
    Node windNode = windNodeList.item(0);
    NamedNodeMap windNamedNodeMap = windNode.getAttributes();
    
    myWeather.windChill = windNamedNodeMap.getNamedItem("chill").getNodeValue().toString();
    myWeather.windDirection = windNamedNodeMap.getNamedItem("direction").getNodeValue().toString();
    myWeather.windSpeed = windNamedNodeMap.getNamedItem("speed").getNodeValue().toString();
   }else{
    myWeather.windChill = "EMPTY";
    myWeather.windDirection = "EMPTY";
    myWeather.windSpeed = "EMPTY";
   }
   
   //<yweather:astronomy sunrise="6:52 am" sunset="7:10 pm"/>
   NodeList astNodeList = srcDoc.getElementsByTagName("yweather:astronomy");
   if(astNodeList != null && astNodeList.getLength() > 0){
    Node astNode = astNodeList.item(0);
    NamedNodeMap astNamedNodeMap = astNode.getAttributes();
    
    myWeather.sunrise = astNamedNodeMap.getNamedItem("sunrise").getNodeValue().toString();
    myWeather.sunset = astNamedNodeMap.getNamedItem("sunset").getNodeValue().toString();
   }else{
    myWeather.sunrise = "EMPTY";
    myWeather.sunset = "EMPTY";
   }
   
   //<yweather:condition text="Fair" code="33" temp="60" date="Fri, 23 Mar 2012 8:49 pm EDT"/>
   NodeList conditionNodeList = srcDoc.getElementsByTagName("yweather:condition");
   if(conditionNodeList != null && conditionNodeList.getLength() > 0){
    Node conditionNode = conditionNodeList.item(0);
    NamedNodeMap conditionNamedNodeMap = conditionNode.getAttributes();
    
    myWeather.conditiontext = conditionNamedNodeMap.getNamedItem("text").getNodeValue().toString();
    myWeather.conditiondate = conditionNamedNodeMap.getNamedItem("date").getNodeValue().toString();
   }else{
    myWeather.conditiontext = "EMPTY";
    myWeather.conditiondate = "EMPTY";
   }
   
   return myWeather; 
  }
  
 }

}


Layout of GetWeather, layout_weather.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    
    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TextView
            android:id="@+id/weather"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </ScrollView>

</LinearLayout>


Modify AndroidManifest.xml to add activity ".GetWeather" and permission of "android.permission.INTERNET".
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidwoeidweather"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".GetWeather">
        </activity>
    </application>

</manifest>


download filesDownload the files.

Friday, October 19, 2012

AutoCompleteTextView with dynamic suggested words

The post "Example of AutoCompleteTextView" demonstrate AutoCompleteTextView with pre-defined suggested words. It's modified to have dynamic suggested words in this exercise.

AutoCompleteTextView with dynamic suggested words

myAutoCompleteAdapter employ a List<string> instead of String[]. Such that we can modify the contain dynamically. When user finish enter by clicking on OK button, it will check if the words is contained in the List<string>. If not, it will be added, and the adapter will be updated.

package com.example.androidautocompletetextview;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements TextWatcher{

 AutoCompleteTextView myAutoComplete;
 String item[]={
   "January", "February", "March", "April",
   "May", "June", "July", "August",
   "September", "October", "November", "December"
 };
 
 List<String> myList;
 ArrayAdapter<String> myAutoCompleteAdapter;
 
 Button buttonOK;
 TextView autoList;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        myAutoComplete = (AutoCompleteTextView)findViewById(R.id.myautocomplete);
        
        prepareMyList();
        myAutoComplete.addTextChangedListener(this);
        
        myAutoCompleteAdapter = new ArrayAdapter<String>(
          MainActivity.this, 
          android.R.layout.simple_dropdown_item_1line, 
          myList);
        
        myAutoComplete.setAdapter(myAutoCompleteAdapter);
        
        buttonOK = (Button)findViewById(R.id.ok);
        buttonOK.setOnClickListener(OkOnClickListener);
        
        autoList = (TextView)findViewById(R.id.autolist);
    }
    
    private void prepareMyList(){
     //prepare your list of words for AutoComplete
     myList = new ArrayList<String>();
     for(int i = 0; i < item.length; i++){
      myList.add(item[i]);
     }
    }
    
    OnClickListener OkOnClickListener
    = new OnClickListener(){

  @Override
  public void onClick(View arg0) {
   // TODO Auto-generated method stub
   
   String newAdd = myAutoComplete.getText().toString();
   
   if(!myList.contains(newAdd)){
    myList.add(newAdd);
    
    // I don't know why simple notifyDataSetChanged() 
    // cannot update the autocomplete words
    //myAutoCompleteAdapter.notifyDataSetChanged();
    
    //update the autocomplete words
    myAutoCompleteAdapter = new ArrayAdapter<String>(
      MainActivity.this, 
            android.R.layout.simple_dropdown_item_1line, 
            myList);
          
          myAutoComplete.setAdapter(myAutoCompleteAdapter);
   }
   
   //display the words in myList for your reference
   String s = "";
   for(int i = 0; i < myList.size(); i++){
    s += myList.get(i) + "\n";
   }
   autoList.setText(s);
  }};

 @Override
 public void afterTextChanged(Editable arg0) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public void beforeTextChanged(CharSequence s, int start, int count,
   int after) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public void onTextChanged(CharSequence s, int start, int before, int count) {
  // TODO Auto-generated method stub
  
 }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <AutoCompleteTextView 
        android:id="@+id/myautocomplete"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:completionThreshold="1"/>
    <Button 
        android:id="@+id/ok"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="OK"/>
    <TextView
        android:id="@+id/autolist"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    
</LinearLayout>


download filesDownload the files.

MOTODEV ends



Motorola launched the MOTODEV Android Portal in 2009 to provide developers with the technical support and resources needed to create quality apps for Motorola devices.

On November 1, the MOTODEV portal, tech library, support forums and social media sites will transition and we’ll begin redirecting users to a new Developer Resources page on Motorola.com for downloads and links to the rich set of tools, support forums and technical documentation now available in the broader Android community such as: Google Android Developers and Stack Overflow.

~ Full announcement from MOTODEV.

Create Animation using Matrix

The former exercise demonstrate how to "Using Matrix create scaled bitmap". In this exercise, we will create animation using matrix.

Create Animation using Matrix


package com.example.androidmatrixanimation;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Matrix;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.OvershootInterpolator;
import android.view.animation.Transformation;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

 Button myButton;
 ImageView myImage1, myImage2;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        myButton = (Button)findViewById(R.id.mybutton);
        myImage1 = (ImageView)findViewById(R.id.myimage1);
        myImage2 = (ImageView)findViewById(R.id.myimage2);
        
        myButton.setOnClickListener(myOnClickListener);
        myImage1.setOnClickListener(myOnClickListener);
        myImage2.setOnClickListener(myOnClickListener);

    }
    
    OnClickListener myOnClickListener
    = new OnClickListener(){

  @Override
  public void onClick(View v) {
   applyAnimation(v);
   
  } 
    };
    
    private void applyAnimation(View v){
     MyAnimation myAnimation = new MyAnimation();
  myAnimation.setDuration(5000);
  myAnimation.setFillAfter(true);
  myAnimation.setInterpolator(new OvershootInterpolator());
  
  v.startAnimation(myAnimation);
    }

    public class MyAnimation extends Animation{

  @Override
  protected void applyTransformation(float interpolatedTime,
    Transformation t) {
   super.applyTransformation(interpolatedTime, t);
   
   final Matrix matrix = t.getMatrix();
   matrix.setScale(interpolatedTime, interpolatedTime);
  }
    }
    
}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    <Button
        android:id="@+id/mybutton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />
    <ImageView
        android:id="@+id/myimage1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="center"
        android:src="@drawable/ic_launcher" />
    <ImageView
        android:id="@+id/myimage2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="center"
        android:src="@drawable/ic_launcher" />

</LinearLayout>




download filesDownload the files.

Download the APK.

Thursday, October 18, 2012

AndroidKickstartR, Start your next Android app in 10 seconds.



AndroidKickstartR helps you to quickly create a well configured Android application using the most popular libraries. It creates and configures your project for you. Just focus on code!

Visit: http://androidkickstartr.com/

Selling Android Apps in Multiple Currencies

Google introducing Buyer’s Currencies in two new countries, India and Russia. All prices for these locales will be in the Indian Rupee (INR) and Russian Ruble (RUB) currencies, respectively. Visit the Google Play Developer Console to set prices for this new country by October 25, 2012. On October 25, 2012, Google Play will automatically assign Buyer’s Currency prices for your products for the new countries if you have not manually set them in the Developer Console.

Learn more.

Tuesday, October 9, 2012

Google launched Tablet App Quality Checklist

Google launched Tablet App Quality Checklist to make it easier for you to ensure your app meets the expectations of tablet users.

The checklist includes a number of key focus areas for building apps that are a great experience on tablets, including:
  • Optimizing your layouts for larger screens
  • Taking advantage of extra screen area available on tablets
  • Using Icons and other assets that are designed for tablet screens

Source: http://android-developers.blogspot.com/2012/10/building-quality-tablet-apps.html

Get touched pixel color of scaled ImageView

To get touched pixel color of a ImageView, you can implement OnTouchListener of the ImageView, get touched position by calling event.getX() and event.getY(), and get the pixel color by calling bitmap.getPixel(x, y)...IF THE BITMAP IN YOUR ImageView IS DISPLAY AT 1:1, layout_width and layout_height ="wrap_content".

If your bitmap is scaled, such as layout_width and layout_height ="match_parent". It will not work! It's a example demonstrate how to invert the touched position to get pixel from scaled ImageView.

Get touched pixel color of scaled ImageView


package com.example.androidtouchedpixel;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 TextView touchedXY, invertedXY, imgSize, colorRGB;
 ImageView imgSource1, imgSource2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        touchedXY = (TextView)findViewById(R.id.xy);
        invertedXY = (TextView)findViewById(R.id.invertedxy);
        imgSize = (TextView)findViewById(R.id.size);
        colorRGB = (TextView)findViewById(R.id.colorrgb);
     imgSource1 = (ImageView)findViewById(R.id.source1);
     imgSource2 = (ImageView)findViewById(R.id.source2);
     
     imgSource1.setOnTouchListener(imgSourceOnTouchListener);
     imgSource2.setOnTouchListener(imgSourceOnTouchListener);
     
    }
    
    OnTouchListener imgSourceOnTouchListener
    = new OnTouchListener(){

  @Override
  public boolean onTouch(View view, MotionEvent event) {
   
   float eventX = event.getX();
   float eventY = event.getY();
   float[] eventXY = new float[] {eventX, eventY};
   
   Matrix invertMatrix = new Matrix();
   ((ImageView)view).getImageMatrix().invert(invertMatrix);
   
   invertMatrix.mapPoints(eventXY);
   int x = Integer.valueOf((int)eventXY[0]);
   int y = Integer.valueOf((int)eventXY[1]);
   
   touchedXY.setText(
     "touched position: "
     + String.valueOf(eventX) + " / " 
     + String.valueOf(eventY));
   invertedXY.setText(
     "touched position: "
     + String.valueOf(x) + " / " 
     + String.valueOf(y));

   Drawable imgDrawable = ((ImageView)view).getDrawable();
   Bitmap bitmap = ((BitmapDrawable)imgDrawable).getBitmap();
   
   imgSize.setText(
     "drawable size: "
     + String.valueOf(bitmap.getWidth()) + " / " 
     + String.valueOf(bitmap.getHeight()));
   
   //Limit x, y range within bitmap
   if(x < 0){
    x = 0;
   }else if(x > bitmap.getWidth()-1){
    x = bitmap.getWidth()-1;
   }
   
   if(y < 0){
    y = 0;
   }else if(y > bitmap.getHeight()-1){
    y = bitmap.getHeight()-1;
   }

   int touchedRGB = bitmap.getPixel(x, y);
   
   colorRGB.setText("touched color: " + "#" + Integer.toHexString(touchedRGB));
   colorRGB.setTextColor(touchedRGB);
   
   return true;
  }};

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <TextView 
        android:id="@+id/xy"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="touched position: "/>
    <TextView 
        android:id="@+id/invertedxy"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="inverted touched position: "/>
    <TextView 
        android:id="@+id/size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="drawable size: "/>
    <TextView 
        android:id="@+id/colorrgb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="touched color: "/>
    <ImageView
        android:id="@+id/source1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher"/>
    <ImageView
        android:id="@+id/source2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/ic_launcher"/>

</LinearLayout>


download filesDownload the files.


Sunday, October 7, 2012

Create skewed bitmap using Matrix

Example to create skewed bitmap using Matrix:

Create skewed bitmap using Matrix


package com.example.androidmatrix;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class MainActivity extends Activity {
 
 ImageView imageSource, imageTarget;
 Bitmap bitmapSource;
 
 SeekBar xBar, yBar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        imageSource = (ImageView)findViewById(R.id.source);
        imageTarget = (ImageView)findViewById(R.id.target);
        xBar = (SeekBar)findViewById(R.id.xbar);
        yBar = (SeekBar)findViewById(R.id.ybar);
        
        bitmapSource = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        imageSource.setImageBitmap(bitmapSource);
        
        xBar.setOnSeekBarChangeListener(xyBarChangeListener);
        yBar.setOnSeekBarChangeListener(xyBarChangeListener);
        
        Bitmap nBM = skewBitmap(bitmapSource, 0.0f, 0.0f);
        imageTarget.setImageBitmap(nBM);
    }
    
    OnSeekBarChangeListener xyBarChangeListener
    = new OnSeekBarChangeListener(){

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   float xskew = (float)(xBar.getProgress() - 100)/100.0f;
   float yskew = (float)(yBar.getProgress() - 100)/100.0f;
         imageTarget.setImageBitmap(skewBitmap(bitmapSource, xskew, yskew));
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }};

 private Bitmap skewBitmap(Bitmap src, float xSkew, float ySkew){
  Matrix matrix = new Matrix();
  matrix.postSkew(xSkew, ySkew);
     Bitmap skewedBitmap = Bitmap.createBitmap(
       bitmapSource, 
       0, 
       0, 
       src.getWidth(), 
       src.getHeight(), 
       matrix, 
       true);
     
     return skewedBitmap;
 }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <ImageView
        android:id="@+id/source"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView
        android:id="@+id/target"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <SeekBar
        android:id="@+id/xbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="200"
        android:progress="100"/>
    <SeekBar
        android:id="@+id/ybar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="200"
        android:progress="100"/>

</LinearLayout>


download filesDownload the files.

Saturday, October 6, 2012

Create scaled bitmap using Matrix

Example to create scaled bitmap using Matrix.postScale() method. Refer to scaleBitmap() method in the code.

Create scaled bitmap using Matrix

package com.example.androidmatrix;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class MainActivity extends Activity {
 
 ImageView imageSource, imageTarget;
 Bitmap bitmapSource;
 
 SeekBar xBar, yBar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        imageSource = (ImageView)findViewById(R.id.source);
        imageTarget = (ImageView)findViewById(R.id.target);
        xBar = (SeekBar)findViewById(R.id.xbar);
        yBar = (SeekBar)findViewById(R.id.ybar);
        
        bitmapSource = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        imageSource.setImageBitmap(bitmapSource);
        
        xBar.setOnSeekBarChangeListener(xyBarChangeListener);
        yBar.setOnSeekBarChangeListener(xyBarChangeListener);
        
        Bitmap nBM = scaleBitmap(bitmapSource, 1.0f, 1.0f);
        imageTarget.setImageBitmap(nBM);
    }
    
    OnSeekBarChangeListener xyBarChangeListener
    = new OnSeekBarChangeListener(){

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   float xscale = (float)(xBar.getProgress())/200;
   float yscale = (float)(yBar.getProgress())/200;
         imageTarget.setImageBitmap(scaleBitmap(bitmapSource, xscale, yscale));
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }};

 private Bitmap scaleBitmap(Bitmap src, float xScale, float yScale){
  Matrix matrix = new Matrix();
  matrix.postScale(xScale, yScale);
     Bitmap scaledBitmap = Bitmap.createBitmap(
       bitmapSource, 
       0, 
       0, 
       src.getWidth(), 
       src.getHeight(), 
       matrix, 
       true);
     
     return scaledBitmap;
 }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <ImageView
        android:id="@+id/source"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView
        android:id="@+id/target"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <SeekBar
        android:id="@+id/xbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="400"
        android:progress="100"/>
    <SeekBar
        android:id="@+id/ybar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="400"
        android:progress="100"/>

</LinearLayout>


download filesDownload the files.

Friday, October 5, 2012

Create rotated bitmap using Matrix

This exercise demonstrate how to create a rotated bitmap using Matrix, with postRotate() method called. Refer to rotateBitmap(Bitmap src, float degrees) method in the code.

Create rotated bitmap using Matrix

package com.example.androidmatrix;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class MainActivity extends Activity {
 
 ImageView imageSource, imageTarget;
 Bitmap bitmapSource;
 
 SeekBar rotateBar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        imageSource = (ImageView)findViewById(R.id.source);
        imageTarget = (ImageView)findViewById(R.id.target);
        rotateBar = (SeekBar)findViewById(R.id.rotatebar);
        
        bitmapSource = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        imageSource.setImageBitmap(bitmapSource);
        
        rotateBar.setOnSeekBarChangeListener(rotateBarChangeListener);
        
        Bitmap nBM = rotateBitmap(bitmapSource, 0.0f);
        imageTarget.setImageBitmap(nBM);
    }
    
    OnSeekBarChangeListener rotateBarChangeListener
    = new OnSeekBarChangeListener(){

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   float rotateDegrees = (float)(rotateBar.getProgress());
         imageTarget.setImageBitmap(rotateBitmap(bitmapSource, rotateDegrees));
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }};

 private Bitmap rotateBitmap(Bitmap src, float degrees){
  Matrix matrix = new Matrix();
     matrix.postRotate(degrees, src.getWidth()/2, src.getHeight()/2);
     Bitmap rotatedBitmap = Bitmap.createBitmap(
       bitmapSource, 
       0, 
       0, 
       src.getWidth(), 
       src.getHeight(), 
       matrix, 
       true);
     
     return rotatedBitmap;
 }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <ImageView
        android:id="@+id/source"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView
        android:id="@+id/target"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <SeekBar
        android:id="@+id/rotatebar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="360"
        android:progress="0"/>

</LinearLayout>


download filesDownload the files.