Friday, June 23, 2017

Question of using ContentLoadingProgressBar

android.support.v4.widget.ContentLoadingProgressBar is subclass of ProgressBar. That waits a minimum time to be dismissed before showing. Once visible, the progress bar will be visible for a minimum amount of time to avoid "flashes" in the UI when an event could take a largely variable time to complete (from none, to a user perceivable amount).

 I TRY to use it in this exercise. To display and hide it by calling its show() and hide() methods. By calling show(), show the progress view after waiting for a minimum delay. If during that time, hide() is called, the view is never made visible.

When long progress run after show(), the ContentLoadingProgressBar shown after a short time.
When short progress run after show(), the ContentLoadingProgressBar will not shown.

But the problem is: once ContentLoadingProgressBar no shown once, it will not be shown again! I don't is it normal behavior, or anything wrong.


Here is my exercise:

MainActivity.java
package com.blogspot.android_er.androidcontentloadingprogressbar;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.widget.ContentLoadingProgressBar;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {

    Button btnStartShortProgress, btnStartLongProgress;
    ProgressBar progressBar;
    ContentLoadingProgressBar contentLoadingProgressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnStartShortProgress = (Button)findViewById(R.id.startshortprogress);
        btnStartLongProgress = (Button)findViewById(R.id.startlongprogress);
        progressBar = (ProgressBar)findViewById(R.id.ProgressBar);
        contentLoadingProgressBar =
                (ContentLoadingProgressBar)findViewById(R.id.ContentLoadingProgressBar);

        btnStartShortProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                btnStartShortProgress.setEnabled(false);
                btnStartLongProgress.setEnabled(false);
                MyAsyncTask myAsyncTask = new MyAsyncTask();
                myAsyncTask.execute(3);
            }
        });

        btnStartLongProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                btnStartShortProgress.setEnabled(false);
                btnStartLongProgress.setEnabled(false);
                MyAsyncTask myAsyncTask = new MyAsyncTask();
                myAsyncTask.execute(50);
            }
        });
    }

    public class MyAsyncTask extends AsyncTask<Integer, Integer, Void> {

        @Override
        protected Void doInBackground(Integer... integers) {
            int i = integers[0];

            while(i-- > 0){
                SystemClock.sleep(100);
            }

            return null;
        }

        @Override
        protected void onPreExecute() {
            progressBar.setVisibility(View.VISIBLE);
            contentLoadingProgressBar.show();
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            progressBar.setVisibility(View.GONE);
            contentLoadingProgressBar.hide();
            btnStartShortProgress.setEnabled(true);
            btnStartLongProgress.setEnabled(true);
        }
    }
}



activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidcontentloadingprogressbar.MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold"
        />

    <Button
        android:id="@+id/startshortprogress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start SHORT Progress"/>
    <Button
        android:id="@+id/startlongprogress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start LONG Progress"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ProgressBar"
        android:textStyle="bold"/>
    <ProgressBar
        android:id="@+id/ProgressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ContentLoadingProgressBar"
        android:textStyle="bold"/>
    <android.support.v4.widget.ContentLoadingProgressBar
        android:id="@+id/ContentLoadingProgressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ic_launcher"/>

</LinearLayout>


Examples of ProgressBar and AsyncTask

Thursday, June 22, 2017

Custom ProgressBar with SecondaryProgress

The former post show how to implement "Custom ProgressBar with progressDrawable" and "ProgressBar with SecondaryProgress". This example show how to Custom ProgressBar with SecondaryProgress.


Create a custom drawable xml res/drawable/myprogressbar.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="5dip" />
            <gradient
                android:angle="180"
                android:centerY="1.0"
                android:startColor="#E8E8E8"
                android:centerColor="#F0F0F0"
                android:endColor="#F8F8F8" />
        </shape>
    </item>
    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    android:angle="270"
                    android:centerY="1.0"
                    android:startColor="#6000F000"
                    android:centerColor="#60008080"
                    android:endColor="#600000F0" />
            </shape>
        </clip>
    </item>
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    android:angle="270"
                    android:centerY="1.0"
                    android:startColor="#E000F000"
                    android:centerColor="#E0008080"
                    android:endColor="#E00000F0" />
            </shape>
        </clip>
    </item>
</layer-list>

Edit the layout to add android:progressDrawable
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidprogressbar.MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold"/>

    <Button
        android:id="@+id/startprogress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start ProgressBar"/>

    <ProgressBar
        android:id="@+id/progressbar"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:max="10"
        android:progress="0"
        android:secondaryProgress="0"
        android:visibility="gone"/>
    <ProgressBar
        android:id="@+id/myprogressbar"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:max="10"
        android:progress="0"
        android:secondaryProgress="0"
        android:visibility="gone"
        android:progressDrawable="@drawable/myprogressbar"/>

</LinearLayout>



MainActivity.java
package com.blogspot.android_er.androidprogressbar;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {

    Button btnStartProgress;
    ProgressBar progressBar, myProgressBar;

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

        btnStartProgress = (Button)findViewById(R.id.startprogress);
        progressBar = (ProgressBar)findViewById(R.id.progressbar);
        myProgressBar = (ProgressBar)findViewById(R.id.myprogressbar);

        btnStartProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                btnStartProgress.setEnabled(false);
                MyAsyncTask myAsyncTask = new MyAsyncTask();
                myAsyncTask.execute();
            }
        });
    }

    public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

        @Override
        protected void onPreExecute() {
            progressBar.setVisibility(View.VISIBLE);
            myProgressBar.setVisibility(View.VISIBLE);
            progressBar.setProgress(0);
            progressBar.setSecondaryProgress(0);
            myProgressBar.setProgress(0);
            myProgressBar.setSecondaryProgress(0);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            for(int i=0; i<10; i++){
                for(int j=0; j<10; j++){
                    publishProgress(i, j);
                    SystemClock.sleep(100);
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            progressBar.setProgress(values[0]);
            progressBar.setSecondaryProgress(values[1]);
            myProgressBar.setProgress(values[0]);
            myProgressBar.setSecondaryProgress(values[1]);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            progressBar.setVisibility(View.GONE);
            myProgressBar.setVisibility(View.GONE);
            btnStartProgress.setEnabled(true);
        }
    }
}


~ More examples of ProgressBar

ProgressBar with SecondaryProgress

Example to use ProgressBar with SecondaryProgress


MainActivity.java
package com.blogspot.android_er.androidprogressbar;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {

    Button btnStartProgress;
    ProgressBar progressBar;

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

        btnStartProgress = (Button)findViewById(R.id.startprogress);
        progressBar = (ProgressBar)findViewById(R.id.progressbar);

        btnStartProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                btnStartProgress.setEnabled(false);
                MyAsyncTask myAsyncTask = new MyAsyncTask();
                myAsyncTask.execute();
            }
        });
    }

    public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

        @Override
        protected void onPreExecute() {
            progressBar.setVisibility(View.VISIBLE);
            progressBar.setProgress(0);
            progressBar.setSecondaryProgress(0);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            for(int i=0; i<10; i++){
                for(int j=0; j<10; j++){
                    publishProgress(i, j);
                    SystemClock.sleep(100);
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            progressBar.setProgress(values[0]);
            progressBar.setSecondaryProgress(values[1]);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            progressBar.setVisibility(View.GONE);
            btnStartProgress.setEnabled(true);
        }
    }
}



activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidprogressbar.MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold"
        />

    <Button
        android:id="@+id/startprogress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start ProgressBar"/>

    <ProgressBar
        android:id="@+id/progressbar"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10"
        android:progress="0"
        android:secondaryProgress="0"
        android:visibility="gone"/>

</LinearLayout>


Next:
Custom ProgressBar with SecondaryProgress

~ More examples of using ProgressBar


Tuesday, June 20, 2017

Add ProgressBar in ToolBar

This example show how to add android.support.v7.widget.Toolbar to layout and add ProgressBar to the ToolBar.


New a project of empty activity in Android Studio.

Edit res/values/styles.xml to change style to "Theme.AppCompat.Light.NoActionBar".
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>


Refer to the above video, add a ToolBar to the layout, and add a ProgressBar to the ToolBar, using Android Studio's graphical design tool.

res/layout/activity_main.xml
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.blogspot.android_er.toolbarprogressbar.MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="0dp"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"
        app:layout_constraintVertical_bias="0.501" />

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="368dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="0dp"
        android:layout_marginRight="0dp"
        android:layout_marginTop="0dp"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="8dp"
        android:visibility="gone"/>

</android.support.constraint.ConstraintLayout>


MainActivity.java
package com.blogspot.android_er.toolbarprogressbar;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    TextView tvTitle;
    ProgressBar myProgressBar;

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

        tvTitle = (TextView)findViewById(R.id.title);
        myProgressBar = (ProgressBar)findViewById(R.id.progressBar);

        tvTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getBaseContext(),
                        "ProgressBar start running",
                        Toast.LENGTH_LONG).show();
                tvTitle.setClickable(false);
                MyAsyncTask myAsyncTask = new MyAsyncTask();
                myAsyncTask.execute();
            }
        });
    }

    public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

        @Override
        protected void onPreExecute() {
            myProgressBar.setVisibility(View.VISIBLE);
            myProgressBar.setProgress(0);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            for(int i=0; i<100; i++){
                publishProgress(i);
                SystemClock.sleep(100);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            myProgressBar.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            myProgressBar.setVisibility(View.GONE);
            tvTitle.setClickable(true);
        }
    }
}


Result:

To replace the indeterminate ProgressBar to Horizontal Progress Bar, edit res/layout/activity_main.xml. (maybe you want to set android:visibility="gone" as in progressBarStyle, depends on your case)
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.blogspot.android_er.toolbarprogressbar.MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="0dp"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"
        app:layout_constraintVertical_bias="0.501" />

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="368dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="0dp"
        android:layout_marginRight="0dp"
        android:layout_marginTop="0dp"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="0dp"
        android:layout_marginLeft="0dp"
        android:layout_marginRight="0dp"
        app:layout_constraintBottom_toBottomOf="@+id/toolbar"
        app:layout_constraintLeft_toLeftOf="@+id/toolbar"
        app:layout_constraintRight_toRightOf="@+id/toolbar" />

</android.support.constraint.ConstraintLayout>



More examples of:
android.support.v7.widget.Toolbar
- ProgressBar

Monday, June 19, 2017

Custom ProgressBar with progressDrawable


To implement our custom ProgressBar, create a drawable xml under /res/drawable/.

res/drawable/myprogressbar.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="10dip" />
            <gradient
                android:startColor="#000000"
                android:centerColor="#FF0000"
                android:centerY="1.0"
                android:endColor="#B0B0B0"
                android:angle="180"
                />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="10dip" />
                <gradient
                    android:startColor="#101010"
                    android:centerColor="#808080"
                    android:centerY="1.0"
                    android:endColor="#F0F0F0"
                    android:angle="270"
                    />
            </shape>
        </clip>
    </item>
</layer-list>

Edit the layout to add android:progressDrawable
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidprogressbar.MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold"
        />

    <Button
        android:id="@+id/startprogress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start ProgressBar"/>

    <ProgressBar
        android:id="@+id/progressbar"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:progress="0"
        android:visibility="gone"/>

    <ProgressBar
        android:id="@+id/myprogressbar"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:progress="0"
        android:visibility="gone"
        android:progressDrawable="@drawable/myprogressbar"/>

</LinearLayout>


MainActivity.java
package com.blogspot.android_er.androidprogressbar;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {

    Button btnStartProgress;
    ProgressBar progressBar, myProgressBar;

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

        btnStartProgress = (Button)findViewById(R.id.startprogress);
        progressBar = (ProgressBar)findViewById(R.id.progressbar);
        myProgressBar = (ProgressBar)findViewById(R.id.myprogressbar);


        btnStartProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                btnStartProgress.setEnabled(false);
                MyAsyncTask myAsyncTask = new MyAsyncTask();
                myAsyncTask.execute();
            }
        });
    }

    public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

        @Override
        protected void onPreExecute() {
            myProgressBar.setVisibility(View.VISIBLE);
            myProgressBar.setProgress(0);
            progressBar.setVisibility(View.VISIBLE);
            progressBar.setProgress(0);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            for(int i=0; i<100; i++){
                publishProgress(i);
                SystemClock.sleep(100);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            myProgressBar.setProgress(values[0]);
            progressBar.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            myProgressBar.setVisibility(View.GONE);
            progressBar.setVisibility(View.GONE);
            btnStartProgress.setEnabled(true);
        }
    }
}


Next:
ProgressBar with SecondaryProgress
Custom ProgressBar with SecondaryProgress


Examples of ProgressBar and AsyncTask


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidprogressbar.MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold"
        />

    <Button
        android:id="@+id/startprogress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start ProgressBar"/>

    <ProgressBar
        android:id="@+id/indeterminateBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone" />

    <ProgressBar
        android:id="@+id/determinateBar1"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:progress="0"
        android:visibility="gone"/>
    <ProgressBar
        android:id="@+id/determinateBar2"
        style="@android:style/Widget.ProgressBar.Inverse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>
    <ProgressBar
        android:id="@+id/determinateBar3"
        style="@android:style/Widget.ProgressBar.Large"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>
    <ProgressBar
        android:id="@+id/determinateBar4"
        style="@android:style/Widget.ProgressBar.Large.Inverse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>
    <ProgressBar
        android:id="@+id/determinateBar5"
        style="@android:style/Widget.ProgressBar.Small"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>
    <ProgressBar
        android:id="@+id/determinateBar6"
        style="@android:style/Widget.ProgressBar.Small.Inverse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ic_launcher"/>
</LinearLayout>



package com.blogspot.android_er.androidprogressbar;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {

    Button btnStartProgress;
    ProgressBar indeterminateBar;
    ProgressBar determinateBar1, determinateBar2, determinateBar3,
                determinateBar4, determinateBar5, determinateBar6;

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

        btnStartProgress = (Button)findViewById(R.id.startprogress);
        indeterminateBar = (ProgressBar)findViewById(R.id.indeterminateBar);
        determinateBar1 = (ProgressBar)findViewById(R.id.determinateBar1);
        determinateBar2 = (ProgressBar)findViewById(R.id.determinateBar2);
        determinateBar3 = (ProgressBar)findViewById(R.id.determinateBar3);
        determinateBar4 = (ProgressBar)findViewById(R.id.determinateBar4);
        determinateBar5 = (ProgressBar)findViewById(R.id.determinateBar5);
        determinateBar6 = (ProgressBar)findViewById(R.id.determinateBar6);

        btnStartProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                btnStartProgress.setEnabled(false);
                MyAsyncTask myAsyncTask = new MyAsyncTask();
                myAsyncTask.execute();
            }
        });
    }

    public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

        @Override
        protected void onPreExecute() {
            indeterminateBar.setVisibility(View.VISIBLE);
            determinateBar1.setVisibility(View.VISIBLE);
            determinateBar1.setProgress(0);
            determinateBar2.setVisibility(View.VISIBLE);
            determinateBar3.setVisibility(View.VISIBLE);
            determinateBar4.setVisibility(View.VISIBLE);
            determinateBar5.setVisibility(View.VISIBLE);
            determinateBar6.setVisibility(View.VISIBLE);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            for(int i=0; i<100; i++){
                publishProgress(i);
                SystemClock.sleep(100);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            determinateBar1.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            indeterminateBar.setVisibility(View.GONE);
            determinateBar1.setVisibility(View.GONE);
            determinateBar2.setVisibility(View.GONE);
            determinateBar3.setVisibility(View.GONE);
            determinateBar4.setVisibility(View.GONE);
            determinateBar5.setVisibility(View.GONE);
            determinateBar6.setVisibility(View.GONE);
            btnStartProgress.setEnabled(true);
        }
    }
}


Next:
Custom ProgressBar with progressDrawable
Add ProgressBar in ToolBar
ProgressBar with SecondaryProgress
Custom ProgressBar with SecondaryProgress
Question of using ContentLoadingProgressBar

Saturday, June 17, 2017

Install Python 3.6 (and IDLE/pip) on Ubuntu 17.04


To install Python 3.6 on Ubuntu 17.04, enter the command:
$ sudo apt-get install python3.6

Install IDLE for Python 3.6, idle-python3.6:
$ sudo apt install idle-python3.6


To install package using pip for Python 3.6:

- Download get-pip.py from https://pip.pypa.io/en/latest/installing/

- Install pip for Python 3.6
$ sudo python3.6 get-pip.py

- Install package:
$ sudo python3.6 -m pip install <package>
reference: Python documenet - Installing Python Modules - ... work with multiple versions of Python installed in parallel

Mastering Android Game Development with Unity

Create enthralling Android games with Unity Faster Than Ever Before

Mastering Android Game Development with Unity

About This Book
  • Develop complex Android games with the help of Unity's advanced features such as artificial intelligence, high-end physics, and GUI transformations.
  • Create amazing Graphical User Interfaces (GUIs) with Unity's new uGUI system
  • Unravel and deploy exciting games across Android devices
Who This Book Is For
If you are a Unity 5 developer and want to expand your knowledge of Unity 5 to create high-end complex Android games, then this book is for you. Readers are expected to have a basic understanding of Unity 5, working with its environment, and its basic concepts.

What You Will Learn
  • Develop your own Jetpack Joyride clone game
  • Explore the advanced features of Unity 5 by building your own Action Fighting game
  • Develop remarkable Graphical User Interfaces (GUIs) with Unity's new uGUI system
  • Enhance your game by adding stunning particle systems and complex animations
  • Build pleasing virtual worlds with special effects, lights, sky cube maps, and cameras
  • Make your game more realistic by providing music and sound effects
  • Debug and deploy your games on different Android devices
In Detail
Game engines such as Unity are the power-tools behind the games we know and love. Unity is one of the most widely-used and best loved packages for game development and is used by everyone, from hobbyists to large studios, to create games and interactive experiences for the Web, desktop, mobile, and console. With Unity's intuitive, easy-to-learn toolset and this book, it's never been easier to become a game developer.

You will begin with the basic concepts of Android game development, a brief history of Android games, the building blocks of Android games in Unity 5, and the basic flow of games. You will configure an empty project for the Jetpack Joyride Clone Game, add an environment and characters, and control them. Next you will walk through topics such as particle systems, camera management, prefabs, animations, triggers, colliders, and basic GUI systems. You will then cover the basic setup for 3D action fighting games, importing models, textures and controlling them with a virtual on-screen joystick. Later you will set up Scene for 3D Configuration, create basic gameplays, and manage input controls. Next you will learn to create the interface for the main menu, gameplay, game over, achievements, and high score screens. Finally you will polish your game with stats, sounds, and Social Networking, followed by testing the game on Android devices and then publishing it on Google Play, Amazon, and OUYA Stores.

Style and approach
A step-by-step and detailed guide to developing high-end complex Android games utilizing the advanced concepts of Unity.

Monday, June 12, 2017

Example using SafetyNet reCAPTCHA API in Android App

reCAPTCHA Android API announced as part of Google Play Services. It's a simple example to use SafetyNet reCAPTCHA API in Android App. Basically, it follow the steps in the tutorial SafetyNet reCAPTCHA API.



- Create a Android Project in Android Studio as as usually, with minSdkVersion of 14 or higher. We need the Package Names in the next step.

- Visit reCAPTCHA Android signup site, fill in the blanks to get your Site key and Secret key. (Get your own, I will delete my keys after the samples finished.) Copy the keys to your program as String.

- Open SDK Manager in Android Studio, make sure you include Google Repository in your SDK Tools.

- Add the follow Google Play services APIs into your Gradle dependencies:
    compile 'com.google.android.gms:play-services-base:11.0.0'
    compile 'com.google.android.gms:play-services-basement:11.0.0'
    compile 'com.google.android.gms:play-services-safetynet:11.0.0'
    compile 'com.google.android.gms:play-services-tasks:11.0.0'

This video show how to:


Modify the code:

MainActivity.java
package com.blogspot.android_er.recaptcha;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.safetynet.SafetyNet;
import com.google.android.gms.safetynet.SafetyNetApi;

public class MainActivity extends AppCompatActivity
        implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener{

    final String SiteKey = "6LdMKyUUAAAAAN0ndw7byI03_qpbpjxKY-mTQnLw";
    final String SecretKey  = "6LdMKyUUAAAAALjcWovpXgcoXiI4i9ykn1U9qs8I";
    private GoogleApiClient mGoogleApiClient;

    Button btnRequest;
    TextView tvResult;

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

        tvResult = (TextView)findViewById(R.id.result);
        btnRequest = (Button)findViewById(R.id.request);
        btnRequest.setOnClickListener(RqsOnClickListener);

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(SafetyNet.API)
                .addConnectionCallbacks(MainActivity.this)
                .addOnConnectionFailedListener(MainActivity.this)
                .build();

        mGoogleApiClient.connect();
    }

    View.OnClickListener RqsOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            tvResult.setText("");

            SafetyNet.SafetyNetApi.verifyWithRecaptcha(mGoogleApiClient, SiteKey)
                    .setResultCallback(new ResultCallback<SafetyNetApi.RecaptchaTokenResult>() {
                        @Override
                        public void onResult(SafetyNetApi.RecaptchaTokenResult result) {
                            Status status = result.getStatus();

                            if ((status != null) && status.isSuccess()) {

                                tvResult.setText("isSuccess()\n");
                                // Indicates communication with reCAPTCHA service was
                                // successful. Use result.getTokenResult() to get the
                                // user response token if the user has completed
                                // the CAPTCHA.

                                if (!result.getTokenResult().isEmpty()) {
                                    tvResult.append("!result.getTokenResult().isEmpty()");
                                    // User response token must be validated using the
                                    // reCAPTCHA site verify API.
                                }else{
                                    tvResult.append("result.getTokenResult().isEmpty()");
                                }
                            } else {

                                Log.e("MY_APP_TAG", "Error occurred " +
                                        "when communicating with the reCAPTCHA service.");

                                tvResult.setText("Error occurred " +
                                        "when communicating with the reCAPTCHA service.");

                                // Use status.getStatusCode() to determine the exact
                                // error code. Use this code in conjunction with the
                                // information in the "Handling communication errors"
                                // section of this document to take appropriate action
                                // in your app.
                            }
                        }
                    });

        }
    };

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Toast.makeText(this, "onConnected()", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Toast.makeText(this,
                "onConnectionSuspended: " + i,
                Toast.LENGTH_LONG).show();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Toast.makeText(this,
                "onConnectionFailed():\n" + connectionResult.getErrorMessage(),
                Toast.LENGTH_LONG).show();
    }
}


layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_margin="20dp"
    tools:context="com.blogspot.android_er.recaptcha.MainActivity" >

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    <Button
        android:id="@+id/request"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Request SafetyNet reCAPTCHA API"/>
    <TextView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

reCAPTCHA Android API announced as part of Google Play Services.

The first SafetyNet reCAPTCHA API announced as part of Google Play Services.



reCAPTCHA Android API is included with Google SafetyNet, which provides services like device attestation and safe browsing to protect mobile apps. Mobile developers can do both the device and user attestations in the same API to mitigate security risks of their apps more efficiently. This adds to the diversity of security protections on Android: Google Play Protect to monitor for potentially harmful applications, device encryption, and regular security updates. Visit the site to learn more about how to integrate with the reCAPTCHA Android API, and keep an eye out for iOS library.

source: Android Developers Blog - Making the Internet safer and faster: Introducing reCAPTCHA Android API

I have tried, please read "Example using SafetyNet reCAPTCHA API in Android App".

Sunday, June 11, 2017

Android System Programming

Android System Programming

Key Features
  • Master Android system-level programming by integrating, customizing, and extending popular open source projects
  • Use Android emulators to explore the true potential of your hardware
  • Master key debugging techniques to create a hassle-free development environment
Book Description
Android system programming involves both hardware and software knowledge to work on system level programming. The developers need to use various techniques to debug the different components in the target devices. With all the challenges, you usually have a deep learning curve to master relevant knowledge in this area. This book will not only give you the key knowledge you need to understand Android system programming, but will also prepare you as you get hands-on with projects and gain debugging skills that you can use in your future projects.

You will start by exploring the basic setup of AOSP, and building and testing an emulator image. In the first project, you will learn how to customize and extend the Android emulator. Then you'll move on to the real challenge―building your own Android system on VirtualBox. You'll see how to debug the init process, resolve the bootloader issue, and enable various hardware interfaces. When you have a complete system, you will learn how to patch and upgrade it through recovery. Throughout the book, you will get to know useful tips on how to integrate and reuse existing open source projects such as LineageOS (CyanogenMod), Android-x86, Xposed, and GApps in your own system.

What you will learn
  • Set up the Android development environment and organize source code repositories
  • Get acquainted with the Android system architecture
  • Build the Android

Thursday, June 8, 2017

Announced at Google I/O: Android support Kotlin officially

Kotlin: Android Support Announced at Google I/O

Kotlin website - https://goo.gl/W6bJJJ
Kotlin and Android documentation - https://goo.gl/NWt6O7

Android announced full support for the Kotlin language at Google I/O along with an increased commitment to both the Java programming language and C++. This video interviewed key stakeholders involved with the decision from both Google and Jetbrains to help understand why this decision was made and what it means to the Android developer community.

Introduction to Kotlin (Google I/O '17)

Life is Great and Everything Will Be Ok, Kotlin is Here (Google I/O '17)
In the first part of this talk, Jake will cover advancing the usage and design patterns of the language for Android development to solve larger problems. In the second part, Christina will share her experience using Kotlin in production, from mistakes to successes, and help you answer questions your team/company might ask about adopting it.

#Kotlin

Sunday, June 4, 2017

Scan Devices IP connected in WiFi network


Example to scan connected devices within the same WiFi network, using InetAddress.isReachable().


package com.blogspot.android_er.androidwireless;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    TextView tvWifiState;
    TextView tvScanning, tvResult;

    ArrayList<InetAddress> inetAddresses;

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

        tvWifiState = (TextView)findViewById(R.id.WifiState);
        tvScanning = (TextView)findViewById(R.id.Scanning);
        tvResult = (TextView)findViewById(R.id.Result);

        //To prevent memory leaks on devices prior to Android N,
        //retrieve WifiManager with
        //getApplicationContext().getSystemService(Context.WIFI_SERVICE),
        //instead of getSystemService(Context.WIFI_SERVICE)
        WifiManager wifiManager =
                (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        tvWifiState.setText(readtvWifiState(wifiManager));

        new ScanTask(tvScanning, tvResult).execute();
    }

    // "android.permission.ACCESS_WIFI_STATE" is needed
    private String readtvWifiState(WifiManager wm){
        String result = "";
        switch (wm.getWifiState()){
            case WifiManager.WIFI_STATE_DISABLED:
                result = "WIFI_STATE_DISABLED";
                break;
            case WifiManager.WIFI_STATE_DISABLING:
                result = "WIFI_STATE_DISABLING";
                break;
            case WifiManager.WIFI_STATE_ENABLED:
                result = "WIFI_STATE_ENABLED";
                break;
            case WifiManager.WIFI_STATE_ENABLING:
                result = "WIFI_STATE_ENABLING";
                break;
            case WifiManager.WIFI_STATE_UNKNOWN:
                result = "WIFI_STATE_UNKNOWN";
                break;
            default:
        }
        return result;
    }

    private class ScanTask extends AsyncTask<Void, String, Void> {

        TextView tvCurrentScanning, tvScanResullt;
        ArrayList<String> canonicalHostNames;

        public ScanTask(TextView tvCurrentScanning, TextView tvScanResullt) {
            this.tvCurrentScanning = tvCurrentScanning;
            this.tvScanResullt = tvScanResullt;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            tvCurrentScanning.setText("Finished.");
            tvScanResullt.setText("");
            for(int i = 0; i < inetAddresses.size(); i++){
                tvScanResullt.append(canonicalHostNames.get(i) + "\n");
            }
        }

        @Override
        protected Void doInBackground(Void... voids) {
            scanInetAddresses();
            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            tvCurrentScanning.setText(values[0]);
        }

        private void scanInetAddresses(){
            //May be you have to adjust the timeout
            final int timeout = 500;

            if(inetAddresses == null){
                inetAddresses = new ArrayList<>();
            }
            inetAddresses.clear();

            if(canonicalHostNames == null){
                canonicalHostNames = new ArrayList<>();
            }
            canonicalHostNames.clear();

            //For demonstration, scan 192.168.1.xxx only
            byte[] ip = {(byte) 192, (byte) 168, (byte) 1, 0};
            for (int j = 0; j < 255; j++) {
                ip[3] = (byte) j;
                try {
                    InetAddress checkAddress = InetAddress.getByAddress(ip);
                    publishProgress(checkAddress.getCanonicalHostName());
                    if (checkAddress.isReachable(timeout)) {
                        inetAddresses.add(checkAddress);
                        canonicalHostNames.add(checkAddress.getCanonicalHostName());
                    }
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                    publishProgress(e.getMessage());
                } catch (IOException e) {
                    e.printStackTrace();
                    publishProgress(e.getMessage());
                }
            }
        }
    }
}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidwireless.MainActivity" >

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/WifiState"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Scanning: "/>
        <TextView
            android:id="@+id/Scanning"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textStyle="italic"/>
    </LinearLayout>

    <TextView
        android:id="@+id/Result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"/>

</LinearLayout>


uses-permission of "android.permission.ACCESS_WIFI_STATE" and "android.permission.INTERNET" are needed.

Saturday, June 3, 2017

Get ssid of connected network and my IP address

Android example code to get ssid and IP address, using WifiInfo.

Tested on Samsung Galaxy A9, running Android 6.0.1.

Wifi enabled and connected

Wifi disabled

MainActivity.java
package com.blogspot.android_er.androidwireless;

import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.format.Formatter;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView tvWifiEnabled, tvWifiState, tvWifiInfo, tvSSID,
                tvRssi, tvIP, tvFormattedIP1, tvFormattedIP2;

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

        tvWifiEnabled = (TextView)findViewById(R.id.WifiEnabled);
        tvWifiState = (TextView)findViewById(R.id.WifiState);
        tvWifiInfo = (TextView)findViewById(R.id.WifiInfo);
        tvSSID = (TextView)findViewById(R.id.SSID);
        tvRssi = (TextView)findViewById(R.id.Rssi);
        tvIP = (TextView)findViewById(R.id.IP);
        tvFormattedIP1 = (TextView)findViewById(R.id.FormattedIP1);
        tvFormattedIP2 = (TextView)findViewById(R.id.FormattedIP2);

        //To prevent memory leaks on devices prior to Android N,
        //retrieve WifiManager with
        //getApplicationContext().getSystemService(Context.WIFI_SERVICE),
        //instead of getSystemService(Context.WIFI_SERVICE)
        WifiManager wifiManager =
                (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        tvWifiEnabled.setText("isWifiEnabled(): " + wifiManager.isWifiEnabled());
        tvWifiState.setText(readtvWifiState(wifiManager));

        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        if(wifiInfo == null){
            tvWifiInfo.setText("wifiInfo == null !!!");
        }else{
            tvWifiInfo.setText(wifiInfo.toString());
            tvSSID.setText("SSID: " + wifiInfo.getSSID());
            tvRssi.setText("Rssi: " + wifiInfo.getRssi() + " dBm");

            int ipAddress = wifiInfo.getIpAddress();
            /*
            Formatter.formatIpAddress() was deprecated in API level 12.
            This method does not support IPv6 addresses.
             */
            String FormatedIpAddress = Formatter.formatIpAddress(ipAddress);
            String FormatedIpAddress2 = String.format("%d.%d.%d.%d",
                    (ipAddress & 0xff),
                    (ipAddress >> 8 & 0xff),
                    (ipAddress >> 16 & 0xff),
                    (ipAddress >> 24 & 0xff));
            tvIP.setText("IP: " + wifiInfo.getIpAddress());
            tvFormattedIP1.setText("" + FormatedIpAddress);
            tvFormattedIP2.setText("" + FormatedIpAddress2);
        }

    }

    // "android.permission.ACCESS_WIFI_STATE" is needed
    private String readtvWifiState(WifiManager wm){
        String result = "";
        switch (wm.getWifiState()){
            case WifiManager.WIFI_STATE_DISABLED:
                result = "WIFI_STATE_DISABLED";
                break;
            case WifiManager.WIFI_STATE_DISABLING:
                result = "WIFI_STATE_DISABLING";
                break;
            case WifiManager.WIFI_STATE_ENABLED:
                result = "WIFI_STATE_ENABLED";
                break;
            case WifiManager.WIFI_STATE_ENABLING:
                result = "WIFI_STATE_ENABLING";
                break;
            case WifiManager.WIFI_STATE_UNKNOWN:
                result = "WIFI_STATE_UNKNOWN";
                break;
            default:
        }
        return result;
    }
}


layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidwireless.MainActivity" >

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/WifiEnabled"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/WifiState"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/WifiInfo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="italic"/>
    <TextView
        android:id="@+id/SSID"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:textColor="#FF0000"/>
    <TextView
        android:id="@+id/Rssi"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#00FF00"/>
    <TextView
        android:id="@+id/comment1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="get IP Address:"/>
    <TextView
        android:id="@+id/IP"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="italic"
        android:textColor="#0000FF"/>
    <TextView
        android:id="@+id/FormattedIP1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="italic"
        android:textColor="#0000FF"/>
    <TextView
        android:id="@+id/FormattedIP2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="italic"
        android:textColor="#0000FF"/>

</LinearLayout>


uses-permission of "android.permission.ACCESS_WIFI_STATE" is needed in AndroidManifest.xml.

Remark on MAC:
Please take a look on the captured screen; the MAC address is 02:00:00:00:00:00.

Refer to Android 6.0 Changes - Access to Hardware Identifier:
To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.

Friday, June 2, 2017

Android Cookbook: Problems and Solutions for Android Developers 2nd Edition, Covers Android Nougat 7.0

Android Cookbook: Problems and Solutions for Android Developers

Jump in and build working Android apps with the help of more than 230 tested recipes. The second edition of this acclaimed cookbook includes recipes for working with user interfaces, multitouch gestures, location awareness, web services, and specific device features such as the phone, camera, and accelerometer. You also get useful info on packaging your app for the Google Play Market.

Ideal for developers familiar with Java, Android basics, and the Java SE API, this book features recipes contributed by more than three dozen Android developers. Each recipe provides a clear solution and sample code you can use in your project right away. Among numerous topics, this cookbook helps you:

  • Get started with the tooling you need for developing and testing Android apps
  • Create layouts with Android’s UI controls, graphical services, and pop-up mechanisms
  • Build location-aware services on Google Maps and OpenStreetMap
  • Control aspects of Android’s music, video, and other multimedia capabilities
  • Work with accelerometers and other Android sensors
  • Use various gaming and animation frameworks
  • Store and retrieve persistent data in files and embedded databases
  • Access RESTful web services with JSON and other formats
  • Test and troubleshoot individual components and your entire application


Wednesday, May 31, 2017

Andy Rubin, creator of Android, debuts his new Essential Phone


Andy Rubin helped create the modern mobile era by steering Google’s Android efforts for nearly a decade. He also built Google’s mobile and digital content businesses, and started Google’s robotics efforts via the acquisitions of Boston Dynamics, Schaft and others. Rubin is the founder and CEO of Playground Global, a venture studio that provides investment, mentorship and resources to tech startups working in the area of hardware and AI. Now, he's launching a new company and phone, called Essential.


Tuesday, May 23, 2017

Programming Kotlin

Familiarize yourself with all of Kotlin's features with this in-depth guide

Programming Kotlin

About This Book
  • Get a thorough introduction to Kotlin
  • Learn to use Java code alongside Kotlin without any hiccups
  • Get a complete overview of null safety, Generics, and many more interesting features
Who This Book Is For
The book is for existing Java developers who want to learn more about an alternative JVM language. If you want to see what Kotlin has to offer, this book is ideal for you.

What You Will Learn
  • Use new features to write structured and readable object-oriented code
  • Find out how to use lambdas and higher order functions to write clean, reusable, and simple code
  • Write unit tests and integrate Kotlin tests with Java code in a transitioning code base
  • Write real-world production code in Kotlin in the style of microservices
  • Leverage Kotlin's extensions to the Java collections library
  • Use destructuring expressions and find out how to write your own
  • Write code that avoids null pointer errors and see how Java-nullable code can integrate with features in a Kotlin codebase
  • Discover how to write functions in Kotlin, see the new features available, and extend existing libraries
  • Learn to write an algebraic data types and figure out when they should be used
In Detail
Kotlin has been making waves ever since it was open sourced by JetBrains in 2011; it has been praised by developers across the world and is already being adopted by companies. This book provides a detailed introduction to Kotlin that shows you all its features and will enable you to write Kotlin code to production.

We start with the basics: get you familiar with running Kotlin code, setting up, tools, and instructions that you can use to write basic programs. Next, we cover object oriented code: functions, lambdas, and properties - all while using Kotlin's new features.

Then, we move on to null safety aspects and type parameterization. We show you how to destructure expressions and even write your own. We also take you through important topics like testing, concurrency, microservices, and a whole lot more. By the end of this book you will be able to compose different services and build your own applications.

Style and approach
An easy to follow guide that covers the full set of features in Kotlin programming.

Kotlin for Android Developers: Learn Kotlin the easy way while developing an Android App

Kotlin for Android Developers: Learn Kotlin the easy way while developing an Android App

Are you tired of using an ancient, inexpressive and unsafe language to develop your Android apps? Do you cry out loud every time you see a Null Pointer Exception in your bug tracker? Then Kotlin is your solution! A language specifically created for Java developers, easy to learn, expressive, null safe and really intuitive. Your productivity will boost and your apps will become more robust. Learn Kotlin the easy way by example and discover the tricks that will make coding easier. In this book, I'll be creating an Android app from ground using Kotlin as the main language. The idea is to learn the language by example, instead of following a typical structure. I'll be stopping to explain the most interesting concepts and ideas about Kotlin, comparing it with Java 7. This way, you can see what the differences are and which parts of the language will help you speed up your work. This book is not meant to be a language reference, but a tool for Android developers to learn Kotlin and be able to continue with their own projects by themselves. I'll be solving many of the typical problems we have to face in our daily lives by making use of the language expressiveness and some other really interesting tools and libraries. The book is very practical, so it is recommended to follow the examples and the code in front of a computer and try everything it's suggested. You could, however, take a first read to get a broad idea and then dive into practice.

Monday, May 22, 2017

Download and install Android Studio 3.0 Canary 1 on Ubuntu 17.04

This post show how to Download and install Android Studio 3.0 Canary 1 on 64-bit Ubuntu 17.04, over Windows 10/Oracle VirtualBox,


Firstly, Install Ubuntu 17.04 on Windows 10/Oracle VirtualBox.

Before install Android Studio on 64-bit Ubuntu 17.04, install 32-bit libraries:
$ sudo dpkg --add-architecture i386
$ sudo apt-get update
$ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386

(details refer to Fix "Unable to run mksdcard SDK tool" when install Android Studio on Linux)

Download Android Studio 3.0 Canary, visit https://developer.android.com/studio/preview/index.html
Unpack the ZIP file, to any directory you want.
Open a terminal, navigate into <android-studio>/bin/ and execute studio.sh

This video show how:


Setup for debugging on real device:

On Ubuntu/Linux, to debug on real device, you have to set up your system to detect your device.
(referencec: https://developer.android.com/studio/run/device.html#setting-up)

Edit/Create /etc/udev/rules.d/51-android.rules
$ sudo nano /etc/udev/rules.d/51-android.rules

Add the code:
SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", MODE="0666", GROUP="plugdev"

Where 00b4 is the vendor ID, replace it to match your device. For my Samsung device, replace with 04e8.

You can check your USB vendor ID here: https://developer.android.com/studio/run/device.html#VendorIds.

or try to find it using lsusb command.



Kotlin programming language, Now official on Android. It's a dummy Hello World of Kotlin language, created in Android Studio 3.0 Canary 1.



Get USB devices' vendor ID and product ID on Linux, using lsusb command

To get the vendor ID/product ID of attached USB devices in Linux, you can use the command lsusb.

This video show how to, tested on Ubuntu 17.05 over Windows 10/Oracle VirtualBox 5.1




reference: Ubuntu Manual - lsusb



Saturday, May 20, 2017

Install Ubuntu 17.04 on Windows 10/Oracle VirtualBox


This video show how to install Install Ubuntu 17.04 on Windows 10 with Oracle VirtualBox 5.1. Basically, the steps is very straightforward.


But...after setup, I cannot google in the browser. And it was found some sites can be reached, some sites cannot. Even cannot run apt-get update. After some searching, I found it's related to DNSSEC in /etc/systemd/resolved.conf.

To fix it, edit the file /etc/systemd/resolved.conf:
$ sudo nano /etc/systemd/resolved.conf

uncomment #DNSSEC=allow-downgrade and replace allow-downgrade with off .


Save and Exit
Reboot

This video show how:


reference:
This page have a good explanation: Hectic Geek - Websites Not Loading (dns issue) After Installing Ubuntu 17.04? [fix]

Install Guest Addition:
The Guest Additions are designed to be installed inside a virtual machine after the guest operating system has been installed. They consist of device drivers and system applications that optimize the guest operating system for better performance and usability. (https://www.virtualbox.org/manual/ch04.html)

It's strongly recommended to install Guest Addition. In case of Ubuntu 17.04, simple click Devices on VirtualBox menu bar, and click Insert Guest Addition CD image...



Share folder between host Windows 10 and guest Ubuntu 17.04:
Starting with version 4.0, VirtualBox can mount shared folders automatically, at your option (link). This video show how to set auto-mount share folder in host Windows 10, and also add user to vboxsf group in guest Ubuntu to access the share folder. (Guest Addition is need)


Friday, May 19, 2017

Fix "Unable to run mksdcard SDK tool" when install Android Studio on Linux

If you install Android Studio on 64-bit Linux and reported with error:
Unable to run mksdcard SDK tool



Most probably some 32-bit libraries are missed.

If you are running a 64-bit version of Ubuntu, you need to install some 32-bit libraries with the following command:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 lib32bz2-1.0

If you are running 64-bit Fedora, the command is:
sudo yum install zlib.i686 ncurses-libs.i686 bzip2-libs.i686

reference: Troubleshoot Android Studio - Linux libraries


When I try to install the 32-bit libraries on Ubuntu 16.04.2 LTS (64-bit) on VirtualBox with the command:

$ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 lib32bz2-1.0

The errors reported:
E: Unable to locate package lib32bz2-1.0
E: Couldn't find any package by glob 'lib32bz2-1.0'
E: Couldn't find any package by regex 'lib32bz2-1.0'

To fixed it, add 32 bit architecture with the command:
$ sudo dpkg --add-architecture i386
$ sudo apt-get update

Re-install with the command 
$ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386


Done:


Android Studio 3.0 available on canary release channel

Just in time for Google I/O 2017, Android Studio 3.0 is available to download on  canary release channel.

To accelerate your development flow, Android Studio 3.0 includes three major features: a new suite of app performance profiling tools to quickly diagnose performance issues, support for the Kotlin programming language, and increased Gradle build speeds for large sized app projects. Android Studio 3.0 also tightly integrates with Android platform development with these additional key features: support for Instant App development, inclusion of the Google Play Store in the Android O emulator system images, and new wizards for Android O development. Overall, this first canary release of Android Studio 3.0 has 20+ new features.



Please refer to the announcement blogpost "Android Studio 3.0 Canary 1" for more details.