Imaginemos un mundo libre

La paz interior comienza en el momento en el que decides no permitir, que ninguna persona o evento, tome el control de tus emociones.

Posts Tagged ‘Desarrollador Android

Android QR Code Scanner – Quick Guide

leave a comment »

In this tutorial, we are going to build a simple Android QR Scanner using ZXing, a well known Open Source library to work with bar and qr codes.

Our small QR Scanner works this way: We call the Barcode Scanner app with an Intent action, it gets the QR Code and send it back to our app.

One problem, is that probably the user doesn’t have the Barcode scanner app installed. In this case our QR Scanner needs to tell this the user and redirect them to Google Play in order to install it.

So, we are going to use ZXing to manage this situation.

1.- Add ZXing to your project.

In particular, we need two Zxing classes, IntentIntegrator and IntentResult. 
Add them easily to your project. In your source directory create another package. Right click and select New -> Package. Let’s call it com.google.zxing.integration.android  and save the classes.  You can find the code here.

Then, in our activity code, we just need to import these classes:

import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;

Once, we have add ZXing to our project, we can start working on our app.

2.- Create the layout.

We need a Button to call the Barcode Scanner app and a TextView to see the qr code content scanned.

<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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.qr.scanner.MainActivity">

    <Button
        android:id="@+id/button_get_qr_code"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/get_qr_code" />

    <TextView
        android:id="@+id/text_view_qr_content"
        android:layout_below="@+id/button_get_qr_code"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

Obviously, we have a  <string name=”get_qr_code”>Get QR Code</string> in the strings.xml file.

3.- Create the Activity and the scanning code.

Find the layout widgets and create a method with “Get QR Code” logic:

import android.content.Intent;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

...

public class MainActivity extends Activity {
    private static final String TAG = "QR Scanner";
    private Activity mActivity;
    private Button mGetQRButton;
    private TextView mQRCodeTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mActivity = this;
        mGetQRButton = (Button) findViewById(R.id.button_get_qr_code);
        mQRCodeTextView = (TextView) findViewById(R.id.text_view_qr_content);
        setupButton();
    }

In the setupButton method, create an instant of the IntentIntegrator class and call the initiateScan() method to start scanning.

    private void setupButton() {
        mGetQRButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                IntentIntegrator integrator = new IntentIntegrator(mActivity);
                integrator.initiateScan();
            }
        });
    }

4.- Get the Scanning results.

Now, we are going to use the IntentResult class, to get the scanned data and show it in our Activity.

The IntentIntegrator will return this data to the onActivityResult method of the calling activity. Create and instant of the IntentResult class. Call the getContents() method of the scanning result and save the returned data in a string.

Finally, update your textview text with this string. It’s always useful to log what we are getting.

    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
        if (scanResult != null) {
            String scanContent = scanResult.getContents();
            mQRCodeTextView.setText(scanContent);
            Log.d(TAG, "QR Scan Content: " + scanContent);
        }
    }

You can see the full example at my GitHub account:

Advertisements

Written by Ronny Yabar

January 24, 2014 at 12:05 pm

Android Code Snippets: Improving Layout Performance

leave a comment »

A common task in Android development, is to call the findViewById() method in your adapters.
There is a repeated use of findViewById() in each cycle, because you need to look up all the elements and update them. This can be really slow in you have hundreds of elements to show, therefore the performance is affected.

What you usually do when start working with adapters is the following:

    public View getView(final int position, View convertView, ViewGroup parent) {
        convertView = inflater.inflate(R.layout.artist_item, null);
        ImageView artistImageView = (ImageView) convertView.findViewById(R.id.artist_image);
        TextViewartistNameTextView = (TextView) convertView.findViewById(R.id.artist_name);
		
        ...Update your views
		
        return convertView;
    }

Instead, use the View Holder design pattern. This will avoid to look the views up in each cycle.

First, you need to create a ViewHolder class and group your views inside it.
Then, in your getView method, match your viewHolder elements with your views in the layout.
Finally, update your views content.

    // Hold the views
    static class ViewHolder {
        ImageView artistImageView;
        TextView artistNameTextView;
    }

    // Populate viewHolder views and set up their content.
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.artist_item, null);
            viewHolder = new ViewHolder();
            viewHolder.artistImageView = (ImageView) convertView.findViewById(R.id.artist_image);
            viewHolder.artistNameTextView = (TextView) convertView.findViewById(R.id.artist_name);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        ...Update your views here

        return convertView;
    }

Written by Ronny Yabar

September 7, 2013 at 11:17 am

Android Code Snippets: Getting the device metrics

leave a comment »

It’s really important to know the device metrics (Height and width pixels, density, density dpi)  when working on an Android app, specially if you are dealing with fragmentation.

Android has a utility class called DisplayMetrics to get these device properties. Let’s say you need these properties in X activities.  It would be better create a utils class and get the device metrics there.

import android.util.DisplayMetrics;

Your class...
    public static float deviceDensity;
    public static int deviceDensityDpi;
    public static int deviceHeightPixels;
    public static int deviceWidthPixels;

    void getDeviceMetrics(Activity activity)  {
        DisplayMetrics metrics  =  new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        deviceDensity = metrics.density;
        deviceDensityDpi = metrics.densityDpi;
        deviceHeight = metrics.heightPixels;
        deviceWidth = metrics.widthPixels;
    }

...

Written by Ronny Yabar

August 3, 2013 at 1:21 pm

Android Code Snippets: Adapter notifyDataSetChanged()

leave a comment »

A common error when working with adapters in Android, is not to notify your adapter when your data has changed.  If you don’t do that, you’ll receive and exception like this:

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification.

Just call the notifyDataSetChanged() method after you modify your content.  But, maybe even if you notified your adapter, you receive an exception like this:

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread.

That means, you need to call notifyDataSetChanged() from the UI thread.  It’s better to create a method, so you can call it at anytime:

private void notifyAdapter()  {
    activity.runOnUiThread(new Runnable()  {
        public void run() {
            listView.setAdapter(null);
            if(adapter != null) {
                adapter.notifyDataSetChanged();
             }
        }
    });
}

I assume you have a listview and adapter objects created.

Enjoy

Written by Ronny Yabar

August 2, 2013 at 1:18 pm

Android Code Snippets: Get User Accounts by domain

leave a comment »

Sometimes, when working on your Android apps, you will need to get the user accounts registered on the phone. A usual scenario, is the Login stuff, where you want to get domain specific accounts.

One way to achieve this, is to use the Account and AccountManager classes. If you want to get only accounts of an specific type, use the getAccountsByType() method.

Imagine I only want to get Google Accounts of mydomain.com

I call the method account_manager.getAccountsByType(“com.google”) to get Google accounts and for matching my domain, I use the Patterns util class that works with regular expressions. What I really need is the Patterns.EMAIL_ADDRESS pattern. Once I got these accounts, I can store them in an array and do whatever I want with them.

Here we go:

import android.accounts.Account;
import android.accounts.AccountManager;
import android.util.Log;
import android.util.Patterns;
...

import java.util.ArrayList;
import java.util.regex.Pattern;

public class LoginActivity extends Activity {
    private static final String TAG = "LOGIN";
    private static final String GOOGLE_ACCOUNT = "com.google";
    private static final String DOMAIN = "@yourdomain.com";
    private ArrayList<String> mDomainAccounts = new ArrayList<String>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);
        getAccounts();
    }

    private void getAccounts() {
        AccountManager account_manager = AccountManager.get(this);
        Pattern emailPattern = Patterns.EMAIL_ADDRESS;

        if(account_manager != null) {
            Account[] accounts = account_manager.getAccountsByType(GOOGLE_ACCOUNT);
            for (Account account : accounts) {
                if (emailPattern.matcher(account.name).matches()) {
                    mDomainAccounts.add(account.name);
                    Log.i(TAG, account.name);
                }
            }
        }
    }

    ...
}

Don’t forget to add the GET_ACCOUNTS permission to your AndroidManifest:

<uses-permission android:name=”android.permission.GET_ACCOUNTS” />

Written by Ronny Yabar

July 4, 2013 at 12:47 pm

Aplicaciones Android de alta calidad por Bruno Oliveira.

leave a comment »

En un español casi perfecto,  Bruno Oliveira de Brasil y Android Developer de Google, nos explica como desarrollar aplicaciones Android de alta calidad.

Un excelente video y un “must-see” para todo desarrollador de aplicaciones móviles.  Excelente los consejos dados por Bruno, personalmente me ayudó muchísimo para seguir para seguir mejorando las habilidades como desarrollador Android.

Gracias por tu visita al blog. Puedes seguirme en Twitter haciendo click en el siguiente enlace:

Written by Ronny Yabar

December 9, 2012 at 2:32 pm

Posted in Android

Tagged with ,