How to Use CommandLineRunner in Spring Boot Application

package com.therealdanvega;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
 
@Component
public class DataLoader implements CommandLineRunner {
 
    private final Logger logger = LoggerFactory.getLogger(DataLoader.class);
 
    @Override
    public void run(String... strings) throws Exception {
        logger.info("Loading data...");
 
    }
}

References
https://www.quickprogrammingtips.com/spring-boot/how-to-use-commandlinerunner-in-spring-boot-application.html
http://therealdanvega.com/blog/2017/04/07/spring-boot-command-line-runner

Integrate Facebook Login with your Android Application

Follow this QuickStart for Facebook Login for Android
https://developers.facebook.com/docs/facebook-login/android

Link the Facebook SDK

mavenCentral() 
compile 'com.facebook.android:facebook-login:[4,5)'

Edit Your Manifest

Open your /app/src/main/res/values/strings.xml file

<string name="facebook_app_id">id</string>
<string name="fb_login_protocol_scheme">protocol</string>

Open the /app/manifest/AndroidManifest.xml file.

<uses-permission android:name="android.permission.INTERNET"/>

Add the following meta-data element, an activity for Facebook, and an activity and intent filter for Chrome Custom Tabs after the application element. Replace @string/appname with the name of your Facebook App:

<meta-data android:name="com.facebook.sdk.ApplicationId" 
        android:value="@string/facebook_app_id"/>
    
    <activity android:name="com.facebook.FacebookActivity"
        android:configChanges=
                "keyboard|keyboardHidden|screenLayout|screenSize|orientation"
        android:label="@string/app_name" />
    <activity
        android:name="com.facebook.CustomTabActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="@string/fb_login_protocol_scheme" />
        </intent-filter>
    </activity>

Provide the Development and Release Key Hashes for Your App

Download OpenSSL which is Requisite
https://slproweb.com/products/Win32OpenSSL.html

Add OpenSSL to path, so you can access it from command line

Go to JDK bin folder

cd C:\Program Files\Java\jdk1.8.0_151\bin

Add debug key hash

keytool -exportcert -alias androiddebugkey -keystore C:\Users\Mahmood\.android\debug.keystore | openssl sha1 -binary | openssl base64

Add release key hash

keytool -exportcert -alias lastlab -keystore C:\Projects\lastlab\keys\store.jks | openssl sha1 -binary | openssl base64

Read QuickStart to Add Facebook Custom Login Button

        buttonSignupFacebook = findViewById(R.id.buttonSignupFacebook);

        facebookLoginManager = LoginManager.getInstance();
        facebookCallbackManager = CallbackManager.Factory.create();

        facebookLoginManager.registerCallback(facebookCallbackManager, new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                Toast.makeText(SelectSignupActivity.this, loginResult.getAccessToken().toString(),
                        Toast.LENGTH_LONG).show();
            }

            @Override
            public void onCancel() {

            }

            @Override
            public void onError(FacebookException error) {
                Toast.makeText(SelectSignupActivity.this, error.getMessage(),
                        Toast.LENGTH_LONG).show();
                error.printStackTrace();
            }
        });

        buttonSignupFacebook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                facebookLoginManager.logInWithReadPermissions(SelectSignupActivity.this,
                        Arrays.asList("email", "public_profile", "user_birthday"));
            }
        });
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        facebookCallbackManager.onActivityResult(requestCode, resultCode, data);
        super.onActivityResult(requestCode, resultCode, data);
    }

References
https://developers.facebook.com
https://www.youtube.com/watch?v=SrAXmZkOpJI
https://developers.facebook.com/docs/facebook-login/android
https://stackoverflow.com/questions/16965058/where-is-debug-keystore-in-android-studio
https://developer.android.com/studio/publish/app-signing.html
https://github.com/facebook/facebook-android-sdk
https://developers.facebook.com/docs/facebook-login/permissions/
https://androidammy.blogspot.com/2015/09/facebook-login-with-custom-button.html

Populating Spinner items directly in xml layout

In your strings.xml define:

<string-array name="array_name">
<item>Array Item One</item>
<item>Array Item Two</item>
<item>Array Item Three</item>
</string-array>

In your layout:

<Spinner 
        android:id="@+id/spinner"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:drawSelectorOnTop="true"
        android:entries="@array/array_name"
    />

References
https://stackoverflow.com/questions/4029261/populating-spinner-directly-in-the-layout-xml

Animating Layout Changes

All you need to do is set an attribute in the layout to tell the Android system to animate these layout changes, and system-default animations are carried out for you.

<LinearLayout android:id="@+id/container"
    android:animateLayoutChanges="true"
    ...
/>

Now, all you need to do is add, remove, or update items in the layout and the items are animated automatically:

private ViewGroup mContainerView;
...
private void addItem() {
    View newView;
    ...
    mContainerView.addView(newView, 0);
}

Tip: If you want to supply custom layout animations, create a LayoutTransition object and supply it to the layout with the setLayoutTransition() method.

References
https://developer.android.com/training/animation/layout.html
https://stackoverflow.com/questions/41464629/expand-collapse-animation-in-cardview
https://github.com/mhdr/AndroidSamples/tree/master/104

Constraint Layout Vertical Align Center

If you have a ConstraintLayout with some size, and a child View with some smaller size, you can achieve centering by constraining the child’s two edges to the same two edges of the parent and set width to 0dp. That is, you can write:

app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"

Or

app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

Example

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/stat_1"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:gravity="center"
        android:maxLines="1"
        android:text="10"
        android:textColor="#777"
        android:textSize="22sp"
        app:layout_constraintTop_toTopOf="@+id/stat_2"
        app:layout_constraintEnd_toStartOf="@+id/divider_1" />

    <TextView
        android:id="@+id/stat_detail_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Streak"
        android:textColor="#777"
        android:textSize="12sp"
        app:layout_constraintTop_toBottomOf="@+id/stat_1"
        app:layout_constraintStart_toStartOf="@+id/stat_1"
        app:layout_constraintEnd_toEndOf="@+id/stat_1" />

    <View
        android:id="@+id/divider_1"
        android:layout_width="1dp"
        android:layout_height="0dp"
        android:layout_marginEnd="16dp"
        android:background="#ccc"
        app:layout_constraintTop_toTopOf="@+id/stat_2"
        app:layout_constraintEnd_toStartOf="@+id/stat_2"
        app:layout_constraintBottom_toBottomOf="@+id/stat_detail_2" />

    <TextView
        android:id="@+id/stat_2"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:maxLines="1"
        android:text="243"
        android:textColor="#777"
        android:textSize="22sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

    <TextView
        android:id="@+id/stat_detail_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:text="Calories Burned"
        android:textColor="#777"
        android:textSize="12sp"
        app:layout_constraintTop_toBottomOf="@+id/stat_2"
        app:layout_constraintStart_toStartOf="@+id/stat_2"
        app:layout_constraintEnd_toEndOf="@+id/stat_2" />

    <View
        android:id="@+id/divider_2"
        android:layout_width="1dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:background="#ccc"
        app:layout_constraintBottom_toBottomOf="@+id/stat_detail_2"
        app:layout_constraintStart_toEndOf="@+id/stat_2"
        app:layout_constraintTop_toTopOf="@+id/stat_2" />

    <TextView
        android:id="@+id/stat_3"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:gravity="center"
        android:maxLines="1"
        android:text="3200"
        android:textColor="#777"
        android:textSize="22sp"
        app:layout_constraintTop_toTopOf="@+id/stat_2"
        app:layout_constraintStart_toEndOf="@+id/divider_2" />

    <TextView
        android:id="@+id/stat_detail_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:text="Steps"
        android:textColor="#777"
        android:textSize="12sp"
        app:layout_constraintTop_toBottomOf="@+id/stat_3"
        app:layout_constraintStart_toStartOf="@+id/stat_3"
        app:layout_constraintEnd_toEndOf="@+id/stat_3" />

</android.support.constraint.ConstraintLayout>

References
https://stackoverflow.com/questions/45220013/constraint-layout-vertical-align-center

How to make ConstraintLayout work with percentage values

Use: a guideline with app:layout_constraintGuide_percent like this:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.3" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Hello text"
        app:layout_constraintLeft_toRightOf="@id/guideline"
        app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>

And then you can use this guideline as anchor points for other views.

Two minor but important notes:

  • TextView width should be 0dp i.e. match constraint and not match parent
  • Guideline orientation should be vertical not horizontal

References
https://stackoverflow.com/questions/42958168/constraint-layout-with-percentage-not-working-as-expected
https://stackoverflow.com/questions/37318228/how-to-make-constraintlayout-work-with-percentage-values

Transition animations between activities on Android above Lollipop

styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
    </style>

Caller Activity

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            Bundle bundle = ActivityOptions.makeSceneTransitionAnimation(this).toBundle();
            startActivity(intent, bundle);
        } else {
            startActivity(intent);
        }

Calling Activity

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Slide transition=new Slide();
            transition.setDuration(300);
            transition.setSlideEdge(Gravity.BOTTOM);
            transition.setMode(Visibility.MODE_IN);
            getWindow().setEnterTransition(transition);
        }

References
https://stackoverflow.com/questions/35064342/activity-transitions-not-working
https://developer.android.com/training/material/animations.html
https://github.com/lgvalle/Material-Animations