Android Gradle Plugin 2.2.0-alpha3 is missing zipalign

Today, I was trying to submit a new version of my app to Google Play and I received this message:

screen1

I’ve verified if I was submiting the debug version of my apk and I’ve confirmed that I was submiting the release version generate in Build > Generate Signed APK.  I’ve tried to use the  zipAlignEnabled true in the release buildType on gradle script but it has not worked.

So, why is it happening?

Simple, Its a problem in gradle plugin version 2.2.0-alpha3… This version doesn’t work well with the zipAlign. I’ve made some testes to check if this post that I’ve found is valid and it is.

With gradle 2.1.2 ZipAlign works fine;
With gradle 2.2.0-alpha2 ZipAlign works fine;
With gradle 2.2.0-alpha3 the APK is not zipaligned.
With gradle 2.2.0-alpha4 ZipAlign works fine, but it's still incompatible with AS2.2

Today was release the alpha4 version and the problem with the ZipAlign has desapeared, but when I debug my app I receive a warn about another problem :  It’s still not compatible with Android Studio 2.2 preview 3.

That’s another good post about this problem.

DialogFragment/AlertDialog dismiss automatically on click button

I was dealing with the case of use an EditText inside my AlertDialog that is created inside an DialogFragment last week and I remembered that I could write a tip about some problems of it. What problems?  It’s simple…An EditText…inside an AlertDialog…Ok, but how to avoid the dismiss of the Dialog when the user click in a positive of negative button? Imagine that the user clicks on the positive button and, when your  button’s listener checks the EditText value, it figures out that the value is invalid. Your code will warn the user that the value is invalid, but, your dialog suddently is dismissed even without you command it after the warn. Why?

Yes, positive and negative buttons will always dismiss the dialog, even without your order. How to avoid it? I’ve found a great answer on stackoverflow that will help us.

________________

What happens with AlertDialog’s setButton() method (and I imagine the same with AlertDialogBuilder’s setPositiveButton() and setNegativeButton()) is that the button you set (e.g. AlertDialog.BUTTON_POSITIVE) with it will actually trigger TWO different OnClickListener objects when pressed. The first being DialogInterface.OnClickListener, which is a parameter to setButton(), setPositiveButton(), and setNegativeButton(). The other is View.OnClickListener, which will be set to automatically dismiss your AlertDialog when any of its button is pressed – and is set by AlertDialog itself.

What you can do is to use setButton() with null as the DialogInterface.OnClickListener, to create the button, and then call your custom action method inside View.OnClickListener. For example,

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
  AlertDialog alertDialog = new AlertDialog(getActivity());
  // set more items...
  alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", null);

  return alertDialog;
}

Then, you may override the default AlertDialog’s buttons’ View.OnClickListener (which would otherwise dismiss the dialog) in the DialogFragment’s onResume() method:

@Override
public void onResume() {
  super.onResume();
  AlertDialog alertDialog = (AlertDialog) getDialog();
  Button okButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
  okButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      // Do your stuff here
    }
  });
}

You will need to set this in the onResume() method because getButton() will return null until after the dialog has been shown! This should cause your custom action method to only be called once, and the dialog won’t be dismissed by default.

Message.obtain() and new Message() – TIP

Is not possible send the same Message instance several time, only once. So we always have to create a new instance. Better than that, instead of create a new instance (new Message()), we can use the method obtain (Message.obtain()) that will return a recycled instance of Message from the pool of recycled objects, what is less expensive than the first option.

While the constructor of Message is public, the best way to get one of these is to call Message.obtain() or one of the Handler.obtainMessage() methods, which will pull them from a pool of recycled objects.

Movie Check is coming =D

I’m almost finishing a simple app to submit as capstone projeto for Udacity Nanodegree. I had 1 month to write something acceptable and submit. I worked every weekday night and could face some small challenges. That was a good experience and I’d like to move forward with this project after the nanodegree.

________

Movie Check is an Android application developed to be the capstone project for Udacity Android Nanodegree. Movie Check allows you to be informed about upcoming movies, movies that is being played now at cinemas, top rated movies, popular movies and be recommended to watch some movies that you possibly will like. If you liked a recommendation of a movie after get informations about it like description, celebrities that worked in cast or crew, videos of trailers and reviews, you can add it in a list of interests to watch on your free time. Or else, if you has already watched a movie, you can classify it and help the app to learn what you really like.

______

Who has never wanted to find a great movie to see in a weekend or holiday? Who has never started to watch a movie thinking it would be good but it was terrible? Movie Check can help you to stop to lose your time watching movies that you won’t like or trying to find a good one.

Movie Check allows you to be informed about upcoming movies, movies that is being played now at cinemas, top rated movies, popular movies and be recommended to watch some movies that you possibly will like. If you liked a recommendation of a movie after get informations about it like description, celebrities that worked in cast or crew, videos of trailers and reviews, you can add it in a list of interests to watch on your free time. Or else, if you has already watched a movie, you can classify it and help the app to learn what you really like.

_____

 

Service restart behavior – Compilation

START_STICKY

  • Service is restarted if it gets terminated. It will tell the system to create a newest copy of the service, when available memory is sufficient to do, after it retains state and recovers from the low memory.
  • In this process we will loose the results that might have calculated before. onStartCommand() will be called on the next instance of the service with a null Intent instead of not being called at all. So, It’s used for services which manages their own state and do not depend on the Intent data.

 

START_NOT_STICKY

  • Service is not restarted. It will tell the system not to worry and bother about to restart the service, even when it is having sufficient available memory.
  • The service is only restarted if the runtime has pending startService() calls since the service termination.
  • This makes a lot more sense for services that are intended to only run while executing commands sent to them. For example, a service may be started every 15 minutes from an alarm to poll some network state. If it gets killed while doing that work, it would be best to just let it be stopped and get started the next time the alarm fires.

START_REDELIVER_INTENT

  • Similar to START_NOT_STICKY, except if the service’s process is killed before it calls stopSelf() for a given intent, that intent will be re-delivered to it until it completes (unless after some number of more tries it still can’t complete, at which point the system gives up).
  • This is useful for services that are receiving commands of work to do, and want to make sure they do eventually complete the work for each command sent.

 

Resources

Vogella, Android Reference and StackOverflow

Hibernate JPA 2.1 – StoredProcedureQuery

Thanks to… someone… that we have JPA 2.1 and the feature StoredProcedureQuery. Throught this method we can call easily a procedure in our database, set parameters and convert the possible result into Java object automatically.

Let’s imagine a simple procedure called ‘SALES_ACCOUNTING’ that receives two dates (‘INITIALDATE’ and ‘FINALDATE’) that determine the time period and returns something like that:

employee conversion_rate sales_amount item_sales_amount attendance_amount
Tássio Auad 90 90 94 100

Firstly, we can create a class that represents this result, in the same way any hibernate entity represents a database table.

@Entity
public class SalesAccounting implements Serializable {

    @Id
    @Column(name = "employee")
    private String employeeName;

    @Column(name = "conversion_rate")
    private Float conversionRate;

    @Column(name = "sales_amount")
    private Integer salesAmount;

    @Column(name = "item_sales_amount")
    private Integer itemSalesAmount;

    @Column(name = "attendance_amount")
    private Integer attendanceAmount;

    ...

Ok, now we can call our procedure and transform each result automatically to a SalesAccounting instance. The main class, the class that will represent our procudure, is called StoredProcedureQuery and we can instanciate it throught EntityManager.createStoredProcedureQuery(). In the first parameters we will pass the procuure’s name and in the seconde paramter, the class that will be instanciated to receive the values of results.

public class SalesAccountingModel {

    private EntityManager entityManager;


    public SalesAccountingModel(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public List<SalesAccounting> listAll(Date initialDate, Date finalDate) { 
        StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("SALES_ACCOUNTING", SalesAccounting.class); } 
     }

Ok, but what about our procudure paramter ‘INITIALDATE’ and ‘FINALDATE’? How can I inform that there is these two parameters? Easy. Just use the method registerStoredProcedureParameter(parametername, classtype, inORout?) like this:

public class SalesAccountingModel {

    private EntityManager entityManager;


    public SalesAccountingModel(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public List<SalesAccounting> listAll(Date initialDate, Date finalDate) { 
         StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("SALES_ACCOUNTING", SalesAccounting.class) 
                         .registerStoredProcedureParameter("INITIALDATE", Date.class, ParameterMode.IN)
                         .registerStoredProcedureParameter("FINALDATE", Date.class, ParameterMode.IN); 
 } 
}

And, to finish our step-by-step, let’s execute our StoredProcedureQuery instance:

public class SalesAccountingModel {

    private EntityManager entityManager;


    public SalesAccountingModel(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public List<SalesAccounting> listAll(Date initialDate, Date finalDate) { 
         StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("SALES_ACCOUNTING", SalesAccounting.class) 
                         .registerStoredProcedureParameter("INITIALDATE", Date.class, ParameterMode.IN)
                         .registerStoredProcedureParameter("FINALDATE", Date.class, ParameterMode.IN); 
         return (List<SalesAccounting>) storedProcedureQuery.setParameter("INITIALDATE", dataInicio).setParameter("FINALDATE", dataFim).getResultList(); 
 } 
}

Retrofit 2.0 – URL concept

I struggled  with the new URL way when I started to use this new version. But it’s easy to understand (after miss much because of the old version vices)! Just keep in mind that the base URL and specific URL of a resource are concatenated. So, you must to take care with ‘/’ at the begining and end of URLs. Let’s define a simple rule to avoid mistakes:

The base API URL set in retrofit instance MUST ALWAYS end with ‘/’

new Retrofit.Builder().baseUrl("http://api.themoviedb.org/3/")

The specific URL of a resource must never be initiated with ‘/’

public interface APIService {
 
    @GET("item/")
    Call listItens();
 
}