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