KDE Connect: Connecting your devices to KDE

KDE Connect

KDE Connect was initially developed as part of a KDE GSoC project in 2013 and is one of those exciting KDE projects that makes you love more this awesome community.  KDE Connect aims to communicate and connect all sort of devices to KDE and vice versa. The objective of KDE Connect is to make your devices interact with each other in a simple and efficient way. Some examples:  Imagine, with a single click, send a document/picture/video from your desktop to your Android phone or control your desktop media player from your mobile. KDE Connect, at the moment, support the following features: … Continue reading “KDE Connect: Connecting your devices to KDE”

Advertisements

Android QR Code Scanner – Quick Guide

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… Continue reading “Android QR Code Scanner – Quick Guide”

Joel on Software

Joel Spolsky is a famous blogger in the software world. He’s an ex-Microsoft employee who worked in the Excel team, is the Co-Founder of Fog Creek, a software company with a great culture and successful products like Trello, FofBugz, Copilot, CityDesk… By the way, the Fog Creek culture is really simple and is summarized like this:

Best Working Conditions -> Best Programmers -> Best Software -> Profit

It’s really funny (Life is to too short, we have to laugh and smile), how some managers still don’t understand this and make the programmers job really painful. Wake up! Wake up! managers.

Joel started writing articles in 2000 and has influenced the way of thinking of many people around the globe. Although, he’s not very active today, he has written really great articles about Software Development, Programming, Design, Startups, Recruiting and Interviews.

If you are a Software Developer, CEO, Team Leader, Product Manager, Startup founder, CS student or just work in the Software Industry, I think you will find these articles really interesting.

You can find all those articles in his blog or you can buy the two books with his writings in Amazon. I really enjoy reading in a tablet too. So, instead of buying the two books, I downloaded the Joel on Software Android app, created by the software company Digicorp. You can use the app, even without an Internet connection. Thanks guys!.

Joel on Software - Android App

These are my favorite articles, in no particular order:

Go and read, buy or download the Joel on Software stuff, it’s worth reading.

Android Code Snippets: Improving Layout Performance

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;
    }

Android Code Snippets: Getting the device metrics

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;
    }

...

Android Code Snippets: Adapter notifyDataSetChanged()

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

Android Code Snippets: Get User Accounts by domain

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” />