Sunday 15 January 2017

HB Blog 127: Creating A Custom Account Type.

So far we've talked about accessing Google APIs, which use accounts and users defined by Google. If you have your own online service, though, it won't have Google accounts or users, so what do you do? It turns out to be relatively straightforward to install new account types on a user's device. This tutorial explains how to create a custom account type that works the same way as the built-in accounts do.
The first thing you'll need is a way to get credentials from the user. This may be as simple as a dialog box that asks for a name and a password. Or it may be a more exotic procedure like a one-time password or a biometric scan. Either way, it's your responsibility to implement the code that:
  1. Collects credentials from the user
  2. Authenticates the credentials with the server
  3. Stores the credentials on the device
Refer the below link for complete sample code:-

Download Sample Code

You need to setup multiple components to be able to create an account programmatically. You need:
  •     an AccountAuthenticator
  •     a Service to provide access to the AccountAuthenticator
  •     some permissions
The Authenticator
The authenticator is an object that will make the mapping between the account type and the autority (i.e. the linux-user) that have rights to manage it.

Declaring an authenticator
is done in xml :
create a file res/xml/authenticator.xml with the following content :
1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.example.harshalbenake.accountsetting.DEMOACCOUNT"
    android:icon="@drawable/ic_launcher"
    android:smallIcon="@drawable/ic_launcher"
android:label="@string/app_name"/>
Note the accountType : it must be reused in code when you create the Account. The icons and label will be used by the "Settings" app to display the accounts of that type.

Implementing the AccountAuthenticator
You must extends AbstractAccountAuthenticator to do that. This will be use by third party app to access Account data.
The following sample don't allow any access to 3rd-party app and so the implementation of each method is trivial.
 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
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.NetworkErrorException;
import android.content.Context;
import android.os.Bundle;

public class CustomAuthenticator extends AbstractAccountAuthenticator {

    public CustomAuthenticator(Context context) {
        super(context);
    }

    @Override
    public Bundle addAccount(AccountAuthenticatorResponse accountAuthenticatorResponse, String s, String s2, String[] strings, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse, String s) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public String getAuthTokenLabel(String s) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] strings) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }
}

The Service exposing the Account Type

Create a Service to manipulate the Accounts of that type :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class AuthenticatorService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        CustomAuthenticator authenticator = new CustomAuthenticator(this);
        return authenticator.getIBinder();
    }
}

Declare the service in your manifest :
1
2
3
4
5
6
7
8
  <service android:name=".AuthenticatorService" android:exported="false">
  <intent-filter>
  <action android:name="android.accounts.AccountAuthenticator"/>
  </intent-filter>
  <meta-data
                android:name="android.accounts.AccountAuthenticator"
                android:resource="@xml/authenticator"/>
</service>
Here, the filter and the meta-data referring to the xml resource declaring the authenticator are the key points.

The permissions
In your manifest be sure to declare the following permissions
1
2
3
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
(not all required for the sample code presented in this post, but you will probably have some more code about account management and at the end all of them will be useful)

Create an account in code
Now that everything is ready you create an account with the following code. Note the boolean returned by addAccountExplicitly informing you about the success or failure.
 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
import android.accounts.Account;
import android.accounts.AccountManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AccountManager accountManager = AccountManager.get(this);
        Account account = new Account("HBAccount","com.example.harshalbenake.accountsetting.DEMOACCOUNT");
        boolean success = accountManager.addAccountExplicitly(account,"password",null);
        if(success){
            Toast.makeText(MainActivity.this,"Account created",Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(MainActivity.this,"Account creation failed. Look at previous logs to investigate",Toast.LENGTH_SHORT).show();
        }

        Account[] accounts = AccountManager.get(this).getAccounts();
        for (Account account1 : accounts) {
            Toast.makeText(MainActivity.this, "Name: " + account1.name+" Type: " + account1.type,Toast.LENGTH_SHORT).show();
        }
    }
}

Sunday 1 January 2017

HB Blog 126: Android For Graphic Designers.

Graphic designers aren't programmers and sometimes don't know how to properly prepare graphic assets for developers. This simple tutorial should help them to do their job better, and to simplify developers lives.

Screen densities and icon dimensions
Qualifier DPI Scaling factor Launcher icon Action bar, tab icon Notification icon (API 11) Notification icon (API 9) Notification icon (older)
ldpi 120 0.75 36 x 36
32 x 32
24 x 24
18 x 18
18 x 18
16 x 16
12 x 19
12 x 12
19 x 19
16 x 16
mdpi 160 1.0 48 x 48
42 x 42
32 x 32
24 x 24
24 x 24
22 x 22
16 x 25
16 x 16
25 x 25
21 x 21
hdpi 240 1.5 72 x 72
64 x 64
48 x 48
36 x 36
36 x 36
33 x 33
24 x 38
24 x 24
38 x 38
32 x 32
xhdpi 320 2.0 96 x 96
84 x 84
64 x 64
48 x 48
48 x 48
44 x 44
32 x 50
32 x 32
50 x 50
42 x 42
xxhdpi 480 3.0 144 x 144
126 x 126
96 x 96
72 x 72
72 x 72
66 x 66
48 x 75
48 x 48
75 x 75
63 x 63
Notice: the first icon dimension in table cell is full asset size, the second icon dimension is optical square. Dimension values are in pixels.
Tip: creating ldpi assets is not really needed anymore. The devices are rare and the platform will just scale down mdpi.


Google Play asset dimensions 
Asset Type Required Image type Dimension
Screenshot yes JPEG or 24-bit PNG
(no alpha)
min length for any side: 320 px
max length for any side: 3840 px
High-res app icon yes 32-bit PNG
(with alpha)
512 x 512 px
Feature graphic yes JPEG or 24-bit PNG
(no alpha)
1024 x 500 px
Promotional graphic no JPEG or 24-bit PNG
(no alpha)
180 x 120 px
Video link no URL of YouTube video -

Dimension units
Unit Units / physical inch Density independent Same physical size on every screen
px varies no no
in 1 yes yes
mm 25.4 yes yes
pt 72 yes yes
dp ~160 yes no
sp ~160 yes no

Size buckets
Type Dimension
Handset smaller than 600 dp
Tablet larger than or equal 600 dp
Size buckets
Notice: one dp (density-independent pixel) is one pixel on a 160 DPI screen.

Views dimensions and spacing
Touchable UI components are generally laid out along 48 dp units. Spacing between each UI element is 8 dp.
48dp rhythm
Button dimensions and spacing
Form dimensions and spacing
Action bar height
Qualifier Dimension
Portrait 48 dp
Landscape 40 dp
Tablet 56 dp

Text size
Type Dimension
Micro 12 sp
Small 14 sp
Medium 18 sp
Large 22 sp
Notice: one sp (scale-independent pixel) is one pixel on a 160 DPI screen if the user's global text scale is set to 100%.

Images and themes
Nine-patch 
A Nine-patch drawable is a stretchable bitmap image, which Android will automatically resize to accommodate the contents of the view in which you have placed it as the background, e.g. nine-patch background for button, which must stretch to accommodate strings of various lengths. The rules for nine-patch image are following:
  • Standard PNG image with alpha
  • Filename suffix is ".9.png", e.g. "btn_login_normal.9.png"
  • Image has an extra 1 pixel wide border, used to define the stretchable/static/padding areas
  • Stretchable sections are indicated by 1 px wide black line(s) in the left and top part of the border
  • Static sections are indicated by fully transparent or white pixels
  • Padding area (optional) is indicated by 1 px wide black line in the right and bottom part of the border
Nine-patch
Colors
Use color primarily for emphasis. Blue is the standard accent color in Android's color palette. Note that red and green may be indistinguishable to color-blind users. Primary colors are as follows:
  • #33B5E5
  • #AA66CC
  • #99CC00
  • #FFBB33
  • #FF4444
  • #0099CC
  • #9933CC
  • #669900
  • #FF8800
  • #CC0000




Holo themes
Android provides three system themes:
  • Holo Light
  • Holo Dark
  • Holo Light with dark action bar

Naming conventions

Naming conventions for drawables
Asset Type Prefix Example
Action bar ab_ ab_stacked.9.png
Button btn_ btn_send_pressed.9.png
Dialog dialog_ dialog_top.9.png
Divider divider_ divider_horizontal.9.png
Icon ic_ ic_star.png
Menu menu_ menu_submenu_bg.9.png
Notification notification_ notification_bg.9.png
Tabs tab_ tab_pressed.9.png
File names must contain only lowercase a-z, 0-9, or _.
Drawables for the specific views (ListView, TextView, EditText, ProgressBar, CheckBox etc.) should be named like this views keeping the naming rules, e.g. drawable for CheckBox should be named "checkbox_on_bg.png".

Naming conventions for icon assets
Asset Type Prefix Example
Icons ic_ ic_star.png
Launcher icons ic_launcher ic_launcher_calendar.png
Action bar icons ic_menu ic_menu_archive.png
Status bar icons ic_stat_notify ic_stat_notify_msg.png
Tab icons ic_tab ic_tab_recent.png
Dialog icons ic_dialog ic_dialog_info.png

Naming conventions for selector states
State Suffix Example
Normal _normal btn_order_normal.9.png
Pressed _pressed btn_order_pressed.9.png
Focused _focused btn_order_focused.9.png
Disabled _disabled btn_order_disabled.9.png
Selected _selected btn_order_selected.9.png

Organizing drawables to directories
One drawable must have the same file name for all screen densities (ldpi, mdpi, hdpi etc.) and all these files must be organized according to density into the following directories. Here's the resources directory structure for drawables:
  • res
    • drawable-ldpi
    • drawable-mdpi
    • drawable-hdpi
    • drawable-xhdpi
    • drawable-xxhdpi