Thursday, 13 November 2014

Expandable Listview

ExpandableListviewActivity
-----------------------------------

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

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.Toast;

public class ExpandableListviewActivity extends ActionBarActivity implements
OnChildClickListener {

private ExpandableListView expandablelistview;
private ExpandableListAdapter adapter;

List<String> listDataHeader;
HashMap<String, List<String>> listDataChild;

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

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

expandablelistview = (ExpandableListView) findViewById(R.id.expandablelistview);

prepareListData();
adapter = new ExpandableListAdapter(ExpandableListviewActivity.this,
listDataHeader, listDataChild);

expandablelistview.setAdapter(adapter);
expandablelistview
.setOnGroupExpandListener(new OnGroupExpandListener() {

@Override
public void onGroupExpand(int groupPosition) {



int len = listDataHeader.size();

for (int i = 0; i < len; i++) {
if (i != groupPosition) {
expandablelistview.collapseGroup(i);
}
}
}
});

expandablelistview
.setOnGroupCollapseListener(new OnGroupCollapseListener() {

@Override
public void onGroupCollapse(int groupPosition) {


}
});
expandablelistview.setOnChildClickListener(this);

}



@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.expandable_listview, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

private void prepareListData() {
listDataHeader = new ArrayList<String>();
listDataChild = new HashMap<String, List<String>>();

// Adding child data
listDataHeader.add("Bus");
listDataHeader.add("Train");
listDataHeader.add("Flignt");

// Adding child data
List<String> busitems = new ArrayList<String>();
busitems.add("Madurai Radha");
busitems.add("KPN");
busitems.add("Raja");
busitems.add("Parveen");

List<String> trainitems = new ArrayList<String>();
trainitems.add("Pandian");
trainitems.add("Coimbatore");
trainitems.add("Pothigai");

List<String> airitems = new ArrayList<String>();
airitems.add("Air India");
airitems.add("Air Asia");
airitems.add("Air Bus");

listDataChild.put(listDataHeader.get(0), busitems); // Header, Child data
listDataChild.put(listDataHeader.get(1), trainitems);
listDataChild.put(listDataHeader.get(2), airitems);
}

@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
// TODO Auto-generated method stub

Toast.makeText(
getApplicationContext(),
"child item clicked Group :" + groupPosition
+ " Child position :" + childPosition, 0).show();
return true;
}
}

ExpandableListAdapter
----------------------------

import java.util.HashMap;
import java.util.List;

import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;

public class ExpandableListAdapter extends BaseExpandableListAdapter {

private Context context;
private List<String> listDataHeader;
private HashMap<String, List<String>> listDataChild;

public ExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listChildData) {

this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = listChildData;

}

@Override
public int getGroupCount() {

return this.listDataHeader.size();
}

@Override
public int getChildrenCount(int groupPosition) {

return this.listDataChild.get(this.listDataHeader.get(groupPosition))
                .size();
}

@Override
public Object getGroup(int groupPosition) {

return this.listDataHeader.get(groupPosition);
}

@Override
public Object getChild(int groupPosition, int childPosition) {

return this.listDataChild.get(this.listDataHeader.get(groupPosition))
                .get(childPosition);
}

@Override
public long getGroupId(int groupPosition) {

return groupPosition;
}

@Override
public long getChildId(int groupPosition, int childPosition) {

return childPosition;
}



@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.list_group_item, null);
}

TextView lblListHeader = (TextView) convertView
.findViewById(R.id.lblListHeader);
lblListHeader.setTypeface(null, Typeface.BOLD);
lblListHeader.setText(headerTitle);

return convertView;
}

@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {

if (childPosition == 0) {

System.out.println("child postion 0");
}

final String childText = (String) getChild(groupPosition, childPosition);

if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.list_child_item, null);
}

TextView txtListChild = (TextView) convertView
.findViewById(R.id.lblListItem);

txtListChild.setText(childText);
return convertView;
}

@Override
public boolean hasStableIds() {

return false;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {

return true;
}



}

activity_expandablelistview.xml
----------------------------------------

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.eswaran.fragements.ExpandableListviewActivity" >

    <ExpandableListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/expandablelistview"
        android:groupIndicator="@drawable/group_indicator"
        />

</RelativeLayout>



list_group_item.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="wrap_content"
    android:orientation="vertical"
    android:padding="8dp"
    >
 
 
    <TextView
        android:id="@+id/lblListHeader"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
        android:textSize="17dp"
        android:textColor="@color/fc_background_dark_green" />
 
</LinearLayout>


list_child_item.xml
-----------------------

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="55dip"
    android:orientation="vertical" >
 
    <TextView
        android:id="@+id/lblListItem"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="17dip"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft" />
 
</LinearLayout>


group_indicator.xml
-------------------------

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/add" android:state_empty="true"></item>
    <item android:drawable="@drawable/minus" android:state_expanded="true"></item>
    <item android:drawable="@drawable/add"></item>

</selector>






Monday, 29 April 2013

Loading Image

Hey everyone!
Recently while working on a project I was asked to lazy load a list of images (bitmaps) into a ListView. What made the task even trickier was the fact that each image had to be streamed from a given URL. I thought about downloading all of the images at the application’s startup Activity, and then dumping them into some kind of external SD card as a cache, but I was told that the images were subject to frequent change and that true caching would be difficult. The result is how I chose to implement the feature, and I thought I’d share it with everyone.
Now there’s no guarantee that the way I’m doing this is the “correct” or optimal way – in fact if you DO know the best way to lazy load images from URLs then please share – but the solution below works and uses a handful of Android classes and concepts, all of which I’ll note as I walk you through the solution.
Before I move onto the code, let’s conceptually think about how we’re going to make this feature work. In this example, let’s say we’re making an HTTP request to some external server that returns a list of Students. Each Student has a name and an image URL which is to be streamed, converted into a Bitmap, and then displayed in a ListView. Getting the list of Student objects is the easy part – but what’s the next step? One option is to loop through each Student, grab each Student’s image URL, convert the URL into a Bitmap, and then allow each Student to hold a reference to their Bitmap; at which point we can load the list like we normally would.
A very feasible solution – but depending on the size of your Student list. Let’s assume that each image takes between 0.5 to 1 seconds to load. Now, if your database only has 5-10 Students in it, then maybe this iterative solution may work. However, consider a database with 100s of Students – clearly this iterative solution won’t hold up in that case. What’s the better solution? Wouldn’t it be nice if we could parallelize the loading process?
That’s step one – thinking of a way to parallelize the process. Step two is to do all this loading and processing on separate background threads. This way the user can interact with the application, even while the images are loading. The last step, step three, is to make sure that each background thread can somehow communicate with the original ListAdapter and make sure that the list gets updated each time an image is successfully streamed.
With that, here’s the code.
First, let’s start with a basic Student object. Each Student has a picture that needs to be loaded, and each student holds a reference to both their image’s URL as well as their Bitmap (to be downloaded):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class Student {
 
    private String name;
 
    private String imgUrl;
 
    private Bitmap image;
 
    private StudentAdapter sta;
 
    public Student(String name, String imgUrl) {
                this.name = name;
                this.imgUrl = imgUrl;
 
                // TO BE LOADED LATER - OR CAN SET TO A DEFAULT IMAGE
                this.image = null;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getImgUrl() {
        return imgUrl;
    }
 
    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
    }
 
        public Bitmap getImage() {
        return image;
    }
 
    public StudentAdapter getAdapter() {
        return sta;
    }
 
    public void setAdapter(StudentAdapter sta) {
        this.sta = sta;
    }
 
    public void loadImage(StudentAdapter sta) {
        // HOLD A REFERENCE TO THE ADAPTER
        this.sta = sta;
        if (imgUrl != null && !imgUrl.equals("")) {
            new ImageLoadTask().execute(imgUrl);
        }
    }
 
    // ASYNC TASK TO AVOID CHOKING UP UI THREAD
    private class ImageLoadTask extends AsyncTask<String, String, Bitmap> {
 
        @Override
        protected void onPreExecute() {
            Log.i("ImageLoadTask", "Loading image...");
        }
 
        // param[0] is img url
        protected Bitmap doInBackground(String... param) {
            Log.i("ImageLoadTask", "Attempting to load image URL: " + param[0]);
            try {
                Bitmap b = ImageService.getBitmapFromURLWithScale(param[0]);
                return b;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
 
        protected void onProgressUpdate(String... progress) {
            // NO OP
        }
 
        protected void onPostExecute(Bitmap ret) {
            if (ret != null) {
                Log.i("ImageLoadTask", "Successfully loaded " + name + " image");
                image = ret;
                if (sta != null) {
                    // WHEN IMAGE IS LOADED NOTIFY THE ADAPTER
                    sta.notifyDataSetChanged();
                }
            } else {
                Log.e("ImageLoadTask", "Failed to load " + name + " image");
            }
        }
    }
 
}
Alright so what’s going on here? Again, the Student object we have here is very simple – it has only a name, image URL, and Bitmap image associated with it. For now, the image will be null (or a default image can be used) but we choose to hold a reference to it so that once it is loaded, we can “cache” it and only have to load it once.
Then, let’s note two things. First, we see that each Student has a loadImage() method which initiates an AsyncTask that we created called ImageLoadTask. By containing the loading process within the Student object, we’ve found a natural way to address step one and parallelize the process. Now, each Student can independently kick off their image loading processes and independently handle the resulting Bitmap. Why do we use an AsyncTask? Well that’s to address step two above and make sure that each process is loaded in a background thread. By doing this, we guarantee that each Student manages their own image Bitmap, and without disturbing the main UI thread!
Furthermore, we see that each Student object holds a reference to a StudentAdapter, whose code will be shown next. This is our solution to step three from above. By holding a reference to the Adapter, we can make sure that once the Student’s image is loaded (through the ImageLoadTask), the Student can then tell the adapter to update itself using the Adapter’s notifyDataSetChanged() method.
Let’s take a quick look at how the StudentAdapter is defined:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class StudentAdapter extends BaseAdapter {
 
    private LayoutInflater mInflater;
 
    private List items = new ArrayList();
 
    public StudentAdapter(Context context, List items) {
        mInflater = LayoutInflater.from(context);
        this.items = items;
    }
 
    public int getCount() {
        return items.size();
    }
 
    public Student getItem(int position) {
        return items.get(position);
    }
 
    public long getItemId(int position) {
        return position;
    }
 
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        Student s = items.get(position);
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.row_layout, null);
            holder = new ViewHolder();
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.image = (ImageView) convertView.findViewById(R.id.image);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.name.setText(s.getName());
        if (s.getImage() != null) {
            holder.pic.setImageBitmap(s.getImage());
        } else {
                // MY DEFAULT IMAGE
            holder.pic.setImageResource(R.drawable.generic_profile_man);
        }
        return convertView;
    }
 
    static class ViewHolder {
        TextView name;
 
        ImageView pic;
    }
 
}
Pretty simple really and nothing much to say. Really you just have to note that in the getView() method, if the Student’s image is null (implying that the Student’s image hasn’t been loaded yet) then I set the image to be a default generic profile picture. And so let’s bring this all together by looking at how we’d set this up in an Activity class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class StudentListActivity extends ListActivity {
 
        private List students;
 
        private StudentAdapter sta;
 
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.list);
 
                // GET YOUR STUDENTS
                students = //...
 
                // CREATE BASE ADAPTER
                sta = new StudentAdapter(StudentListActivity.this, students);
 
                // SET AS CURRENT LIST
                setListAdapter(sta);
 
                for (Student s : students) {
                        // START LOADING IMAGES FOR EACH STUDENT
                        s.loadImage(sta);
                }
        }
 
}
And voila! That’s it! We look through our list of Students, and for each Student we call their loadImage() method, making sure we pass in the instantiated ListAdapter. Then, each loadImage() method will kick off an AsyncTask that will stream the image, cache it as a Bitmap, and then notify the ListAdapter to update itself.
How this is going to look at the end will be a list that the user can scroll through, where each row is loading itself behind the scenes, and displaying its image as soon as the loading is done. Hopefully this all makes sense – and again happy to hear other solutions as well! Best of luck and as usual, happy coding.



--------------------------------------------------------------------------------------
Hey everyone,
This post is for anyone who has ever wanted to load an image from a given URL and turn it into a Bitmap which you can then use to set as an ImageView’s background, or upload as a Contact’s photo, etc.
So here it is,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static Bitmap getBitmapFromURL(String src) {
    try {
        URL url = new URL(src);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}
Nothing too complicated – simply create a URL object using the “src” string (i.e. String src = “http://thinkandroid.wordpress.com&#8221;), connect to it, and use Android’s BitmapFactory class to decode the input stream. The result should be your desired Bitmap object!
- jwei

Top to bottom animation android

Create anim folder in res.


slide_in_up.xml
--------------------

<?xml version="1.0" encoding="utf-8"?>

<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="0%p"
    android:toYDelta="-100%p"
    android:duration="@android:integer/config_longAnimTime"
    />

slide_out_up.xml
--------------------
<?xml version="1.0" encoding="utf-8"?>

<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="0%p"
    android:toYDelta="-100%p"
    android:duration="@android:integer/config_longAnimTime"
    />


Implement in java
---------------------

Intent intent = new Intent(this, Secondscreen.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up);

***********************************************************************************

For back button animation
-----------------------------

@Override
    public void onBackPressed() {
        super.onBackPressed();
      
        finish();
        overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up);
    }



BroadCast in android


Ref:

http://www.javacodegeeks.com/2012/08/android-broadcast-receiver-enable-and.html


activity_brord_casting.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'>

     <Button
        android:layout_width='fill_parent'
        android:layout_height='wrap_content'
        android:padding='10dip'
        android:text='@string/start_repeating_alarm'
        android:onClick='startRepeatingAlarm'
        tools:context='.EnableDisableBroadcastReceiver' />
     <Button
       android:layout_width='fill_parent'
       android:layout_height='wrap_content'
       android:padding='10dip'
       android:text='@string/cancel_alarm'
       android:onClick='cancelAlarm'
       tools:context='.EnableDisableBroadcastReceiver' />
    
    <Button
        android:layout_width='fill_parent'
        android:layout_height='wrap_content'
        android:padding='10dip'
        android:text='@string/enable_broadcast_receiver'
        android:onClick='enableBroadcastReceiver'
        tools:context='.EnableDisableBroadcastReceiver' />
   <Button
       android:layout_width='fill_parent'
       android:layout_height='wrap_content'
       android:padding='10dip'
       android:text='@string/disable_broadcast_receiver'
       android:onClick='disableBroadcastReceiver'
       tools:context='.EnableDisableBroadcastReceiver' />
      
</LinearLayout>


BrordCastingActivity.Java
-----------------------------

package com.example.broadcastingexample;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.view.View;
import android.widget.Toast;

public class BrordCastingActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_brord_casting);
    }
       /**
     * This method gets called when 'Start Repeating Alarm' button is pressed.
     * It sets the repeating alarm whose periodicity is 3 seconds.
     * @param view
     */
    public void startRepeatingAlarm(View view)
    {
        AlarmManager am=(AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(this, AlarmManagerBroadcastReceiver.class);
        PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, 0);
        //After after 2 seconds
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 4 , pi);
        Toast.makeText(this, "Started Repeating Alarm", Toast.LENGTH_SHORT).show();
    }
 /**
  * This method gets called when 'cancel Alarm' button is pressed.
  * This method cancels the previously set repeating alarm.
  * @param view
  */
    public void cancelAlarm(View view)
    {
        Intent intent = new Intent(this, AlarmManagerBroadcastReceiver.class);
        PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, 0);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(sender);
        Toast.makeText(this, "Cancelled alarm", Toast.LENGTH_SHORT).show();
    }
    /**
     * This method enables the Broadcast receiver registered in the AndroidManifest file.
     * @param view
     */
   public void enableBroadcastReceiver(View view){
    ComponentName receiver = new ComponentName(this, AlarmManagerBroadcastReceiver.class);
    PackageManager pm = this.getPackageManager();

    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);
    Toast.makeText(this, "Enabled broadcast receiver", Toast.LENGTH_SHORT).show();
   }
   /**
    * This method disables the Broadcast receiver registered in the AndroidManifest file.
    * @param view
    */
   public void disableBroadcastReceiver(View view){
    ComponentName receiver = new ComponentName(this, AlarmManagerBroadcastReceiver.class);
    PackageManager pm = this.getPackageManager();

    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);
    Toast.makeText(this, "Disabled broadcst receiver", Toast.LENGTH_SHORT).show();
   }  
}


AlarmManagerBroadcastReceiver.Java
------------------------------------------

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public class AlarmManagerBroadcastReceiver extends BroadcastReceiver {

     final public static String ONE_TIME = "onetime";
     final private String tag="tag";
     @Override
     public void onReceive(Context context, Intent intent) {

              Log.i(tag, "msg");
             //You can do the processing here update the widget/remote views.
             StringBuilder msgStr = new StringBuilder();
             Log.i(tag, "msg2");
             //Format time.
             Format formatter = new SimpleDateFormat("hh:mm:ss a");
             Log.i(tag, "msg3");
             msgStr.append(formatter.format(new Date()));
             Log.i(tag, "msg4");

             Toast.makeText(context, msgStr, Toast.LENGTH_SHORT).show();
             Log.i(tag, "msg5");
                    
     }
}


androidmanitest

--------------------


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcastingexample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="10" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.broadcastingexample.BrordCastingActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       
         <!-- Broadcast receiver -->
        <receiver android:name='com.example.broadcastingexample.AlarmManagerBroadcastReceiver' />
    </application>

</manifest>


Thursday, 18 April 2013

Barcode scanner using Zxing

Android barcode scanner using Zxing

How to call Zxing barcode scanner from you application using Intent? The ZXing project provides a standalone barcode reader application using Android's intent mechanism, can be called by other applications who wish to integrate barcode scanning.

If you want to integrate barcode scanning directly into your application without relying on having the separate ZXing application installed, then you can do so! It's an open source project and the code is available for free and can be downloaded at http://code.google.com/p/zxing/.You are going to add the whole ZXing project core to your app and modify as you wish. This way your app will no longer require ZXing app exist in client device.

ZXing uses phone or tablet camera to scan barcodes, QR codes or multi-format 1D/2D barcodes. So the scan result highly depends on the camera quality and resolution. ZXing has relatively fast processing speed. More importantly, it is an open source projectso you can do whatever changes you like to it!

Android barcode scanner using Zxing

Example source code for using Zxing barcode scanner from you application using Intent



Source for main.xml screen layout

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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"
 android:layout_gravity="center">
 <TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/hello"
  android:gravity="center" android:textSize="25sp"/>
 <Button android:text="Scan QR Code" android:id="@+id/scanner"
  android:layout_width="wrap_content" android:layout_height="wrap_content"
  android:gravity="center" android:layout_gravity="center_horizontal">
 </Button>
 <Button android:text="Scan BAR Code" android:id="@+id/scanner2"
  android:layout_width="wrap_content" android:layout_height="wrap_content"
  android:gravity="center" android:layout_gravity="center_horizontal">
 </Button>
</LinearLayout>

Source for AndroidScanner.java program for barcode scanning

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.as400samplecode;
 
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
 
public class AndroidScanner extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        try {
            Button scanner = (Button)findViewById(R.id.scanner);
            scanner.setOnClickListener(new OnClickListener() {
                
                public void onClick(View v) {
                    Intent intent = new Intent("com.google.zxing.client.android.SCAN");
                    intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
                    startActivityForResult(intent, 0);
                }
 
            });
            
            Button scanner2 = (Button)findViewById(R.id.scanner2);
            scanner2.setOnClickListener(new OnClickListener() {
                
                public void onClick(View v) {
                    Intent intent = new Intent("com.google.zxing.client.android.SCAN");
                    intent.putExtra("SCAN_MODE", "PRODUCT_MODE");
                    startActivityForResult(intent, 0);
                }
 
            });
            
        } catch (ActivityNotFoundException anfe) {
            Log.e("onCreate", "Scanner Not Found", anfe);
        }
        
    }
    
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (requestCode == 0) {
            if (resultCode == RESULT_OK) {
                String contents = intent.getStringExtra("SCAN_RESULT");
                String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
                // Handle successful scan
                Toast toast = Toast.makeText(this, "Content:" + contents + " Format:" + format , Toast.LENGTH_LONG);
                toast.setGravity(Gravity.TOP, 25, 400);
                toast.show();
            } else if (resultCode == RESULT_CANCELED) {
                // Handle cancel
                Toast toast = Toast.makeText(this, "Scan was Cancelled!", Toast.LENGTH_LONG);
                toast.setGravity(Gravity.TOP, 25, 400);
                toast.show();
                
            }
        }
    }
 
}

TIP: You can make your application check for existence of the Zxing application. 

See IntentIntegrator for a possibly easier way to integrate. In particular this will handle the case where Barcode Scanner is not yet installed. Click on the link below for more details

http://code.google.com/p/zxing/source/browse/trunk/android-integration/src/com/google/zxing/integration/android/IntentIntegrator.java

Sample code from IntentIntegrator.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private static final String PACKAGE = "com.google.zxing.client.android";
 
catch (ActivityNotFoundException e) {
      return showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo);
    }
 
private static AlertDialog showDownloadDialog(final Activity activity,
                                                CharSequence stringTitle,
                                                CharSequence stringMessage,
                                                CharSequence stringButtonYes,
                                                CharSequence stringButtonNo) {
    AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
    downloadDialog.setTitle(stringTitle);
    downloadDialog.setMessage(stringMessage);
    downloadDialog.setPositiveButton(stringButtonYes, new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialogInterface, int i) {
        Uri uri = Uri.parse("market://search?q=pname:" + PACKAGE);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        try {
          activity.startActivity(intent);
        } catch (ActivityNotFoundException anfe) {
          // Hmm, market is not installed
          Log.w(TAG, "Android Market is not installed; cannot install Barcode Scanner");
        }
      }
    });
    downloadDialog.setNegativeButton(stringButtonNo, new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialogInterface, int i) {}
    });
    return downloadDialog.show();
  }

More information on Zxing scanner application


According to ZXing (pronounced "zebra crossing") is an open-source, multi-format 1D/2D barcode image processing library implemented in Java, with ports to other languages. Our focus is on using the built-in camera on mobile phones to scan and decode barcodes on the device, without communicating with a server. However the project can be used to encode and decode barcodes on desktops and servers as well. We currently support these formats:

  • UPC-A and UPC-E
  • EAN-8 and EAN-13
  • Code 39
  • Code 93
  • Code 128
  • QR Code
  • ITF
  • Codabar
  • RSS-14 (all variants)
  • Data Matrix
  • PDF 417 ('alpha' quality)
  • Aztec ('alpha' quality)

To scan codabar format pass the intent extra the format as explained below

/**
* Comma-separated list of formats to scan for. The values must match the names of
* {@link com.google.zxing.BarcodeFormat}s, e.g. {@link com.google.zxing.BarcodeFormat#EAN_13}.
* Example: "EAN_13,EAN_8,QR_CODE"
*
* This overrides {@link #MODE}.
*/
?
1
2
public static final String FORMATS = "SCAN_FORMATS";
intent.putExtra("SCAN_FORMATS", "CODABAR");


List of barcode formats supported by ZXING

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/** QR Code 2D barcode format. */
public static final BarcodeFormat QR_CODE = new BarcodeFormat("QR_CODE");
 
/** DataMatrix 2D barcode format. */
public static final BarcodeFormat DATA_MATRIX = new BarcodeFormat("DATA_MATRIX");
 
/** UPC-E 1D format. */
public static final BarcodeFormat UPC_E = new BarcodeFormat("UPC_E");
 
/** UPC-A 1D format. */
public static final BarcodeFormat UPC_A = new BarcodeFormat("UPC_A");
 
/** EAN-8 1D format. */
public static final BarcodeFormat EAN_8 = new BarcodeFormat("EAN_8");
 
/** EAN-13 1D format. */
public static final BarcodeFormat EAN_13 = new BarcodeFormat("EAN_13");
 
/** UPC/EAN extension format. Not a stand-alone format. */
public static final BarcodeFormat UPC_EAN_EXTENSION = new BarcodeFormat("UPC_EAN_EXTENSION");
 
/** Code 128 1D format. */
public static final BarcodeFormat CODE_128 = new BarcodeFormat("CODE_128");
 
/** Code 39 1D format. */
public static final BarcodeFormat CODE_39 = new BarcodeFormat("CODE_39");
 
/** Code 93 1D format. */
public static final BarcodeFormat CODE_93 = new BarcodeFormat("CODE_93");
 
/** CODABAR 1D format. */
public static final BarcodeFormat CODABAR = new BarcodeFormat("CODABAR");
 
/** ITF (Interleaved Two of Five) 1D format. */
public static final BarcodeFormat ITF = new BarcodeFormat("ITF");
 
/** RSS 14 */
public static final BarcodeFormat RSS14 = new BarcodeFormat("RSS14");
 
/** PDF417 format. */
public static final BarcodeFormat PDF417 = new BarcodeFormat("PDF417");
 
/** RSS EXPANDED */
public static final BarcodeFormat RSS_EXPANDED = new BarcodeFormat("RSS_EXPANDED");

Did you find this article helpful? Share it!