Fix Xiaomi INSTALL_FAILED_USER_RESTRICTED

If you are developing android and using real device to install your build APK instead of virtual device and you are using Xiaomi phone (Mine is Xiaomi Redmi 4x) probably you will facing this error.

To fix this, what you need to do are just enable these configuration in your device.

  • Developer Mode
  • USB Debugging
  • Install via USB
  • USB debugging (Security Settings)

Reference: https://stackoverflow.com/a/49485273/1936697

Create Circle ImageView with Picasso

Here is how to create circle ImageView and load the image with picasso library.
First of all you need to create transformation subclass to create circle shape following below.

     /**
     * Enables hardware accelerated rounded corners.
     * original idea here : http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
     */
    public class RoundedTransformation implements com.squareup.picasso.Transformation {
        private final int radius;
        private final int margin;  // dp

        // radius is corner radii in dp
        // margin is the board in dp
        public RoundedTransformation(final int radius, final int margin) {
            this.radius = radius;
            this.margin = margin;
        }

        @Override
        public Bitmap transform(final Bitmap source) {
            final Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));

            Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
            canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, paint);

            if (source != output) {
                source.recycle();
            }

            return output;
        }

        @Override
        public String key() {
            return "rounded";
        }
    }

After that, what you need to do just load your image with transformation class above.

Picasso.with(yourContext)
       .load("...") // Your image source.
       .transform(new RoundedTransformation(50, 4))
       .fit()  // Fix centerCrop issue: http://stackoverflow.com/a/20824141/1936697
       .centerCrop()
       .into(yourImageView);

 

Publish GreenRobot EventBus from Service to Activity/Fragment

I assume that you already know GreenRobot EventBus, and here is how to publish data from android service to your Activity/Fragment.

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        MyData data = new MyData();
        data.setMessage("Hello...");
        EventBus.getDefault().post(data);
    }
});

reference: http://stackoverflow.com/a/33249376/1936697

Hide Samsung Tablet Soft Keyboard Programatically

Android keyboard usually will show up when there are focus in input widget like EditText. In mobile device we can avoid soft keyboard show up when at first fragment/activity start by defining this code on the input widget xml.

android:focusableInTouchMode="true"

But this method will not work in samsung tablet, in my case Samsung Galaxy Tab.
So we have to hide it programatically to hide samsung soft keyboard. We just need to add this single line on your fragment/activity initialization.

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

Reference: http://stackoverflow.com/a/10699765/1936697

Adding SSL Certificate to Retrofit 2

I assume that you already know how to get SSL certificate from your server and you already put it in android resource inside “raw” directory.

SS
SSL Certificate File

Here is how to read in in android and add to your retrofit.

private static SSLContext getSSLConfig(Context context) throws CertificateException, IOException,
            KeyStoreException, NoSuchAlgorithmException, KeyManagementException {

    // Loading CAs from an InputStream
    CertificateFactory cf = null;
    cf = CertificateFactory.getInstance("X.509");

    Certificate ca;
    // I'm using Java7. If you used Java6 close it manually with finally.
    try (InputStream cert = context.getResources().openRawResource(R.raw.your_certificate)) {
        ca = cf.generateCertificate(cert);
    }

    // Creating a KeyStore containing our trusted CAs
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore keyStore   = KeyStore.getInstance(keyStoreType);
    keyStore.load(null, null);
    keyStore.setCertificateEntry("ca", ca);

    // Creating a TrustManager that trusts the CAs in our KeyStore.
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(keyStore);

    // Creating an SSLSocketFactory that uses our TrustManager
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), null);

    return sslContext;
}

By default Retrofit using OkHttp as the http client library, and here is the last step.

Retrofit.Builder builder = new Retrofit.Builder().baseUrl(Constant.BASE_API_URL);

OkHttpClient okHttp = new OkHttpClient();
okHttp.setSslSocketFactory(getSSLConfig(contex).getSocketFactory());

Retrofit retrofit = builder.client(okHttp).build();
retrofit.create(serviceClass)

References:
http://developer.android.com/training/articles/security-ssl.html
http://stackoverflow.com/a/31436459/1936697

Basic Reactive Programming with RxJava

Just found interesting blog post series about reactive programming with RxJava.

http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
http://blog.danlew.net/2014/09/22/grokking-rxjava-part-2/
http://blog.danlew.net/2014/09/30/grokking-rxjava-part-3/
http://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/

Thanks to Daniel Lew 😀

 

Fix “no such column” on Sugar ORM

I have this entity class to represent my sqlite table in my android apps.

public class TemporaryOrder extends SugarRecord<TemporaryOrder> {

    public String desc;
    public float lat;
    public float lng;
    public String note;
    public boolean isFrom;

    public TemporaryOrder() {
    }

    public TemporaryOrder(String desc, float lat, float lng, String note, boolean isFrom) {
        this.desc = desc;
        this.lat = lat;
        this.lng = lng;
        this.isFrom = isFrom;
        this.note = note;
    }
}

The problem appear when I need to check, whether there’s order with “isFrom” status true by doing this.

boolean isExists = Select.from(TemporaryOrder.class).where(Condition.prop("isFrom").eq(true)).count() > 1;
// I got this error : no such column: isFrom (code 1)

Evidently SugarORM turns camel case variable to underscore in sqlite, so we just need to replace “isFrom” to “is_From”.

boolean isExists = Select.from(TemporaryOrder.class).where(Condition.prop("is_From").eq(true)).count() > 1;

Reference: https://github.com/satyan/sugar/issues/137#issuecomment-51685321

Add User Agent in Retrofit 2

I’m using retrofit for my android http library and I just know that by default there’s no “User-Agent” inside request header.
Because I have to check coming request in my backend, so I identify by “User-Agent” and I have to attach user agent to my entire request on my android project to deal with it.

Here is code snippet to add “User-Agent” to all retrofit request (I used retrofit 2)

public class UserAgentInterceptor implements Interceptor {

    private final String userAgent;

    public UserAgentInterceptor(String userAgent) {
        this.userAgent = userAgent;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originRequest = chain.request();
        Request requestWithUserAgent = originRequest.newBuilder()
                                                    .header("User-Agent", userAgent)
                                                    .build();
        return chain.proceed(requestWithUserAgent);
    }
}

And the last, what you need to do is register the interceptor above to our OKHttp inside retrofit.

String UA = System.getProperty("http.agent");  // Get android user agent.

OkHttpClient okHttp = new OkHttpClient()
okHttp.interceptors().add(new UserAgentInterceptor(UA));

Retrofit.Builder builder = new Retrofit.Builder().baseUrl("http://your-base-url.com/");
Retrofit retrofit = builder.client(okHttp).build();

Reference: http://stackoverflow.com/a/27840834/1936697