Friday, December 20, 2013

Generics vs. AndroidAnnotations Android

Hi there!

In the last post i've shown the advantages of AndroidAnnotations against the tratidional instantiation way from Androd using castings while using the method findById(). AndroidAnnotatations are fine, but if for some reason (additional depencency, License or somethign else) you can't use it, there is an alternative to it. Generics solves this problem in my opinion also very elegant.

Pre-Conditions

Do the steps of post AndroidAnnotations and come back to this post when you are done.

BaseActivity with generics

Create the following class in your sample project (Attention: for some reason i don't know, while inserting code snippets here, generic types are not displayed correctly. For this reason i copied the generics like a String "T extends View". Please remove the Strings from it after copying):

import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;

@SuppressWarnings("unchecked")
public class BaseActivity extends Activity {

    /**
     * Convenience method. Does exactly the same as {@link BaseActivity#initById(Class, int)}
     * @param safetyCheck the class type to be returned
     * @param id the defined R.id... in the layout xml file
     * @return a reference of the specified class type.
     */
    public <"T extends View"> T getReferenceById(Class safetyCheck, final int id) {
        return initById(safetyCheck, id);
    }

    /**
     * Initializes views over id's.
     * @param safetyCheck the class type to be returned
     * @param id the defined R.id... in the layout xml file
     * @return a reference of the specified class type.
     */
    public <"T extends View"> T initById(Class safetyCheck, final int id) {
        return (T) findViewById(id);
    }

    /**
     * Initializes views over id's with onClickListeners.
     * @param id the defined R.id... in the layout xml file
     * @param callback a concrete implementation of {@link OnClickCallback}
     * @return a reference of the specified class type in {@link OnClickCallback}.
     */
    public <"T extends View"> T initWithListener(final int id, final OnClickCallback callback) {
        T type = (T) findViewById(id);
        type.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                callback.onClickPerformed((T) view);
            }
        });
        return type;
    }

    /**
     * Initializes views over id's with onTouchListeners.
     * @param id the defined R.id... in the layout xml file
     * @param callback a concrete implementation of {@link OnTouchCallback}
     * @return a reference of the specified class type in {@link OnTouchCallback}.
     */
    public <"T extends View"> T initWithListener(final int id, final OnTouchCallback callback) {
        T type = (T) findViewById(id);
        type.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                return callback.onTouchPerfomed((T) view, event);
            }

        });
        return type;
    }

    /**
     * Initializes views over id's with onLongClickListeners.
     * @param id the defined R.id... in the layout xml file
     * @param callback a concrete implementation of {@link OnLongClickCallback}
     * @return a reference of the specified class type in {@link OnLongClickCallback}.
     */
    public <"T extends View"> T initWithListener(final int id, final OnLongClickCallback callback) {
        T type = (T) findViewById(id);
        type.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                return callback.onLongClickPerformed((T) view);
            }
        });
        return type;
    }

    /**
     * Implement this interface and add an instance of it to the method
     * {@link BaseActivity#initWithListener(int, Callback)} while initializing your components
     * (Views)
     * @author Ricardo Ferreira
     * @since 20/12/2013
     * @version 1.0
     */
    public interface OnClickCallback<"T extends View"> {
        void onClickPerformed(T view);
    }
    /**
     * Implement this interface and add an instance of it to the method
     * {@link BaseActivity#initWithListener(int, Callback)} while initializing your components
     * (Views)
     * @author Ricardo Ferreira
     * @since 20/12/2013
     * @version 1.0
     */
    public interface OnLongClickCallback<"T extends View"> {
        boolean onLongClickPerformed(T view);
    }
    /**
     * Implement this interface and add an instance of it to the method
     * {@link BaseActivity#initWithListener(int, Callback)} while initializing your components
     * (Views)
     * @author Ricardo Ferreira
     * @since 20/12/2013
     * @version 1.0
     */
    public interface OnTouchCallback<"T extends View"> {
        boolean onTouchPerfomed(T view, MotionEvent event);
    }

}


Modify your MainActivity

Copy paste the next code segment into your MainActiviy. (Attention: for some reason i don't know, while inserting code snippets here, generic types are not displayed correctly. For this reason i copied the generics like a String "T extends View". Please remove the Strings from it after copying):

import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends BaseActivity {

    private OnClickCallback<"Button"> btnClickCallback = new ButtonClickCallback();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initById(TextView.class, R.id.textView1);
        initWithListener(R.id.button1, btnClickCallback);
        initWithListener(R.id.button2, btnClickCallback);
        initWithListener(R.id.button3, btnClickCallback);
        initWithListener(R.id.button4, btnClickCallback);
        initWithListener(R.id.button5, btnClickCallback);
        initWithListener(R.id.button6, btnClickCallback);
        initWithListener(R.id.button7, btnClickCallback);
        initWithListener(R.id.button8, btnClickCallback);
        initWithListener(R.id.button9, btnClickCallback);
        initWithListener(R.id.button10, btnClickCallback);
        initWithListener(R.id.button11, btnClickCallback);
        initWithListener(R.id.button12, btnClickCallback);
        initWithListener(R.id.button13, btnClickCallback);
        initWithListener(R.id.button14, btnClickCallback);
        initWithListener(R.id.button15, btnClickCallback);

    }

    private class ButtonClickCallback implements OnClickCallback<"Button"> {
        @Override
        public void onClickPerformed(Button type) {
            switch (type.getId()) {
            case R.id.button1:
                // returns a Button... do something useful with... if you need to...
                getReferenceById(Button.class, R.id.button1); 
                handleClick();
                break;
            case R.id.textView1:
                // returns a TextView... do something useful with... if you need to...
                getReferenceById(TextView.class, R.id.textView1); 
                handleClick();
                break;
            default:
                handleClick();
                break;
            }
        }
    }

    private void handleClick() {
        Toast.makeText(this, "Generics are even cooler!", Toast.LENGTH_SHORT).show();
    }

}


That's all. Hope you like it.

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†

Wednesday, December 18, 2013

Write less code with AndroidAnnotations and increase maintainability and readability

Hi there!

Today i'm gonna show how to write less code but simultaneously improve maintainability and readability of your android code. I was so impressed that I wanted to try myself, how good and how easy it really is. In this tuturial i will only show the benefits of AndroidAnnotations and not how to install it. But don't worry. If you decide to use it (and i'm sure you'll will :) there is no magic on how to install it. In this site you'll get all the information you need: AndroidAnnotations

The sample project

We will endup with something like this bellow to show to you the power and simplicity of AndroidAnnotatios. 




MainActivity

Create a simple project and dont change the default names while creating the project. In the folder res>layout>activity_main.xml copy/paste the following code snippet inside of it.




    

    


Initializing the components 

If you initialize the components in the tradional android way, you would end up with a class like this:

package com.treslines.androidannotations;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

    private TextView title;
    private Button button1;
    private Button button2;
    private Button button3;
    private Button button4;
    private Button button5;
    private Button button6;
    private Button button7;
    private Button button8;
    private Button button9;
    private Button button10;
    private Button button11;
    private Button button12;
    private Button button13;
    private Button button14;
    private Button button15;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        title = (TextView) findViewById(R.id.textView1);
        button1 = (Button) findViewById(R.id.button1);
        button2 = (Button) findViewById(R.id.button2);
        button3 = (Button) findViewById(R.id.button3);
        button4 = (Button) findViewById(R.id.button4);
        button5 = (Button) findViewById(R.id.button5);
        button6 = (Button) findViewById(R.id.button6);
        button7 = (Button) findViewById(R.id.button7);
        button8 = (Button) findViewById(R.id.button8);
        button9 = (Button) findViewById(R.id.button9);
        button10 = (Button) findViewById(R.id.button10);
        button11 = (Button) findViewById(R.id.button11);
        button12 = (Button) findViewById(R.id.button12);
        button13 = (Button) findViewById(R.id.button13);
        button14 = (Button) findViewById(R.id.button14);
        button15 = (Button) findViewById(R.id.button15);
        
        button1.setOnClickListener(this);
        button2.setOnClickListener(this);
        button3.setOnClickListener(this);
        button4.setOnClickListener(this);
        button5.setOnClickListener(this);
        button6.setOnClickListener(this);
        button7.setOnClickListener(this);
        button8.setOnClickListener(this);
        button9.setOnClickListener(this);
        button10.setOnClickListener(this);
        button11.setOnClickListener(this);
        button12.setOnClickListener(this);
        button13.setOnClickListener(this);
        button14.setOnClickListener(this);
        button15.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        final int id = view.getId();
        switch (id) {

        case R.id.button1:
            handleClick();
            break;
        case R.id.button2:
            handleClick();
            break;
        case R.id.button3:
            handleClick();
            break;
        case R.id.button4:
            handleClick();
            break;
        case R.id.button5:
            handleClick();
            break;
        case R.id.button6:
            handleClick();
            break;
        case R.id.button7:
            handleClick();
            break;
        case R.id.button8:
            handleClick();
            break;
        case R.id.button9:
            handleClick();
            break;
        case R.id.button10:
            handleClick();
            break;
        case R.id.button11:
            handleClick();
            break;
        case R.id.button12:
            handleClick();
            break;
        case R.id.button13:
            handleClick();
            break;
        case R.id.button14:
            handleClick();
            break;
        case R.id.button15:
            handleClick();
            break;

        default:
            break;
        }

    }
    
    private void handleClick(){
        Toast.makeText(this, "AndroidAnnotations are cool!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}



The benefits of AndroidAnnotations

If you do the same thing with AndroidAnnotations we endup with something soooooo coooool like this ;)


package com.treslines.withandroidannotations;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.googlecode.androidannotations.annotations.Click;
import com.googlecode.androidannotations.annotations.EActivity;
import com.googlecode.androidannotations.annotations.ViewById;

@EActivity(R.layout.activity_main)
public class MainActivity extends Activity {

    @ViewById(R.id.textView1) protected TextView title;
    @ViewById(R.id.button1) protected Button button1;
    @ViewById(R.id.button2) protected Button button2;
    @ViewById(R.id.button3) protected Button button3;
    @ViewById(R.id.button4) protected Button button4;
    @ViewById(R.id.button5) protected Button button5;
    @ViewById(R.id.button6) protected Button button6;
    @ViewById(R.id.button7) protected Button button7;
    @ViewById(R.id.button8) protected Button button8;
    @ViewById(R.id.button9) protected Button button9;
    @ViewById(R.id.button10) protected Button button10;
    @ViewById(R.id.button11) protected Button button11;
    @ViewById(R.id.button12) protected Button button12;
    @ViewById(R.id.button13) protected Button button13;
    @ViewById(R.id.button14) protected Button button14;
    @ViewById(R.id.button15) protected Button button15;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // NO NEED TO INITIALIZE COMPONENTS ANYMORE
        // ONLY 62 LINES AGAINST 139 LINES (2 TIMES LESS CODE)
        // LESS COPY/PASTE ERROR
    }

    // No switch-cases anymore...
    // Handle clicks together or independently ...
    // No need to implement onClickListener anymore... 
    @Click({R.id.button1,R.id.button2,R.id.button3}) void onButton1Clicked() {handleClick();};
    @Click({R.id.button4,R.id.button5,R.id.button6}) void onButton4Clicked() {handleClick();};
    @Click({R.id.button7,R.id.button8,R.id.button9}) void onButton7Clicked() {handleClick();};
    @Click({R.id.button10,R.id.button11,R.id.button12}) void onButton10Clicked() {handleClick();};
    @Click(R.id.button13) void onButton13Clicked() {handleClick();};
    @Click(R.id.button14) void onButton14Clicked() {handleClick();};
    @Click(R.id.button15) void onButton15Clicked() {handleClick();};

    private void handleClick(){
        Toast.makeText(this, "AndroidAnnotations are cool!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}


That's all. Hope you like it.

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†

How to create an awesome partial transparent dialog(like) Activity Android

Hi there!

Today i'll show, how to make the diffence in your profissional apps by designing real cool, awesome activities. In this sample i'm gonna share how we can create an activity that looks like a dialog with some partial transparent parts, which allows me to see the background of the launcher main activity.

Here is the sketch to visualize the idea behind the text:


Create a sample project

Create an Android Project and define your main activity as ExampleActivity. After that, create a second activity called PhotoPickerActivity. Don´t worry about the details. We will see it a few steps ahead. Just create it and leave it empty. Define in the layout of  ExampleActivity only a single button, add an OnClickListener to it and as soon as the button is pressed, call an action like that:

Intent intent = new Intent(getContext(), PhotoPickerActivity.class);
getActivity().startActivityForResult(intent, PhotoPickerActivity.REQUEST_CODE_OPEN_GALLERY);


Activity dialog style.

Create a style.xml in the folder: res>values like that:



    
    




Layout of PhotoPickerActivity

Create a layout called for example: activity_photo_picker.xml in folder: res>layout like that:



    

    

        

            

            
        

        

            
        
    

    




Manifest Entry

In your manifest, make sure you've added the following code snippet to it(Make sure the package name matches your own definition. In my case it is called com.treslines.ExampleActivity):




Content of PhotoPickerActivity

Copy/paste the next code section into PhotoPickerActivity.

public class PhotoPickerActivity extends Activity implements OnClickListener {

    public static final String ACTION_NAVIGATE_BACK = "ACTION_NAVIGATE_BACK";
    public static final String ACTION_PHOTO_SHOT = "ACTION_PHOTO_SHOT";
    public static final String ACTION_PHOTO_TAKEN = "ACTION_PHOTO_TAKEN";
    public static final int REQUEST_CODE_OPEN_GALLERY = 20;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photo_picker);
        findViewById(R.id.close_view).setOnClickListener(this);
        findViewById(R.id.camera_view).setOnClickListener(this);
        inflatePhotoViewsToShow();
    }

    private void inflatePhotoViewsToShow() {
        // 1. Load photos from a service
        // 2. inflate photos in views here...
        // 3. add listener this click listener to each one
        // 4. add real data to the switch cases
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {

        case R.id.close_view:
            Intent navigateBack = new Intent(this, ExampleActivity.class);
            navigateBack.setAction(ACTION_NAVIGATE_BACK);
            navigateBack.setData(Uri.EMPTY); 
            setResult(Activity.RESULT_OK, navigateBack);
            finish();
            break;

        case R.id.camera_view:
            Intent photoShot = new Intent();
            photoShot.setAction(ACTION_PHOTO_SHOT);
            photoShot.setData(Uri.EMPTY); // set real data here...
            setResult(Activity.RESULT_OK, photoShot);
            finish();
            break;
            
        // photo has been taken (selected)
        default:
            Intent photoTaken = new Intent();
            photoTaken.setAction(ACTION_PHOTO_TAKEN);
            photoTaken.setData(Uri.EMPTY); // set real data here...
            setResult(Activity.RESULT_OK, photoTaken);
            finish();
            break;
        }
    }

}


OnActivityResult from ExampleActivity

In the method onActivityResult from your main class ExampleActivity, make sure you've added the content bellow:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode == Activity.RESULT_OK) {
            
            if (requestCode == PhotoPickerActivity.REQUEST_CODE_OPEN_GALLERY) {
                if(!PhotoPickerActivity.ACTION_NAVIGATE_BACK.equals(data.getAction())){
                    if(PhotoPickerActivity.ACTION_PHOTO_SHOT.equals(data.getAction())){
                        Toast.makeText(this, "photo shot over camera", Toast.LENGTH_SHORT).show();
                    }else if(PhotoPickerActivity.ACTION_PHOTO_TAKEN.equals(data.getAction())){
                        Toast.makeText(this, "photo selected over photo picker", Toast.LENGTH_SHORT).show();
                    }
                }
            }

 }
}

That's all i hope you like it.

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†

Saturday, December 7, 2013

How to identify design pattern before coding?

Hi there!

In this post we will learn how to identify design pattern before coding! Isn't it exciting? As you probabilly know, i'm addicted to design patterns. I've read a lot of good books and probabilly as you, my biggest problem was always the identification of cases/scenarios in which i could use them.

There are great books out there, but none of them explains in a simple way, how to identify it. Most of them says: "It depends on the usecase or it depends on the dev's expirience" In fact the expirience (years that you have been working on the software business) may help you identifying the right patterns to be used in some default scenarios, but can't we learn it a little bit faster? Do we have to wait years to get it done right?

Motivated by those questions, i've been trying to identify the patterns by the last mobile project i made. I was very surprised how simple it can be and how much better understandable, extensible and readable my end project was. All you need to do is to sketch it first. Really!!! That's all. Don't worry, we will see the whole process step by step. :-)

The Patterns

In this tutorial we will learn how i was able to identify a bunch of patterns before starting coding (Please note: In this tutorial i will not explain why a specific pattern is good or not. I will assume you know already design pattern and are interested in see how/when to apply it) In my project i was able to identify the following patterns:

  • Command Pattern
  • State Pattern
  • Adapter Pattern
  • Null Object Pattern
  • Singleton Pattern
  • Observer Pattern (Listeners)
  • Template Method Pattern

The Challange

Ok, let's get to an apparently simple, but real project. Imagine you have the following challange:

You have 4 buttons on a toolbar on the bottom of your application. Every button starts its own animation  when it is tapped (let's say it is moved upward to show its activity) and after its animation is done, a second animation starts. (let's say a column is slided out showing icons on it). Can you imagine it? something like this:

Sketch

The requirements

Ok, let's move on. Here are futher requirements:
  • Every animation has to be synchronized which means, if an animation is running, none of the other animations can be started, till it ends. 
  • After every transition (animation) we should have the possibility of excuting some actions if we need. (let's say play a sound or execute a desired action)
  • Every button must be locked to each other. This means, if i press and hold one button, i can't fire another action by pressing anoter button.
  • If we touch the screen and an animation is showing already, this animation will slide back and a defined dafault button will be selected. (will be moved a little bit upward)

How can i identify the patterns now?

Know that we have sketched the scenarios and have listed the requirements, how can we identify proper pattern to use in this case?

Well, what i have done was to simple imagine the five buttons as a TV-Remote control and the animations as transition states on my screen. Doing that way it was almost impossible to not see the patterns. So i thought i had commands to start the animations (Command Pattern) and i thought i had states to represent any animation's transition. (State Pattern) - The key to this was the sketch i made. Imagine: Without it, it would be almost impossible to see it.

We should give the possibility to fire actions between states. And because this should be only possibilities, i can imagine scenarios in which there will be no actions also possible right? And here they are: NullState, NullAction and NullCommand. (Null Object Pattern)

Ok let's think further. As a requirement we must ensure singularity to any button. So i automatically see the picture of a lock, because there should be only one way to start actions. In that case we need a global accessible but unique flag to control that. (Synchronized Singleton Pattern)

And last but not least, as we will be dealing with a lot of action listeners and because of the button's synchronization, it would be necessary to implement a lot of individual Listeners for every button. If we do that way, we would end up with a bunch of duplicated code lines. For this reason we should implement an adapter of the TouchListener in which we place the lock logic in central unique place (Template Method Pattern), making it available for all buttons in the aplication. (Adapter Pattern). So i ended up with a simple but very usefull class diagram like that bellow which i used to define the app's architecture (structural part of it):

initial class diagram

Conclusion

In my opinion at least two things are indispensable in the process of figuring out what design pattern to apply:
  • a sketch 
  • as many requirements as available

Share your expirience

If you know other simple, practical ways on how to find out which design pattern to use, please feel free to contact me and share your thoughts.  It would be great to se the usage of other pattern in practise. (real projects) like i did. That's all. hope you like it.

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†


Wednesday, November 6, 2013

How to create a bit state register java android

Hi there! Today i'gonna share/show how we could create a bit state register, manupulate bit states doing OR and AND operations on it. Favor/consider always the state pattern whenever possible over this solution here. I use it when the state pattern is not our first choice or is inappropriate. (when it gets to complex or i'm doing simple state checks and the design is simple, fixed and not intented to be extended) It is a simple 32 states bit processor which can hold up to max 32 states. The result at the end will be something like in the class diagram bellow:



BitStates

/**
 * Bit states to represent 32 possible states. The first state is the mask state to reset states.
 * Those states can be used to define component transition states while animating it.
 * 
INSTRUCTIONS ON HOW TO USE IT:

 * In combination with a state pattern, you may associate any bit state to a transition, position, animation or whatever you need to monitor in a proper sequence. 
 * For example: If you want to know that a button X has been pressed, animation Y is done and Fragment Z is shown, associate a bit state to each of them
 * and do an "or-operation" on it. You'll be able now to extract all those information (3 states) from just one bit combination without having to explicitly ask for it using a lot of if/else cases.
 * 
  BIT STATE REPRESENTATION            HEX CODE REPRESENTATION
  00000000000000000000000000000000 0
 00000000000000000000000000000001 1
 00000000000000000000000000000010 2
 00000000000000000000000000000100 4
 00000000000000000000000000001000 8
 00000000000000000000000000010000 10
 00000000000000000000000000100000 20
 00000000000000000000000001000000 40
 00000000000000000000000010000000 80
 00000000000000000000000100000000 100
 00000000000000000000001000000000 200
 00000000000000000000010000000000 400
 00000000000000000000100000000000 800
 00000000000000000001000000000000 1000
 00000000000000000010000000000000 2000
 00000000000000000100000000000000 4000
 00000000000000001000000000000000 8000
 00000000000000010000000000000000 10000
 00000000000000100000000000000000 20000
 00000000000001000000000000000000 40000
 00000000000010000000000000000000 80000
 00000000000100000000000000000000 100000
 00000000001000000000000000000000 200000
 00000000010000000000000000000000 400000
 00000000100000000000000000000000 800000
 00000001000000000000000000000000 1000000
 00000010000000000000000000000000 2000000
 00000100000000000000000000000000 4000000
 00001000000000000000000000000000 8000000
 00010000000000000000000000000000 10000000
 00100000000000000000000000000000 20000000
 01000000000000000000000000000000 40000000
 10000000000000000000000000000000 80000000
 * 
* @author Ricardo Ferreira 01/11/2013 * */ public enum BitStates { STATE_00(0x0), STATE_01(0x1), STATE_02(0x2), STATE_03(0x4), STATE_04(0x8), STATE_05(0x10), STATE_06(0x20), STATE_07(0x40), STATE_08(0x80), STATE_09(0x100), STATE_10(0x200), STATE_11(0x400), STATE_12(0x800), STATE_13(0x1000), STATE_14(0x2000), STATE_15(0x4000), STATE_16(0x8000), STATE_17(0x10000), STATE_18(0x20000), STATE_19(0x40000), STATE_20(0x80000), STATE_21(0x100000), STATE_22(0x200000), STATE_23(0x400000), STATE_24(0x800000), STATE_25(0x1000000), STATE_26(0x2000000), STATE_27(0x4000000), STATE_28(0x8000000), STATE_29(0x10000000), STATE_30(0x20000000), STATE_31(0x40000000), STATE_32(0x80000000); private int state; private BitStates(int state) { this.state = state; } public int getState() { return state; } }

BitStateRegister

import java.util.HashMap;
import java.util.Map;

// Singleton Pattern
/**
 * Use this register to associate bit states to concrete states in a state pattern.
 * This register can hold up to 33 bit states,while the 0 state is per default the
 * zero state (reset mask state).
 * @author Ricardo Ferreira 02/11/2013
 *
 */
public class BitStateRegister {

 private static final BitStateRegister INSTANCE = new BitStateRegister();
 private static final Map stateRegister = new HashMap();
 private static final int registerMaxSize = 33;

 private BitStateRegister() {
  // Singleton Pattern
 }

 public static BitStateRegister getInstance() {
  registerZeroStateOnlyOnce();
  return INSTANCE;
 }
 
 private static void registerZeroStateOnlyOnce(){
  if (!stateRegister.containsKey("zero")) {
   stateRegister.put("zero", BitStates.STATE_00.getState());
  }
 }

 /**
  * State Register. It registers a new state only if not exists already. 

  * This Register is able to register from 1 up to 32 states in a 32 bit system.

  * You do not have to care about it. The states will be created and increased

  * automatically, when registered.

 
  * 
  * To obtain the zero state(reset mask state), call getState("zero"); on it.

  * To check if the register is already completely full, call isRegisterComplete(); on it.
  * 
  * @param stateClassSimpleName the simple class name provided by calling: ConcreteState.class.getSimpleName(); on your concrete state.
  * @return true if the new state was created, false if the state already exists or the register is full.
  */
 public boolean registerStateFor(String stateClassSimpleName) {
  boolean operationResult = false;
  if (!stateRegister.containsKey(stateClassSimpleName) && stateRegister.size() < registerMaxSize) {
   int nextStateIndex = stateRegister.size();
   int newState = BitStates.values()[nextStateIndex].getState();
   stateRegister.put(stateClassSimpleName, newState);
   operationResult = true;
  }
  return operationResult;
 }

 public boolean unregisterStateFor(String stateClassSimpleName){
  boolean operationResult = false;
  if (stateRegister.containsKey(stateClassSimpleName)) {
   Integer bitState = stateRegister.get(stateClassSimpleName);
   stateRegister.remove(bitState);
   operationResult = true;
  }
  return operationResult;
 }

 public int getStateFor(String stateClassSimpleName) {
  return stateRegister.get(stateClassSimpleName);
 }

 /**
  * Returns true if the Register is already completely filled up with 32 states , false otherwise.
  * 
  * @return true if the Register is already completely filled up with 32 states , false otherwise
  */
 public boolean isRegisterComplete() {
  return stateRegister.size() == registerMaxSize;
 }
 
 /**
  * Checks if the state of the given state class name is set in the current bit state.
  * @param currentBitState the current bit state
  * @param stateClassSimpleName the simple class name provided by calling: ConcreteState.class.getSimpleName(); on your concrete state.
  * @return true if the bit is set, false otherwise.
  */
 public boolean isBitStateSetted(int currentBitState, String stateClassSimpleName){
  boolean operationResult = false;
  if(stateRegister.containsKey(stateClassSimpleName)){
   int stateFor = getStateFor(stateClassSimpleName);
   if((stateFor&currentBitState)==stateFor){
    operationResult = true;
   }
  }
  return operationResult;
 }

}

BitStateProcessor

/**
 * A bit state processor with a process state capacity of max 32 states.
 * Favor/consider always the usage of a state pattern instead of it. 
 * But in case the state pattern is inappropriate, you can use it.
 * 
 * @author Ricardo Ferreira 06/11/2013
 * 
 */
public class BitStateProcessor {
 private int resetMask = BitStateRegister.getInstance().getStateFor("zero");
 private int currentBitState = 0x0;
 private int internalState = 0x0;
 private String stateClassSimpleName;

 /**
  * @param stateClassSimpleName
  *            the simple class name of your concrete state provided by calling ConcreteState.class.getSimpleName();
  */
 public BitStateProcessor(int currentBitState, String stateClassSimpleName) {
  this.currentBitState = currentBitState;
  this.stateClassSimpleName = stateClassSimpleName;
  BitStateRegister.getInstance().registerStateFor(stateClassSimpleName);
  this.internalState = BitStateRegister.getInstance().getStateFor(stateClassSimpleName);
 }

 public int getCurrentBitState() {
  return this.currentBitState;
 }

 public void setCurrentBitState(int currentBitState) {
  this.currentBitState = currentBitState;
 }

 public void resetCurrentBitState() {
  this.currentBitState = this.currentBitState & this.resetMask;
 }

 public boolean isBitStateSetted() {
  return BitStateRegister.getInstance().isBitStateSetted(this.currentBitState, this.stateClassSimpleName);
 }

 public boolean unregisterStateFor(String stateClassSimpleName) {
  return BitStateRegister.getInstance().unregisterStateFor(stateClassSimpleName);
 }

 public boolean isRegisterComplete() {
  return BitStateRegister.getInstance().isRegisterComplete();
 }

 public int getStateFor(String stateClassSimpleName) {
  return BitStateRegister.getInstance().getStateFor(stateClassSimpleName);
 }

 /**
  * Returns a new bit state.
  * 
  * @param currentBitState the actual bit state passed to this class or method
  * @return the new bit state after an "or-operarion" with its internal state.
  */
 public int processCurrentBitState(int currentBitState) {
  this.currentBitState = this.internalState | currentBitState;
  return this.currentBitState;
 }

}

That's all! hope you like it!

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†

Monday, November 4, 2013

How to lock state to synchonize transitions java android

Hi there!
Today i'm gonna share one of many possible ways to acquire a lock with the intent of synchronize transitions or whatever task you may have. I use it to synchronize complex animation transition sequences in Android.


import java.util.HashSet;
import java.util.Set;

/**
 * Use this class to synchronize transitions, animations or whatever you want.

 * It is designed to acquire and release a synchronized lock state, coordinating

 * the access of it in a multi thread environment.
 * 
 * @author Ricardo Ferreira 04/11/2013
 */
public class StateLock {

 private final static StateLock INSTANCE = new StateLock();
 private Set lockSet = new HashSet();
 private boolean lock = false;
 
 private StateLock() {
  // singleton
 }

 /** Synchronized because the lock state should be acquired and released in a controlled way */
 public synchronized static StateLock getInstance() {
  return StateLock.INSTANCE;
 }

 public synchronized boolean isStateLocked() {
  return lock;
 }
 
 public synchronized boolean hasStateAlreadyLocked(String stateSimpleClassName) {
  return lockSet.contains(stateSimpleClassName);
 }

 /** Returns true if the state lock was acquired by the given class, false otherwise */
 public synchronized boolean acquireLockState(String stateSimpleClassName) {
  boolean operationResult = false;
  if (lockSet.isEmpty()) {
   lockSet.add(stateSimpleClassName);
   lock = true;
   operationResult = true;
  }
  return operationResult;
 }

 /** Returns true if the lock was released or no state was locked, false otherwise */
 public synchronized boolean releaseLockState(String stateSimpleClassName) {
  boolean operationResult = false;
  if (lockSet.contains(stateSimpleClassName)) {
   lockSet.clear();
   lock = false;
   operationResult = true;
  } else if (lockSet.isEmpty()) {
   lock = false;
   operationResult = true;
  }
  return operationResult;
 }

 protected Object clone() throws CloneNotSupportedException {
  throw new CloneNotSupportedException();
 }

}

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†

Wednesday, October 30, 2013

How to handle orientation changes on Android

Hi there!
Today i'm gonna share a very common task, i used to have while developing android apps. Most of the scenarios we can handle by using the conventions of foldername-port or foldername-land for Portrait and Landscape mode while developing app which supports both orientations. That´s a good practise and should be done whenever possible. But in some special cases, we need to thread the orientation changes by listening to it. If this is also an issue by you, you'll may find helpful to see how we could do it. The code segment bellow shows a class which was designed to be implemented in line in your activity every time you may need the capability of handling orientation changes. Specially when the phones stands or is lying on the side. The instructions on how to use it, is described on the class's javadoc.

The abstract, reusable class definition


import android.view.Surface;

/**
 * Handles screen orientation changes. It was designed to be used/implemented in line,

 * directly in your activity. To be able to work properly, this class needs a manifest entry in the

 * activity tag called:

 * 
 * ... 
   
 * android:screenOrientation="fullSensor"

 * ... 
 * 

 * INSTRUCTIONS ON HOW TO USE IT:

 * 1) Implement the behavior you need in the methods:

 * {@link AbstractRotationHandler#onPhoneStands()} and

 * {@link AbstractRotationHandler#onPhoneLyingOnTheSide()}

 * 2) Then pass the current orientation constant to the method:

 * {@link AbstractRotationHandler#onOrientationChanged(int)} by calling:

 * getWindowManager().getDefaultDisplay().getRotation();

 * from your activity.
 * 
 * @author Ricardo Ferreira 30/10/2013
 * 
 */
public abstract class AbstractRotationHandler {

 /**
  * Pass the current orientation constant by calling:

  * getWindowManager().getDefaultDisplay().getRotation();

  * from your activity.
  * 
  * @param rotation
  *            the current rotation constant provided by your activity
  */
 public void onOrientationChanged(final int rotation) {
  switch (rotation) {
  case Surface.ROTATION_0:
  case Surface.ROTATION_180: {
   onPhoneStands();
   break;
  }
  case Surface.ROTATION_90:
  case Surface.ROTATION_270: {
   onPhoneLyingOnTheSide();
   break;
  }
  }
 }

 /**
  * Implement the behavior you need, when the phone stands.
  */
 protected abstract void onPhoneStands();

 /**
  * Implement the behavior you need, when the phone is lying on the side.
  */
 protected abstract void onPhoneLyingOnTheSide();

}

The implementation of it


 private AbstractRotationHandler concreteRotationHandler = new AbstractRotationHandler() {

        @Override
        protected void onPhoneStands() {
               // do what you need here...
        }

        @Override
        protected void onPhoneLyingOnTheSide() {
               // do what you need here...
         }
    };

The usage of it


int rotation = getWindowManager().getDefaultDisplay().getRotation();
this.concreteRotationHandler.onOrientationChanged(rotation);

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†

Thursday, October 17, 2013

Android AutoSave For Saving Processes After Custom Delay

Hi there! Today i'm gonna share a very common task while developing android apps. An autosave function which allow me to monitor user actions and save something after a custom delay everytime the user interacts with the UI.

Defining the common Interface

This interface will be implemented by the interested clients. For example your Activity.
/**
 * Clients who are interested in having auto save capabilities functions implements this interface.

 * 

 * Steps on how to use it:

 * - Implement this interface

 * - In your UI, in the desired onClick, onTouch or whatever method, create a new instance of {@link AutoSave}

 * - Pass this implemented instance to the constructor of {@link AutoSave}

 * - With the method setSecondsToWait() of {@link AutoSave}, set the seconds you may want to delay the save process.

 * - Obs: If you do not use the call setSecondsToWait() on {@link AutoSave}, the default behavior will be 10 seconds delay.

 * - Important: Call the start() method on {@link AutoSave} to start monitoring user actions.

 * 
 * @author Ricardo Ferreira 17/10/2013
 */
public interface SaveAction {

 public void autosave();

}

Defining the AutoSave Thread

This is the class which monitors the user's interaction.
/**
 * Use this class to start a auto save process as a Thread with some delay before saving.

 * 

 * Steps on how to use it:

 * - Instantiate this instance in your desired onClick, onTouch or whatever method

 * - Call the method setSecondsToWait() and set the seconds you want to delay

 * - (If you do not call setSecondsToWait() on {@link AutoSave}, the default behavior will be 10 seconds delay.)

 * - Important: Call the start() method on {@link AutoSave} to start monitoring user actions.

 * 
 * @author Ricardo Ferreira  17/10/2013
 * 
 */
public class AutoSave extends Thread {

 private Activity context;
 private long startTime = 0;
 private long currentTime = 0;
 private final long teenSeconds = 10000;
 private final long oneSecond = 1000;
 private boolean recording = false;
 private SaveAction saveAction;
 private long secondsToWait = 0;

 public AutoSave(Activity context, SaveAction saveAction) {
  this.context = context;
  this.saveAction = saveAction;
 }

 @Override
 public void run() {

  while (!this.context.isDestroyed()) {
   try {
    if (isRecording()) {
     setCurrentTime(System.currentTimeMillis());
     if (getCurrentTime() - getStartTime() > (secondsToWait == 0 ? teenSeconds : secondsToWait)) {
      setRecording(false);
      setStartTime(0);
      setCurrentTime(0);
      autoSave();
     }
     sleep(oneSecond);
    } else {
     sleep(oneSecond);
    }
   } catch (InterruptedException e) {
    Log.i("TEST", e.getMessage());
    e.printStackTrace();
   }
  }

 }

 public void setSecondsToWait(long secondsToWait) {
  this.secondsToWait = secondsToWait;
 }

 public void saveAfterSecondsToWait() {
  if (!isRecording()) {
   setRecording(true);
   setStartTime(System.currentTimeMillis());
  }
 }

 private void autoSave() {
  this.saveAction.autosave();
 }

 private long getStartTime() {
  return startTime;
 }

 private void setStartTime(long startTime) {
  this.startTime = startTime;
 }

 private void setCurrentTime(long currentTime) {
  this.currentTime = currentTime;
 }

 private long getCurrentTime() {
  return currentTime;
 }

 private boolean isRecording() {
  return recording;
 }

 private void setRecording(boolean recording) {
  this.recording = recording;
 }

}

Initializing the AutoSave instance

Lets assume now, that you have an Activity which implements the interface SaveAction. Lets call it: "PaintActivity" and you are interested in monitoring user actions. Every time the user draws something on the screen, you'll wait teen seconds and save the drawing. To do it so, call this two lines bellow in your onTouchListener's constructor. Then when the action happens, call saveAfterSecondsToWait() from AutoSave. Done! If you want to customize the delay time, call setSecondsToWait() from AutoSave before calling start(). Done! ;) You can now implement your auto save behavior in your Activity.

this.autosave = new AutoSave(this.context, (PainterActivity) this.context);
//this.autosave.setSecondsToWait(3000);// three seconds delay
this.autosave.start();
// call saveAfterSecondsToWait() from autosave when the action actually happens. for example: onTouch() or onClick() whatever...
this.autosave.saveAfterSecondsToWait(),


That's all! Hope you like it! :)

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†

Thursday, October 10, 2013

Android Almanac - Code Snippet Repo

Hi there! This section i will totatlly dedicate to android dev´s out there! It is as little Android Almanac containing common code snippets for the different purposes and tasks. I will be growing permanently. So if you miss something, just leave a constructive comment and i will try my best to accomplish that ok. Hope you like it.

How to detect device's 3G, wifi or internet connection

private boolean isConnectedToInternet(Context ctx) {

        NetworkInfo info = (NetworkInfo) ((ConnectivityManager) ctx
                .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();

        if (info == null || !info.isConnected()) {
            return false;
        }
        if (info.isRoaming()) {
            // here is the roaming option you can change it if you want to
            // disable internet while roaming, just return false
            return false;
        }
        return true;
    }

Easy way to give feedback to users while pressing ImageView

final ImageView eraseBtn = (ImageView)findViewById(R.id.eraseBtn);
         eraseBtn.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    eraseBtn.setColorFilter(getResources().getColor(R.color.translucent_black));
                    eraseBtn.invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    eraseBtn.setColorFilter(null);
                    eraseBtn.invalidate();
                    break;
                default:
                    break;
                }
                return false;
            }
        });
Define the translucent black color like this in your strings.xml file:
< ? xml version="1.0" encoding="utf-8" ? >
< resources >
     ....
    < color name="translucent_black" >#51000000< / color>
     ....
< / resources>

How to compute degrees from MouseEvent (x,y coordinates)

In some cases, we need to compute the degrees from a give coordinate. Like from an event. Here is a simple way how to do it:

    private float getDegrees(MotionEvent event) {
        double radians = Math.atan2(event.getY(1) - event.getY(0), event.getX(1) - event.getX(0));
        return (float) Math.toDegrees(radians);
    }

Listening to orientation changes onSensorChanged()

In some cases, we need to implement SensorEventListener and implement onSensorChanded. While listening to it, i lost many yours looking for a simple approach which allows me to simple decide if my fone is lying on the side or if it stands. A very nice and simple way is to listen to its angles like that:

... code omitted ...

public void onSensorChanged(SensorEvent event) {
        float pitch = event.values[1];
        float roll = event.values[2];
        if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            if (pitch < -45 && pitch > -135) {
                onLandscapePhoneStands();
            } else if (pitch > 45 && pitch < 135) {
                onLandscapePhoneOnHead();
            } else if (roll > 45) {
                onLandscapePhoneLyingOnTheLeftSide();
            } else if (roll < -45) {
                onLandscapePhoneLyingOnTheRightSide();
            }
        } else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
            if (pitch < -45 && pitch > -135) {
                onPhoneStands();
            } else if (pitch > 45 && pitch < 135) {
                onPhoneOnHead();
            } else if (roll > 45) {
                onPhoneLyingOnTheLeftSide();
            } else if (roll < -45) {
                onPhoneLyingOnTheRightSide();
            }
        }
    }

... code omitted ...

How to remove padding from AlertDialog on Android

I had a task to solve, which was very tricky. I needed to display an alert dialog, which presents an image (using the whole space of the dialog) without any buttons. Just a fullscreen picture on it. The problem was, that on the top side of the dialog, was always a border line remaining. No matter what i did or set in the layout.xml. I lost many hours searching for a proper solution. At the end the solution was as simple as i thought, but very tricky. All you need to do, is to call the following piece of code after calling the show() method on your dialogBuilder or on your dialog itself.

... code ommited...

dialogBuilder.show(); 

ViewGroup parent = (ViewGroup)view.getParent();

parent.setPadding(0, 0, 0, 0);

... code ommited ...

Getting the current display size

That´s a very common task for diffent purposes. Here a snippet for it:

DisplayMetrics metrics = getResources().getDisplayMetrics();
  int displayWidth = metrics.widthPixels;
  int displayHeight = metrics.heightPixels;

Rounded Corners by Layouts

Sometimes you'll need to be a little more sofisticated with your layout. One task i had, was to round the corners from my fragment layout, setting stroke type, color and radius. This may also be helpfull to you. In the folder drawable define a shape.xml called: rounded_layout_corners.xml with the content bellow and set it to the android:background attribute of your layout in the xml file.:


    
    
    
    


Rounded Corners by Layouts without bottom line

More examples with rounded corners but this way hidding the bottom line. For this kind of layout you'll need to create the drawable folder for portrait and drawable-land for landscape mode.

Here's the portrait layout i called rounded_layout_corner.xml
 
    
    
     
     
    
    
     
 
And here's the landscape layout i called also rounded_layout_corner.xml but put it in the drawable-land folder.
 
     
    
     
     
    
    
     
 

Supporting Multiple Screen Sizes

That´s a very common task. Here the most important infos you need to know.

drawable-ldpi (120 dpi, Low density screen) - 36px x 36px
drawable-mdpi (160 dpi, Medium density screen) - 48px x 48px
drawable-hdpi (240 dpi, High density screen) - 72px x 72px
drawable-xhdpi (320 dpi, Extra-high density screen) - 96px x 96px
drawable-xxhdpi or drawable-480dpi (480 dpi, XHDPI density screen) - 144px x 144px

Reacting to different orientations

That´s another very common task. Here one option you may like it:

private boolean onPhoneMovement() {
  boolean isPhoneLyingOnTheSide = false;
  DisplayMetrics metrics = getResources().getDisplayMetrics();
  int displayWidth = metrics.widthPixels;
  int displayHeight = metrics.heightPixels;
  switch (getWindowManager().getDefaultDisplay().getRotation()) {
  case Surface.ROTATION_0:
  case Surface.ROTATION_180: {
   onPhoneStands(displayHeight);
   isPhoneLyingOnTheSide = false;
   break;
  }
  case Surface.ROTATION_90:
  case Surface.ROTATION_270: {
   onPhoneLiesOnTheSide(displayWidth);
   isPhoneLyingOnTheSide = true;
   break;
  }
  }
  return isPhoneLyingOnTheSide;
 }

Setting Width and Height to Layouts

That can be very usefull in some cases:

private void onPhoneLiesOnTheSide(int displayWidth) {
  this.toReplace = (LinearLayout) findViewById(R.id.toReplace);
  this.toReplace.getLayoutParams().height = this.buttonBackground.getHeight();
  this.toReplace.getLayoutParams().width = displayWidth - this.buttonBackground.getWidth();
 }

 private void onPhoneStands(int displayHeight) {
  this.toReplace = (LinearLayout) findViewById(R.id.toReplace);
  this.toReplace.getLayoutParams().height = displayHeight - this.buttonBackground.getHeight();
  this.toReplace.getLayoutParams().width = this.buttonBackground.getWidth();
 }

Fragment Replacement and Animation (Slide In and Slide Out)

Attention: If you've never worked with fragments, so please read my previous post about it first. dynamically fragment replacement android This snippet could be a differencial in your app. create a folder anim and anim-land in the folder res. Then put those xml-files in it. In folder anim create a xml file called slide_in.xml


    


The in the same folder anim create a xml file called slide_out.xml


    


The in the folder anim-land create a xml file called slide_in.xml


    


And last but no least in the folder anim-land create a xml file called slide_out.xml


    



Then try this here:
 private void hideFragmen(final Fragment framgmentToShow, boolean isPhoneLyingOnTheSide) {
  FragmentTransaction transaction = getFragmentManager().beginTransaction();
  transaction.setCustomAnimations(R.anim.slide_out, R.anim.slide_in);
  transaction.replace(R.id.toReplace, framgmentToShow);
  transaction.hide(framgmentToShow);
  transaction.commit();
 }

 private void showFragment(final Fragment framgmentToShow, boolean isPhoneLyingOnTheSide) {
  FragmentTransaction transaction = getFragmentManager().beginTransaction();
  transaction.setCustomAnimations(R.anim.slide_out, R.anim.slide_in);
  transaction.replace(R.id.toReplace, framgmentToShow);
  transaction.show(framgmentToShow);
  transaction.commit();
 }

Load/Decode Bitmap from Resource with BitmapFactory

You'll need this line several times while developing with Android.

  Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);

Rotate icons depending on phone Orientation

That´s a nice one. Small, fine and native. Because buttons are also views you can use this i a very generic way.

private void setIconRotation(int degrees) {
  for (View view : viewsToRotate) {
   view.setRotation(degrees);
  }
}

Fix/fixing a layout on the right side of your phone

That's also a good one. No matter what kind of the screen orientation you have. Just fix(post it) your layout in the right corner of your phone.

public void handleRotationChange(int rotation) {
  switch (rotation) {
  case Surface.ROTATION_0:
  case Surface.ROTATION_180: {
   // ***********************************************************
   // rotate toolbar (fix it on the right)
   // ***********************************************************
   this.layoutToolbar.setOrientation(LinearLayout.HORIZONTAL);
   this.layoutToolbar.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
   LayoutParams params = (LayoutParams) this.layoutToolbar.getLayoutParams();
   params.gravity = Gravity.BOTTOM;
   params.width = LayoutParams.MATCH_PARENT;
   params.height = LayoutParams.WRAP_CONTENT;
   // ***********************************************************
   // rotate icons
   // ***********************************************************
   setIconRotation(0);
  }
   break;

  case Surface.ROTATION_90:
  case Surface.ROTATION_270: {
   // ***********************************************************
   // rotate toolbar (fix it on the bottom)
   // ***********************************************************
   this.layoutToolbar.setOrientation(LinearLayout.VERTICAL);
   this.layoutToolbar.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
   LayoutParams params = (LayoutParams) this.layoutToolbar.getLayoutParams();
   params.gravity = Gravity.RIGHT;
   params.width = LayoutParams.WRAP_CONTENT;
   params.height = LayoutParams.MATCH_PARENT;
   // ***********************************************************
   // rotate icons
   // ***********************************************************
   setIconRotation(0);
  }
   break;
  }
 }

Showing/show simple info message on the screen

private void showMessage(String msg) {
  Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
 }

GPS distance calculation from one point to another


public double calculeDistanciaEmMetrosComoDouble(double lat1, double lng1, double lat2, double lng2) {
  return calculeDistancia(lat1, lng1, lat2, lng2);
 }

 /** calcula a distância de um ponto ao outro (longitude, latitude) retornando a distância com o suffix "m" no final*/
 public String calculeDistanciaEmMetros(double lat1, double lng1, double lat2, double lng2) {
  double distanciaCalculada = calculeDistancia(lat1, lng1, lat2, lng2);
  return definaQuantosNumerosAposVirgula(2, distanciaCalculada) + " m";
 }
 
 /** calcula a distância de um ponto ao outro (longitude, latitude) retornando a distância com o suffix "km" no final*/
 public String calculeDistanciaEmKilometros(double lat1, double lng1, double lat2, double lng2) {
  double distanciaCalculada = calculeDistancia(lat1, lng1, lat2, lng2);
  double kilometros = distanciaCalculada / 1000;
  return definaQuantosNumerosAposVirgula(2, kilometros) + " km";
 }
 
 /** calcula a distância de um ponto ao outro (longitude, latitude) retornando a distância em miles (1.609km) com o suffix "miles" no final*/
 public String calculeDistanciaEmMiles(double lat1, double lng1, double lat2, double lng2) {
  double distanciaCalculada = calculeDistancia(lat1, lng1, lat2, lng2);
  double miles = distanciaCalculada / 1609.344;
  return definaQuantosNumerosAposVirgula(2, miles) + " miles";
 }
 
 /** calcula a distância de um ponto ao outro (longitude, latitude) retornando a distância em yards (0.9144m) com o suffix "yards" no final*/
 public String calculeDistanciaEmYards(double lat1, double lng1, double lat2, double lng2) {
  double distanciaCalculada = calculeDistancia(lat1, lng1, lat2, lng2);
  double yards = distanciaCalculada / 0.9144;
  return definaQuantosNumerosAposVirgula(2, yards) + " yards";
 }
 
 /** calcula a distância de um ponto ao outro (longitude, latitude) retornando a distância em feets (0.3048m) com o suffix "feets" no final*/
 public String calculeDistanciaEmFeets(double lat1, double lng1, double lat2, double lng2) {
  double distanciaCalculada = calculeDistancia(lat1, lng1, lat2, lng2);
  double feets = distanciaCalculada / 0.3048;
  return definaQuantosNumerosAposVirgula(2, feets) + " feets";
 }
 
 /** calcula a distância de um ponto ao outro (longitude, latitude) retornando a distância em metros"*/
 private double calculeDistancia(double lat1, double lng1, double lat2, double lng2) {
  double earthRadius = 3958.75;
  double dLat = Math.toRadians(lat2 - lat1);
  double dLng = Math.toRadians(lng2 - lng1);
  double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
    + Math.cos(Math.toRadians(lat1))
    * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2)
    * Math.sin(dLng / 2);
  double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  double dist = earthRadius * c;
  int meterConversion = 1609;
  double result = (dist * meterConversion);
  return result;

 }
 
 private String definaQuantosNumerosAposVirgula(int qnt, double amount){
  NumberFormat df = DecimalFormat.getInstance();
  df.setMinimumFractionDigits(2);
  df.setMaximumFractionDigits(2);
  return df.format(amount);
 }

Hide Application Titlebar


public void hideApplicationTitleBar() {
  requestWindowFeature(Window.FEATURE_NO_TITLE);
 }

Set Application Orientation


setRequestedOrientation(defineActivityOrientation());
public int defineActivityOrientation() {
  return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 }

GPS Locatition Manager, LastKnownLocation, Wifi, Network


protected LocationManager locationManager;
protected String provider;
protected Geocoder coder;
private void initGeoLocation() {
  this.addressFinder = new AddressFinder(this, this.autoCompleteSearch);
  this.locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
  showMessageOnGpsDeactivated();
  // Define the criteria how to select the locatioin provider -> use default
  this.provider = locationManager.getBestProvider(new Criteria(), false);
  this.coder = new Geocoder(this);
 }
public boolean showMessageOnGpsDeactivated() {
  boolean isGpsDeactivated = false;
  if (!isGpsProviderEnabled() || !isNetworkProviderEnabled()) {
   showModalGpsActivateDialog();
   isGpsDeactivated = true;
  }
  return isGpsDeactivated;
 }
private boolean isGpsProviderEnabled() {
  return this.locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
 }

 private boolean isNetworkProviderEnabled() {
  return this.locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
 }
public boolean isOnline() {
  boolean isConnected = false;
  ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo netInfo = cm.getActiveNetworkInfo();
  if (netInfo != null && netInfo.isConnectedOrConnecting()) {
   isConnected = true;
  }
  return isConnected;
 }
public boolean isWiFiOnline() {
  boolean isConnected = false;
  ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo mWifi = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
  if (mWifi != null && mWifi.isConnectedOrConnecting()) {
   isConnected = true;
  }
  return isConnected;
 }
public void showModalGpsActivateDialog() {

  LayoutInflater inflater = getLayoutInflater();
  View view = inflater.inflate(R.layout.layout_toast, (ViewGroup) findViewById(R.id.layout_toast_gps));

  new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(getResources().getText(R.string.toast_gps_dialog_title))
    .setPositiveButton(getResources().getText(R.string.toast_gps_dialog_button_text), new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
      navigateTo(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
     }

    }).setView(view).setCancelable(false).show();
 }
public Location getLastKnownLocation() {
  Location location = null;
  if (isOnline()) {
   if (!showMessageOnGpsDeactivated()) {
    if (isLocationAvailable()) {
     location = this.locationManager.getLastKnownLocation(this.provider);
    } else {
     showMessage(this, getResources().getString(R.string.toast_gps_dialog_no_gps_available));
    }
   }
  } else {
   showModalNoNetworkDialog();
  }
  return location;
 }

 public boolean isLocationAvailable() {
  this.locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
  this.provider = locationManager.getBestProvider(new Criteria(), false);
  this.coder = new Geocoder(this);
  return this.locationManager.getLastKnownLocation(this.provider) != null;
 }

Navigation, Intent, Google Play Store, Webpage


/** Use this method to get passed values over Intent.SetExtras(...) */
 public String getPassedUserInputSelection(String key) {
  return (String) getIntent().getExtras().get(key);
 }

 /** Use this method to navigate from one activity to another passing values to the target activity */
 public void navigateToPassingValues(Context fromActivity, Class toActivityClass, String bundleKey, Bundle bundle) {
  Intent activityToStart = createActivityToStart(fromActivity, toActivityClass);
  activityToStart.putExtra(bundleKey, bundle);
  startActivity(activityToStart);
 }

 /** Use this method to navigate from one activity to another passing values to the target activity */
 public void navigateToPassingValues(Context fromActivity, Class toActivityClass, String key, String value) {
  Intent activityToStart = createActivityToStart(fromActivity, toActivityClass);
  activityToStart.putExtra(key, value);
  startActivity(activityToStart);
 }

 /** Use this method to navigate from one activity to another */
 public void navigateTo(Context fromActivity, Class toActivityClass) {
  startActivity(createActivityToStart(fromActivity, toActivityClass));
 }

 /** Use this method to navigate directly to a given intent */
 public void navigateTo(Intent intent) {
  startActivity(intent);
 }

 private Intent createActivityToStart(Context fromActivity, Class toActivityClass) {
  return new Intent(fromActivity, toActivityClass);
 }

 /** Use this method to open the google play store from this app */
 public void navigateToGooglePlayStore() {
  final String appName = "com.treslines.onibuspe";
  try {
   startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appName)));
  } catch (android.content.ActivityNotFoundException anfe) {
   startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + appName)));
  }
 }

 public void navigateToTreslines() {
  final String webpage = "http://www.treslines.com/index.html";
  try {
   startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(webpage)));
  } catch (android.content.ActivityNotFoundException anfe) {
   // If anything goes wrong, don't disturb the user experience. just don't open the webpage
  }
 }
 
 public void navigateToWebpage(String address) {
  final String webpage = address;
  try {
   startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(webpage)));
  } catch (android.content.ActivityNotFoundException anfe) {
   // If anything goes wrong, don't disturb the user experience. just don't open the webpage
  }
 }

 /** Use this method to display messages to the user */
 public void showMessage(Context context, String msg) {
  Toast toast = Toast.makeText(context, msg, Toast.LENGTH_LONG);
  toast.setGravity(Gravity.CENTER, 0, 0);
  toast.show();
 }

AutoComplete, MultiAutoCompleteTextView


/** Use this method to create a custom autocomplete with NoTokenizer and no suggestions flags */
 public void createAutoComplete(MultiAutoCompleteTextView autoComplete, String[] contentToShow) {
  autoComplete.setAdapter(new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, contentToShow));
  autoComplete.setTokenizer(getTokenizerForMultiAutoCompleteTextView());
  autoComplete.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
 }

 /** Use this method to create a custom Tokenizer with no comma(,) termination */
 public NoTokenizer getTokenizerForMultiAutoCompleteTextView() {
  return new NoTokenizer();
 }

 private class NoTokenizer extends MultiAutoCompleteTextView.CommaTokenizer {

  @Override
  public int findTokenEnd(CharSequence text, int cursor) {
   return super.findTokenEnd(text, cursor);
  }

  @Override
  public int findTokenStart(CharSequence text, int cursor) {
   return super.findTokenStart(text, cursor);
  }

  @Override
  public CharSequence terminateToken(CharSequence text) {
   CharSequence terminateToken = super.terminateToken(text);
   terminateToken = terminateToken.toString().replace(" ,", "").replace(", ", "");
   return terminateToken;
  }

 }

Creating array from string.xml


public String[] createLinhasFromStringXml() {
  return getResources().getStringArray(R.array.linha_array);
 }

Inflater to put into your abstracted class


public View inflateContentView(int layoutId) {
  LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  return inflater.inflate(layoutId, null);
 }

DB, database date parser


import android.annotation.SuppressLint;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@SuppressLint("SimpleDateFormat")
public class DbDateParser {
 private static final String format = "yyyy-MM-dd";

 public static Date stringToDate(String data) {
  Date dDate = null;
  SimpleDateFormat formatter = new SimpleDateFormat(format);
  try {
   dDate = formatter.parse(data);
  } catch (ParseException e) {
  }
  return dDate;
 }

 public static String dateToString(Date data) {
  return dateToString(data, format);
 }

 public static String dateToString(Date data, String format) {
  SimpleDateFormat formatter = new SimpleDateFormat(format);
  return formatter.format(data);
 }

 public static int getHour(Date data) {
  try {
   SimpleDateFormat formatter = new SimpleDateFormat("HH");
   return Integer.parseInt(formatter.format(data));
  } catch (Exception ex) {
   return -1;
  }
 }

 public static int getMinute(Date data) {
  try {
   SimpleDateFormat formatter = new SimpleDateFormat("mm");
   return Integer.parseInt(formatter.format(data));
  } catch (Exception ex) {
   return -1;
  }
 }

 public static int getDay(Date data) {
  try {
   SimpleDateFormat formatter = new SimpleDateFormat("dd");
   return Integer.parseInt(formatter.format(data));
  } catch (Exception ex) {
   return -1;
  }
 }

 public static int getMonth(Date data) {
  try {
   SimpleDateFormat formatter = new SimpleDateFormat("MM");
   return Integer.parseInt(formatter.format(data));
  } catch (Exception ex) {
   return -1;
  }
 }

 public static int getYear(Date data) {
  try {
   SimpleDateFormat formatter = new SimpleDateFormat("yyyy");
   return Integer.parseInt(formatter.format(data));
  } catch (Exception ex) {
   return -1;
  }
 }

 public static Date getFullHour_String2Date(String data) {
  try {
   SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
   return formatter.parse(data);
  } catch (Exception ex) {
   return new Date();
  }
 }
}

Ormlite, SQLite, DatabaseHelper


import java.sql.SQLException;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import com.treslines.entity.EmpresaEntity;
import com.treslines.entity.ItinerarioEntity;
import com.treslines.entity.LinhaEntity;
import com.treslines.entity.ParadaEntity;
import com.treslines.entity.ReferenciaEntity;
import com.treslines.entity.RotaEntity;
import com.treslines.entity.RoteiroEntity;

public class DatabaseHelper extends OrmLiteSqliteOpenHelper {

 private static final String DATABASE_NAME = "databasename.db";
 private static final int DATABASE_VERSION = 1;

 public DatabaseHelper(Context context) {
  super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }

 @Override
 public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
  try {
   Log.i("DB", "onCreate: create tables if not exists");
   TableUtils.createTableIfNotExists(connectionSource, LinhaEntity.class);
   TableUtils.createTableIfNotExists(connectionSource, ReferenciaEntity.class);
   TableUtils.createTableIfNotExists(connectionSource, RoteiroEntity.class);
   TableUtils.createTableIfNotExists(connectionSource, RotaEntity.class);
   TableUtils.createTableIfNotExists(connectionSource, EmpresaEntity.class);
   TableUtils.createTableIfNotExists(connectionSource, ItinerarioEntity.class);
   TableUtils.createTableIfNotExists(connectionSource, ParadaEntity.class);
  } catch (SQLException e) {
   Log.e(DatabaseHelper.class.getSimpleName(), "Can't create database", e);
   throw new RuntimeException(e);
  }
 }

 @Override
 public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
  try {
   // delete all tables
   Log.i("DB", "onUpgrade: drop old tables and create new tables");
   TableUtils.dropTable(connectionSource, ParadaEntity.class, true);
   TableUtils.dropTable(connectionSource, ItinerarioEntity.class, true);
   TableUtils.dropTable(connectionSource, EmpresaEntity.class, true);
   TableUtils.dropTable(connectionSource, RotaEntity.class, true);
   TableUtils.dropTable(connectionSource, RoteiroEntity.class, true);
   TableUtils.dropTable(connectionSource, ReferenciaEntity.class, true);
   TableUtils.dropTable(connectionSource, LinhaEntity.class, true);
   // create new tables
   onCreate(db, connectionSource);
  } catch (SQLException e) {
   Log.e(DatabaseHelper.class.getSimpleName(), "Can't drop databases", e);
   throw new RuntimeException(e);
  }
 }

 @Override
 public void close() {
  super.close();
 }
}

import com.j256.ormlite.field.DatabaseField;

// ORMLite download addresses
// ormlite-android-4.45: //www.java2s.com/Code/Jar/o/Downloadormliteandroid445jar.htm
// ormlite-core-4.45: http://sourceforge.net/projects/ormlite/files/

public abstract class AbstractEntity {

 @DatabaseField(columnName="_id", generatedId = true)
 private Integer id;
 @DatabaseField(columnName="timestamp")
 private String timestamp;
 
 // ormlite require default constructor
 public AbstractEntity() {
  super();
 }
 
 public AbstractEntity(Integer id, String timestamp) {
  setId(id);
  setTimestamp(timestamp);
 }

 public Integer getId() {return id;}
 public void setId(Integer id) {this.id = id;}
 public String getTimestamp() {return timestamp;}
 public void setTimestamp(String timestamp) {this.timestamp = timestamp;}

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((id == null) ? 0 : id.hashCode());
  result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  AbstractEntity other = (AbstractEntity) obj;
  if (id == null) {
   if (other.id != null)
    return false;
  } else if (!id.equals(other.id))
   return false;
  if (timestamp == null) {
   if (other.timestamp != null)
    return false;
  } else if (!timestamp.equals(other.timestamp))
   return false;
  return true;
 } 
}

import java.util.ArrayList;
import java.util.Collection;

import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.field.ForeignCollectionField;
import com.j256.ormlite.table.DatabaseTable;

@DatabaseTable(tableName="empresa")
public class EmpresaEntity extends AbstractEntity implements Comparable{

 @DatabaseField(columnName="empresa_nome")
 private String nome;
 @DatabaseField(columnName="empresa_abreviacao")
 private String abreviacao;
 @DatabaseField(columnName="empresa_codigo")
 private String codigo;
 @ForeignCollectionField(columnName="empresa_linhas")
 private Collection linhas = new ArrayList();
 
 // ormlite require default constructor
 public EmpresaEntity(){
  super();
 }
 
 public EmpresaEntity(String codigo,String abreviacao,String nome, Collection linhas){
  setCodigo(codigo);
  setAbreviacao(abreviacao);
  setNome(nome);
  setLinhas(linhas);
 }
 
 public EmpresaEntity(String codigo,String abreviacao,String nome){
  setCodigo(codigo);
  setAbreviacao(abreviacao);
  setNome(nome);
 }
 
 public Collection getLinhas() {return linhas;}
 public void setLinhas(Collection linhas) {this.linhas = linhas;}
 public String getNome() {return nome;}
 public void setNome(String nome) {this.nome = nome;}
 public String getAbreviacao() {return abreviacao;}
 public void setAbreviacao(String abreviacao) {this.abreviacao = abreviacao;}
 public String getCodigo() {return codigo;}
 public void setCodigo(String codigo) {this.codigo = codigo;}

 @Override
 public int compareTo(EmpresaEntity another) {
  if (equals(another)) {
   return 0;
  }
  return -1;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = super.hashCode();
  result = prime * result + ((abreviacao == null) ? 0 : abreviacao.hashCode());
  result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
  result = prime * result + ((linhas == null) ? 0 : linhas.hashCode());
  result = prime * result + ((nome == null) ? 0 : nome.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (!super.equals(obj))
   return false;
  if (getClass() != obj.getClass())
   return false;
  EmpresaEntity other = (EmpresaEntity) obj;
  if (abreviacao == null) {
   if (other.abreviacao != null)
    return false;
  } else if (!abreviacao.equals(other.abreviacao))
   return false;
  if (codigo == null) {
   if (other.codigo != null)
    return false;
  } else if (!codigo.equals(other.codigo))
   return false;
  if (linhas == null) {
   if (other.linhas != null)
    return false;
  } else if (!linhas.equals(other.linhas))
   return false;
  if (nome == null) {
   if (other.nome != null)
    return false;
  } else if (!nome.equals(other.nome))
   return false;
  return true;
 }
}

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†