TimePicker in Android Tutorial/Example

In this tutorial, I will show you how to implement TimePicker and TimePickerDialog in Android. TimePicker is a widget in Android which allows you to select a time in terms of hour and minutes. TimePickerDialog is a dialog which allows to select the time and provides the selected time in an override method.

layout file including text-view where selected time from time picker dialog is shown, a button on which click a Timepickerdialog will be shown and a time-picker widget.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.coderzpassion.timepicker.MainActivity">

    <TimePicker
        android:id="@+id/timepick"
        android:layout_alignParentTop="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </TimePicker>

    <TextView
        android:id="@+id/settime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="dcdc"
        android:layout_above="@+id/bt_settime"
        android:layout_centerHorizontal="true"
        />

    <Button
        android:id="@+id/bt_settime"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="Set Time"
        android:layout_alignParentBottom="true"/>

</RelativeLayout>

MainActivity.java 

package com.coderzpassion.timepicker;

import android.app.TimePickerDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TimePicker;

import java.util.Calendar;

public class MainActivity extends AppCompatActivity {

    TextView settime;
    Button bt_settime;
    Calendar calendar;
    int hour,min;
    TimePicker picker;

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

        settime=(TextView)findViewById(R.id.settime);
        bt_settime=(Button)findViewById(R.id.bt_settime);
        bt_settime.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                openTimePickerDialog();
            }
        });

        picker=(TimePicker)findViewById(R.id.timepick);
        setCurrentTimeFirstTime();
        picker.setIs24HourView(false);
    }

    //function to set current time to textview
    private void setCurrentTimeFirstTime()
    {
        calendar=Calendar.getInstance();
         hour=calendar.get(Calendar.HOUR_OF_DAY);
         min=calendar.get(Calendar.MINUTE);
        settime.setText(updateTime(hour,min));
    }

    //function to show timepicker dialog
    private void openTimePickerDialog()
    {
        TimePickerDialog dialog=new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {
            @Override
            public void onTimeSet(TimePicker timePicker, int hour, int min) {
                //set selected time to textview
                settime.setText(updateTime(hour,min));

            }
        },hour,min,false);

        dialog.show();
    }

    // function to get am and pm from time
    private String updateTime(int hours, int mins) {

        String timeSet = "";
        if (hours > 12) {
            hours -= 12;
            timeSet = "PM";
        } else if (hours == 0) {
            hours += 12;
            timeSet = "AM";
        } else if (hours == 12)
            timeSet = "PM";
        else
            timeSet = "AM";


        String minutes = "";
        if (mins < 10)
            minutes = "0" + mins;
        else
            minutes = String.valueOf(mins);

        // Append in a StringBuilder
        String aTime = new StringBuilder().append(hours).append(':')
                .append(minutes).append(" ").append(timeSet).toString();

        return aTime;
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.coderzpassion.timepicker">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "26.0.0"
    defaultConfig {
        applicationId "com.coderzpassion.timepicker"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    implementation 'com.android.support:appcompat-v7:25.4.0'
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}

Output

timepickerdialogexample    timepickerexample

What is the use of Handler in Android

When an android application is launched the main thread is automatically created. This thread is also called UI thread. This main thread is responsible for everything related to UI i.e drawing the views, dispatching various events and handling the clicks and updating the views. If we perform heavy operations or long running operations UI thread gets blocked and if UI threads blocks for 5 secs or more Android ANR dialog will appear i.e Application not responding.

Handler is a thread which runs on Main UI thread. Handler allows to schedule or repeats the Task at a given interval of time. Handler provides us a way to communicate with the main Thread.

The handler can be used to schedule messages or runnable to executed at some point in the future.

Handler provides us with various methods to execute or to queue the tasks.

Main methods which are used as Follows:-

  1. post(Runnable).
  2. postAtTime(Runnable,long).
  3. postDelayed(Runnable,long).

In Below code, we download the Bitmap in Background thread and then set on Image view in Main Thread

Thread thread=new Thread(new Runnable() {
          @Override
          public void run() {
           // get Bitmap from url in background
             final Bitmap b=getBitmapFromNetwork();

             // setBitmap in UI thread
              profileImage.post(new Runnable() {
                  @Override
                  public void run() {
                      profileImage.setImageBitmap(b);
                  }
              });
            // set Bitmap at particular time 
              new Handler().postAtTime(new Runnable() {
                  @Override
                  public void run() {
                      profileImage.setImageBitmap(b);
                  }
              },SystemClock.uptimeMillis()+1000);

              // set Bitmap after some Delay
              new Handler().postDelayed(new Runnable() {
                  @Override
                  public void run() {
                      profileImage.setImageBitmap(b);
                  }
              },1000);

          }
      });
     thread.start();

The handler can also be used to send Messages to a class or between different activities. This can be as an event notifier or triggers to perform some actions.

Following ways or methods are used to pass messages to Handler.

  1. sendEmptyMessage(int).
  2. sendEmptyMessageAtTime(int,long).
  3. sendEmptyMessageDelayed(int,long).
  4. sendMessage(Message).
  5. sendMessageAtTime(Message,long).
  6. sendMessageDelayed(Message,long).

Let’s see how they work with an example in Same Class.

// on click of a button I am passing int value in sendEmptyMessage to the handler.

sample.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View view) {               
           handler.sendEmptyMessage(0);
           }
       });

the handler will catch the int value in what variable of Message class and we can perform something depending upon the value of what.

handler =new Handler()
        {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Toast.makeText(MainActivity.this,""+msg.what,Toast.LENGTH_SHORT).show();

                if(msg.what==0)
                {
                    //perform something
                }
                if(msg.what==1)
                {
                    //do something
                }
                else
                {
                    // do something else
                }
            }
        };

// on click of Button i am passing a Bundle object to Message class object and similarly, we can pass a custom object also. similarly, sendMessageAtTime(msg,  uptime) and sendMessageDelayed(msg, delay) can be used to deliver message object at the particular time and after some delay in milliseconds.

sample.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {               
              Message message=new Message();
              Bundle b=new Bundle();
              b.putString("name","abc");
              message.setData(b);
              handler.sendMessage(message);
             }
      });

and handler will receive the Bundle object from Message object and we can perform tasks accordingly.

handler =new Handler()
      {
          @Override
          public void handleMessage(Message msg) {
              super.handleMessage(msg);
              Bundle b=msg.getData();
              Toast.makeText(MainActivity.this,""+b.get("name"),Toast.LENGTH_SHORT).show();
          }
      };

// send messages to the Handler in other Activity(SecondActivity.java) from another activity(MainActivity.java).

SecondActivity.java // the activity containing handler as inner class

/**
 * Created by coderzpassion on 30/06/17.
 */

public class SecondActivity extends AppCompatActivity {

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

    class MyHandler extends Handler
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Bundle b=msg.getData();
            Log.e("value",""+b.get("name"));
        }
    }

}

MainActivity.java // the activity to call handler

public class MainActivity extends AppCompatActivity {

    TextView sample;
    ImageView profileImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sample=(TextView)findViewById(R.id.sample);
        sample.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SecondActivity handler=new SecondActivity();
                SecondActivity.MyHandler handler1=handler. new MyHandler();
                Message message=new Message();
                Bundle b=new Bundle();
                b.putString("name","abc");
                message.setData(b);
                handler1.sendMessage(message);
            }
        });
    }
}

Full code

MainActivity.java

public class MainActivity extends AppCompatActivity {

    TextView sample;
    ImageView profileImage;
    Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sample=(TextView)findViewById(R.id.sample);
        sample.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SecondActivity handler=new SecondActivity();
                SecondActivity.MyHandler handler1=handler. new MyHandler();
                Message message=new Message();
                Bundle b=new Bundle();
                b.putString("name","abc");
                message.setData(b);
                handler1.sendMessage(message);

//            handler.sendEmptyMessage(0);
            }
        });

      handler =new Handler()
        {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
//                Toast.makeText(MainActivity.this,""+msg.what,Toast.LENGTH_SHORT).show();
//
//                if(msg.what==0)
//                {
//                    //perform something
//                }
//                if(msg.what==1)
//                {
//                    //do something
//                }
//                else
//                {
//                    // do something else
//                }
                Bundle b=msg.getData();
                Toast.makeText(MainActivity.this,""+b.get("name"),Toast.LENGTH_SHORT).show();
            }
        };






//        Thread thread=new Thread(new Runnable() {
//            @Override
//            public void run() {
//             // get Bitmap from url in background
//               final Bitmap b=getBitmapFromNetwork();
//
//               // setBitmap in UI thread
//                profileImage.post(new Runnable() {
//                    @Override
//                    public void run() {
//                        profileImage.setImageBitmap(b);
//                    }
//                });
//              // set Bitmap at particular time
//                new Handler().postAtTime(new Runnable() {
//                    @Override
//                    public void run() {
//                        profileImage.setImageBitmap(b);
//                    }
//                }, SystemClock.uptimeMillis()+1000);
//
//                // set Bitmap after some Delay
//                new Handler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        profileImage.setImageBitmap(b);
//                    }
//                },1000);
//
//            }
//        });
//       thread.start();
    }
}

SecondActivity.java

public class SecondActivity extends AppCompatActivity {


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

    class MyHandler extends Handler
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Bundle b=msg.getData();
            Log.e("value",""+b.get("name"));
        }
    }

}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.coderzpassion.handlersample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity"/>
    </application>

</manifest>

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "26.0.0"
    defaultConfig {
        applicationId "com.coderzpassion.handlersample"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    implementation 'com.android.support:appcompat-v7:25.4.0'
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}

Output

handlerandroidexample   handlerandroidtutorial

How to implement Service in Android

Service is an application component that can perform long-running operations in the background like for downloading files or whether to check internet calls or something else similar. A service does not have any UI so it can be called from other Android components and it can be in running state even if we switch applications.

A service has high priority than invisible activity or background activity but less priority than foreground Activity.

To create Service with priority equal to Foreground Activity we can create Foreground Service.

A service can be implemented in two ways:

  1. startService();
  2. bindService();

Let’s understand the behavior in startService()

When service is started using startService(intent) then the onCreate() method of service class will be called and then onStartCommand() method of Service will be called. Once the Service is running then calling startService() will call onStartCommand() again. So if this case can happen, then program onStartCommand accordingly.

In onStarComman() int is returned which describes the service restart behavior as follows:-

  1. Service.START_STICKY – Service is restarted if it gets terminated by the system in case of low resources.
  2. Service.START_NOT_STICKY – if this int flag is used service is not restarted. these are used for services which are called again or periodically.
  3. Service.START_REDELIVER_INTENT – if this int flag is used service is restarted and intent is re-delivered. it is similar to START_STICKY.

To stop a Service () call stopService() or stopSelf().

Let’s understand the behavior in bindService().

When bindService(Intent, ServiceConnection, Flag)  is called then the onBind() method of service is called and it returns the Binder object in onServiceConnection onServiceConnected() and when service is disconnected then onServicedisconnected method of ServiceConnection is called.

First Define a Service class as Follows-:

Service class to display current time, it will display toast with startService() and print timestamp with bindService();

BoundService.java

public class BoundService extends Service {
    private static String LOG_TAG = "BoundService";
    private IBinder mBinder = new MyBinder();

    @Override
    public void onCreate() {
        super.onCreate();
        Log.v(LOG_TAG, "in onCreate");
        Toast.makeText(getApplicationContext(),""+getTimestamp(),Toast.LENGTH_LONG).show();
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.v(LOG_TAG, "in onBind");
        return mBinder;
    }

    @Override
    public void onRebind(Intent intent) {
        Log.v(LOG_TAG, "in onRebind");
        super.onRebind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.v(LOG_TAG, "in onUnbind");
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.v(LOG_TAG, "in onDestroy");

    }

    public String getTimestamp() {
        long elapsedMillis = System.currentTimeMillis();
        SimpleDateFormat format=new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
        Date date=new Date(elapsedMillis);

        return format.format(date);
    }

    public class MyBinder extends Binder {
        BoundService getService() {
            return BoundService.this;
        }
    }

}

Declare the Service in AndroidManifest.xml

<service android:name=".BoundService" >
       </service>

MainActivity.java as activity class

public class MainActivity extends AppCompatActivity {
    BoundService mBoundService;
    boolean mServiceBound = false;

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


        final TextView timestampText = (TextView) findViewById(R.id.timestamp_text);
        Button printTimestampButton = (Button) findViewById(R.id.print_timestamp);
        Button stopServiceButon = (Button) findViewById(R.id.stop_service);
        printTimestampButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mServiceBound) {
                    timestampText.setText(mBoundService.getTimestamp());
                }
            }
        });

        stopServiceButon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mServiceBound) {
                    unbindService(mServiceConnection);
                    mServiceBound = false;
                }
                Intent intent = new Intent(MainActivity.this,
                        BoundService.class);
                stopService(intent);
            }
        });

    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, BoundService.class);
        startService(intent);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mServiceBound) {
            unbindService(mServiceConnection);
            mServiceBound = false;
        }
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mServiceBound = false;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            BoundService.MyBinder myBinder = (BoundService.MyBinder) service;
            mBoundService = myBinder.getService();
            mServiceBound = true;
        }
    };
}

it will display fist time from the onCreate method of service which will be called by startService() and print timestamp on click of a button with the help of bindService() method.

// layout for mainActivity

activity_main.xml

<RelativeLayout 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:background="#FFFFFF"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
     >
    <Button
        android:id="@+id/print_timestamp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="130dp"
        android:text="Print Timestamp" />

    <TextView
        android:id="@+id/timestamp_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/print_timestamp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="120dp"
        android:text=""
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <Button
        android:id="@+id/stop_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/print_timestamp"
        android:layout_centerHorizontal="true"
        android:text="Stop Service" />

</RelativeLayout>

 

Output

servicesample    servicetimestamp

How to implement BroadcastReceiver in Android

Broadcast Receiver is an Android component which allows the users to register for an event and triggers when the event happens. A receiver can be registered for pre-defined Android actions or custom actions.

To implement the Broadcast Receiver in Android Application:

  1. Define a Broadcast Register.(can be done in two ways i.e one is locally in Activity class and second is Define Custom Broadcast as a class)
  2. Register the receiver for particular events.(can be done in two ways i.e one is to register receiver in an activity and other is register receiver in AndroidManifest file)
  3. The receiver gets triggered once the event happens or when a custom broadcast is sent.

Note: If we register the receiver in AndroidManifest.xml file it will also trigger if the application is killed/ not alive but if we register the receiver in Activity it will only till the application is live.

We can define the receiver locally in a class or can define the Broadcast Receiver class explicitly.

To define the broadcast receiver explicitly.

I have defined the class as MyBroadcastReceiver and showed a toast in the onReceive method.

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"Broadcast Received",Toast.LENGTH_SHORT).show();
    }
}

To define the Broadcast receiver in Activity class.

public class MainActivity extends AppCompatActivity {

    BroadcastReceiver receiver;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        receiver=new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context,"Broadcast Received in Activity called ",Toast.LENGTH_SHORT).show();
            }
        };
    }
}

 To register a Receiver in AndroidManifest.xml file

<receiver android:name=".MyBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
            </intent-filter>
        </receiver>

 To register a Receiver in Activity class

to register locally defined receiver.

// to register local receiver
  filter = new IntentFilter();
  // specify the action to which receiver will listen
  filter.addAction("com.local.receiver");
  registerReceiver(receiver,filter);

to register custom receiver.

//to Register custom Broadcast Receiver defined in separate class
       MyBroadcastReceiver myBroadcastReceiver=new MyBroadcastReceiver();
       IntentFilter filter1=new IntentFilter();
       filter1.addAction("Intent.ACTION_POWER_CONNECTED");
       registerReceiver(myBroadcastReceiver,filter1);

Don’t forget to unregister the receiver if not needed.

@Override
   protected void onDestroy() {
       super.onDestroy();
       if(receiver!=null)
       {
           unregisterReceiver(receiver);
       }
   }

Now in my Application, i registered two receiver’s one is local with the custom action and other is registered in AndroidManifest file with Action power connected which will trigger once the device is connected to power.

Now Full Code:-

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.coderzpassion.broadcastsample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".MyBroadcastReceiver">
            <intent-filter>
                <action android:name="Intent.ACTION_POWER_CONNECTED"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    BroadcastReceiver receiver;
    IntentFilter filter;
    Button sendbroadcast;

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

        receiver=new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context,"Broadcast Received in Activity called",Toast.LENGTH_SHORT).show();
            }
        };

        // to register local receiver
        filter = new IntentFilter();
        // specify the action to which receiver will listen
        filter.addAction("com.local.receiver");
        registerReceiver(receiver,filter);

        sendbroadcast=(Button)findViewById(R.id.sendbroadcast);
        sendbroadcast.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent("com.local.receiver");
                sendBroadcast(intent);
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(receiver!=null)
        {
            unregisterReceiver(receiver);
        }
    }
}

//layout for above activity

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.coderzpassion.broadcastsample.MainActivity">

    <Button
        android:id="@+id/sendbroadcast"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send BroadCast!"
        android:layout_centerInParent="true" />

</RelativeLayout>

MyBroadcastReceiver.java

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"Broadcast Received Device is connected to Power",Toast.LENGTH_SHORT).show();
    }
}

Final Results

broadcastreceiver   broadcastreceived

 

Saving and Retrieving Data from Firebase Android Part one

In the last tutorial, I described how to sign up and sign in the user at Firebase. In this tutorial, I am going to describe how to save and retrieve the data at Firebase using Android.

If you are not Aware of Firebase Please refer here

if you want to learn about sign up and sign in users At Firebase refer my last tutorial here

So, Let’s Start:-

  1. Create an Activity to sign up and sign in the user.
  2. Create an Activity to save the user details at Firebase.
  3. Create an Activity to retrieve the data from Firebase and show in ListView.

Note: Please follow here to get JSON file and copy at Module’s root path and add the dependency and plugin.

Add the following dependencies to your module build.gradle

compile 'com.google.firebase:firebase-auth:9.0.0'
compile 'com.google.firebase:firebase-database:9.0.0'

create a layout to signup and sign the user.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
   >

    <LinearLayout
        android:id="@+id/layout_email_password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:orientation="vertical">

        <EditText
            android:id="@+id/field_email"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:gravity="center_horizontal"
            android:hint="Enter your mail"
            android:inputType="textEmailAddress"
            android:maxLines="1" />

        <EditText
            android:id="@+id/field_password"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:gravity="center_horizontal"
            android:hint="Enter your password"
            android:inputType="textPassword"
            android:maxLines="1" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/layout_buttons"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/layout_email_password"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal">

        <Button
            android:id="@+id/button_sign_in"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="Sign In" />


        <Button
            android:id="@+id/button_sign_up"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="Sign Up" />

    </LinearLayout>


</RelativeLayout>

MainActivity.java for User sign up, sign in and check if the user already signed in then show DashboardActivty.

package com.coderzpassion.firebasesample;

import android.app.ProgressDialog;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private DatabaseReference mDatabase;
    private FirebaseAuth mAuth;

    private EditText mEmailField;
    private EditText mPasswordField;
    private Button mSignInButton;
    private Button mSignUpButton;

    private ProgressDialog mProgressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDatabase = FirebaseDatabase.getInstance().getReference();
        mAuth = FirebaseAuth.getInstance();

        // Views
        mEmailField = (EditText) findViewById(R.id.field_email);
        mPasswordField = (EditText) findViewById(R.id.field_password);
        mSignInButton = (Button) findViewById(R.id.button_sign_in);
        mSignUpButton = (Button) findViewById(R.id.button_sign_up);

        // Click listeners
        mSignInButton.setOnClickListener(this);
        mSignUpButton.setOnClickListener(this);

        // check if user is signed in then start dashboardactivity
        if(mAuth.getCurrentUser()!=null)
        {
            Intent intent=new Intent(MainActivity.this,DashBoardActivity.class);
            startActivity(intent);
            finish();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_sign_in:
                signIn();
                break;
            case R.id.button_sign_up:
                signUp();
                break;
        }

    }
    
    // to validate the form is user has filled the required fields
    private boolean validateForm() {
        boolean result = true;
        if (TextUtils.isEmpty(mEmailField.getText().toString())) {
            mEmailField.setError("Required");
            result = false;
        } else {
            mEmailField.setError(null);
        }

        if (TextUtils.isEmpty(mPasswordField.getText().toString())) {
            mPasswordField.setError("Required");
            result = false;
        } else {
            mPasswordField.setError(null);
        }

        return result;
    }

    private void signIn() {
        Log.d("MainActivity", "signIn");
        if (!validateForm()) {
            return;
        }

        showProgressDialog();
        String email = mEmailField.getText().toString();
        String password = mPasswordField.getText().toString();
// to sign in the user at firebase
        mAuth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d("MainActivity", "signIn:onComplete:" + task.isSuccessful());
                        hideProgressDialog();

                        if (task.isSuccessful()) {
                            Intent intent=new Intent(MainActivity.this,DashBoardActivity.class);
                            startActivity(intent);
                            finish();
                        } else {
                            Toast.makeText(MainActivity.this, "Sign In Failed",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    private void signUp() {
        Log.d("MainActivity", "signUp");
        if (!validateForm()) {
            return;
        }

        showProgressDialog();
        String email = mEmailField.getText().toString();
        String password = mPasswordField.getText().toString();
    // to sign up the user at firebase
        mAuth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d("MainActivity", "createUser:onComplete:" + task.isSuccessful());
                        hideProgressDialog();

                        if (task.isSuccessful()) {
                            Toast.makeText(MainActivity.this, "Successful! Please Sign In",
                                    Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(MainActivity.this, "Sign Up Failed",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    public void showProgressDialog() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setCancelable(false);
            mProgressDialog.setMessage("Loading...");
        }

        mProgressDialog.show();
    }

    public void hideProgressDialog() {
        if (mProgressDialog != null && mProgressDialog.isShowing()) {
            mProgressDialog.dismiss();
        }
    }


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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

layout for DashBoardActivity which will be shown to the user once a user is logged in.

activity_dashboard.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/savedetails"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Save Details"/>

    <Button
        android:id="@+id/showusers"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Show Users"/>

</LinearLayout>

DashBoardAcivity

package com.coderzpassion.firebasesample;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

/**
 * Created by coderzpassion on 31/07/16.
 */
public class DashBoardActivity extends AppCompatActivity {

    Button savedetails,getusers;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dashboard);
        savedetails=(Button)findViewById(R.id.savedetails);
        getusers=(Button)findViewById(R.id.showusers);
        
        // to save user details call HomeActivity
        savedetails.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(DashBoardActivity.this,HomeActivity.class);
                startActivity(intent);
            }
        });
       // to get user details call ShowUsers Activity
        getusers.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(DashBoardActivity.this,ShowUsers.class);
                startActivity(intent);
            }
        });
    }
}

Create a Model Class as User.java to save user properties.

package com.coderzpassion.firebasesample.model;

/**
 * Created by coderzpassion on 31/07/16.
 */
public class User {
    private String firstname="";
    private String lastname="";
    private String age="";
    private String email="";

    public User()
    {

    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

create a layout to allow the user to enter first-name, Lastname, age, email and then save at Firebase.

activity_home.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="First Name:"/>
        <EditText
            android:id="@+id/fname"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="Enter your First name"/>

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Last Name:"/>
        <EditText
            android:id="@+id/lname"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="Enter your Last name"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Age:"/>
        <EditText
            android:id="@+id/age"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="Enter your age"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Email:"/>
        <EditText
            android:id="@+id/email"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="Enter your email"/>

    </LinearLayout>

    <Button
        android:id="@+id/save"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Save"/>


</LinearLayout>

HomeActivity.java

package com.coderzpassion.firebasesample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.coderzpassion.firebasesample.model.User;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

/**
 * Created by coderzpassion on 31/07/16.
 */
public class HomeActivity extends AppCompatActivity {

     EditText fname,lname,age,email;
     Button save;

    private DatabaseReference mDatabase;
    private FirebaseAuth mAuth;

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

        mDatabase = FirebaseDatabase.getInstance().getReference();
        mAuth = FirebaseAuth.getInstance();

        fname=(EditText)findViewById(R.id.fname);
        lname=(EditText)findViewById(R.id.lname);
        age=(EditText)findViewById(R.id.age);
        email=(EditText)findViewById(R.id.email);
        save=(Button)findViewById(R.id.save);
        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(validateForm())
                {
                    String frstname=fname.getText().toString().trim();
                    String lstname=lname.getText().toString().trim();
                    String ae=age.getText().toString().trim();
                    String ema=email.getText().toString().trim();
                    // create user object and set all the properties 
                    User user=new User();
                    user.setFirstname(frstname);
                    user.setLastname(lstname);
                    user.setAge(ae);
                    user.setEmail(ema);

                    if(mAuth.getCurrentUser()!=null)
                    {
                        // save the user at UserNode under user UID
                        mDatabase.child("UserNode").child(mAuth.getCurrentUser().getUid()).setValue(user, new DatabaseReference.CompletionListener() {
                            @Override
                            public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                           if(databaseError==null)
                           {
                               Toast.makeText(HomeActivity.this, "Data is saved successfully",
                                       Toast.LENGTH_SHORT).show();
                               finish();
                           }
                            }
                        });
                    }

                }
            }
        });
    }

    // to check if user filled all the required fieds
    public boolean validateForm()
    {
        boolean alldone=true;
        String frstname=fname.getText().toString().trim();
        String lstname=lname.getText().toString().trim();
        String ae=age.getText().toString().trim();
        String ema=email.getText().toString().trim();

        if(TextUtils.isEmpty(frstname))
        {
            fname.setError("Enter your first name");

            return false;
        }else
        {
            alldone=true;
            fname.setError(null);
        }
        if(TextUtils.isEmpty(lstname))
        {
           lname.setError("Enter your last name");
            return false;
        }else
        {
            alldone=true;
            lname.setError(null);
        }
        if(TextUtils.isEmpty(ae))
        {
            age.setError("Enter your Age");
            return false;
        }else
        {
            alldone=true;
            age.setError(null);
        }
        if(TextUtils.isEmpty(ema))
        {
            email.setError("Enter your Email");
            return false;
        }else
        {
            alldone=true;
            email.setError(null);
        }
        return alldone;

    }
}

Now create an Adapter class to show Username and User email and then set it to Listview.

layout for adapter containing two text view one for username and other for user email.

adapter_listing.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="120dp">

   <TextView
       android:id="@+id/user_fullname"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentLeft="true"
       android:textSize="12dp"/>

    <TextView
        android:id="@+id/user_email"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:textSize="12dp"/>


</RelativeLayout>

ListingAdapter.java

private class ListingAdapter extends BaseAdapter {

       Context context;
       LayoutInflater layoutInflater;
       ArrayList<User> users;

       public ListingAdapter(Context con,ArrayList<User> users)
       {
           context=con;
           layoutInflater = LayoutInflater.from(context);
           this.users=users;
       }

       @Override
       public int getCount() {
           return users.size();
       }

       @Override
       public View getView(int position, View convertView, ViewGroup parent) {
           ViewHolder holder;

           if (convertView == null) {
               convertView = layoutInflater.inflate(R.layout.adapter_listing, null, false);
               holder = new ViewHolder();

               holder.fullname = (TextView) convertView.findViewById(R.id.user_fullname);
               holder.email = (TextView) convertView.findViewById(R.id.user_email);
               convertView.setTag(holder);

           } else {
               holder = (ViewHolder) convertView.getTag();
           }

           User user=users.get(position);

           holder.fullname.setText(user.getFirstname()+user.getLastname());
           holder.email.setText(user.getEmail());

           return convertView;
       }

      public class ViewHolder {
           TextView fullname, email;

       }
       @Override
       public Object getItem(int position) {
           return users.get(position);
       }

       @Override
       public long getItemId(int position) {
           return position;
       }
   }

Create a layout for Activity to show users in Listview.

activity_showusers.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/allusers"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </ListView>

</LinearLayout>

ShowUsers.java

package com.coderzpassion.firebasesample;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.coderzpassion.firebasesample.model.User;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;

/**
 * Created by coderzpassion on 31/07/16.
 */
public class ShowUsers extends AppCompatActivity {

    ListView allusers;
    ProgressDialog mProgressDialog;
    DatabaseReference databaseReference= FirebaseDatabase.getInstance().getReference();
    ListingAdapter adapter;
    ArrayList<User> users=new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_showusers);
        allusers=(ListView)findViewById(R.id.allusers);
        adapter=new ListingAdapter(ShowUsers.this,users);
        allusers.setAdapter(adapter);
        getDataFromServer();
    }

    // getting the data from UserNode at Firebase and then adding the users in Arraylist and setting it to Listview
    public void getDataFromServer()
    {
        showProgressDialog();
        databaseReference.child("UserNode").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                if(dataSnapshot.exists())
                {

                    for(DataSnapshot postSnapShot:dataSnapshot.getChildren())
                    {
                        User user=postSnapShot.getValue(User.class);
                        users.add(user);
                        adapter.notifyDataSetChanged();
                    }


                }
                hideProgressDialog();
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                hideProgressDialog();
            }
        });
    }
    private void showProgressDialog() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(ShowUsers.this);
            mProgressDialog.setMessage("Loading...");
            mProgressDialog.setIndeterminate(true);
        }

        mProgressDialog.show();
    }

    private void hideProgressDialog() {
        if (mProgressDialog != null && mProgressDialog.isShowing()) {
            mProgressDialog.dismiss();
        }
    }


    private class ListingAdapter extends BaseAdapter {

        Context context;
        LayoutInflater layoutInflater;
        ArrayList<User> users;

        public ListingAdapter(Context con,ArrayList<User> users)
        {
            context=con;
            layoutInflater = LayoutInflater.from(context);
            this.users=users;
        }

        @Override
        public int getCount() {
            return users.size();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;

            if (convertView == null) {
                convertView = layoutInflater.inflate(R.layout.adapter_listing, null, false);
                holder = new ViewHolder();

                holder.fullname = (TextView) convertView.findViewById(R.id.user_fullname);
                holder.email = (TextView) convertView.findViewById(R.id.user_email);
                convertView.setTag(holder);

            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            User user=users.get(position);

            holder.fullname.setText(user.getFirstname()+user.getLastname());
            holder.email.setText(user.getEmail());

            return convertView;
        }

       public class ViewHolder {
            TextView fullname, email;

        }
        @Override
        public Object getItem(int position) {
            return users.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }
    }
}

For official documentation Refer at Following link:-

saving data at firebase

Output

workingwithfirebase successfulsignin usersavedsuccessfullyatfirebase savinguseratfirebaseandroid  showusersfromfirebaseandroid

Database at Firebase

databaseatfirebase