Android room database : CRUD example tutorial

Introduction: 

Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.

Apps that handle non-trivial amounts of structured data can benefit greatly from persisting that data locally. The most common use case is to cache relevant pieces of data. That way, when the device cannot access the network, the user can still browse that content while they are offline. Any user-initiated content changes are then synced to the server after the device is back online.

Because Room takes care of these concerns for you, we highly recommend using Room instead of SQLite.

GITHUB

DEMO

Components: 

There are 3 major components in Room:

  • Database: Contains the database holder and serves as the main access point for the underlying connection to your app’s persisted, relational data.The class that’s annotated with @Database should satisfy the following conditions:
    • Be an abstract class that extends RoomDatabase.
    • Include the list of entities associated with the database within the annotation.
    • Contain an abstract method that has 0 arguments and returns the class that is annotated with @Dao.

    At runtime, you can acquire an instance of Database by calling Room.databaseBuilder() orRoom.inMemoryDatabaseBuilder().

  • Entity: Represents a table within the database.
  • DAO: Contains the methods used for accessing the database.

 

Architecture :

 

 

CRUD Operation

 

 

1)Project setup and dependency:

add  google() to repository in gradle (project) file

[java]
buildscript {

repositories {
<strong> google()</strong>
jcenter()
}
dependencies {
classpath ‘com.android.tools.build:gradle:3.2.0’

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}
[/java]

and

[java]
implementation "android.arch.persistence.room:runtime:1.0.0"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

[/java]

to gradle(app) file

[java]
apply plugin: ‘com.android.application’

android {
compileSdkVersion 28
defaultConfig {
applicationId "com.adndigitalbd.androidroomdatabase"
minSdkVersion 19
targetSdkVersion 28
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’])
implementation ‘com.android.support:appcompat-v7:28.0.0’
implementation ‘com.android.support.constraint:constraint-layout:1.1.3’
implementation ‘com.android.support:design:28.0.0’
testImplementation ‘junit:junit:4.12’
androidTestImplementation ‘com.android.support.test:runner:1.0.2’
androidTestImplementation ‘com.android.support.test.espresso:espresso-core:3.0.2’

<strong> implementation "android.arch.persistence.room:runtime:1.0.0"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

implementation ‘com.android.support:recyclerview-v7:28.0.0’
implementation ‘com.android.support:cardview-v7:28.0.0’

}

[/java]

 

 

2) Create Entity: 

Create a entity/model named User  and create three fields id,name,email where id is auto incremental primary key.

[java]

import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;
import android.support.annotation.ColorInt;

@Entity(tableName = "users")
public class User {

@PrimaryKey(autoGenerate = true)
private int id = 0;

@ColumnInfo(name = "user_name")
private String name;

@ColumnInfo(name = "user_email")
private String email;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}
}
[/java]

3) Create DAO (data access object) class :

Create a DAO interface class named DAO class . Here added insert , get data , update and delete operation methods and queries.

[java]
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.Update;

import com.adndigitalbd.androidroomdatabase.entity.User;

import java.util.List;

@Dao
public interface DaoClass {

/***
* insert data
* @param user
*/
@Insert
public void addUser(User user);

/**
* retrieve all data from users table
* @return
*/
@Query("select * from users")
public List<User> getUsers();

/***
* Delete user from users table
* @param user
*/
@Delete
public void deleteUser(User user);

/***
* Update user from users table
* @param user
*/
@Update
public void updateUser(User user);
}
[/java]

4) Database access class :
Create database abstract class that will extends RoomDatabase , So that we can call this class and method from any where

[java]
import android.arch.persistence.room.Database;
import android.arch.persistence.room.RoomDatabase;

import com.adndigitalbd.androidroomdatabase.entity.User;
import com.adndigitalbd.androidroomdatabase.dao.DaoClass;

@Database(entities = User.class, version = 1)
public abstract class DatabaseClass extends RoomDatabase {
public abstract DaoClass daoClass();
}
[/java]

5 ) Create an Adapter :

Congratulations!! We have done our main task to implement RoomDatabase in our project . We will just call the CRUD methods from an Activity.
We will show our data as a list . We can use recyclerview so that . Now we will create an adapter so that we can display our data with recyclerview .

[java]
import android.app.AlertDialog;
import android.arch.persistence.room.Room;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.adndigitalbd.androidroomdatabase.R;
import com.adndigitalbd.androidroomdatabase.activities.AddUserActivity;
import com.adndigitalbd.androidroomdatabase.activities.MainActivity;
import com.adndigitalbd.androidroomdatabase.database.DatabaseClass;
import com.adndigitalbd.androidroomdatabase.entity.User;
import com.adndigitalbd.androidroomdatabase.globalVariables.GlobalVariables;

import java.util.List;

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserHolder> {

public List<User> userList;
DatabaseClass db;
private Context mContext;

public UserAdapter(List<User> userList) {
this.userList = userList;
}

@NonNull
@Override
public UserAdapter.UserHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {

mContext = parent.getContext();
db = Room.databaseBuilder(parent.getContext(),
DatabaseClass.class, "myDatabase").allowMainThreadQueries().build();

View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.user_adapter, parent, false);
UserHolder userAdapter = new UserHolder(v);
return userAdapter;
}

@Override
public void onBindViewHolder(@NonNull final UserAdapter.UserHolder userHolder, final int position) {
userHolder.name.setText(userList.get(position).getName().toString());
userHolder.email.setText(userList.get(position).getEmail().toString());

userHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
AlertDialog alertDialog = new AlertDialog.Builder(mContext).create();

alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "Edit",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
GlobalVariables.id = userList.get(position).getId();
GlobalVariables.name = userList.get(position).getName();
GlobalVariables.email = userList.get(position).getEmail();
GlobalVariables.updateFlag = "update";

Intent intent = new Intent(mContext,AddUserActivity.class);
mContext.startActivity(intent);
}
});

alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Delete",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
deleteUser(userList.get(position).getId());
dialog.dismiss();
userList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, userList.size());

}
});
alertDialog.show();

}
});
}

@Override
public int getItemCount() {
return userList.size();
}

private void deleteUser(int id) {
User user = new User();
user.setId(id);
db.daoClass().deleteUser(user);
Toast.makeText(mContext, "Deleted!", Toast.LENGTH_SHORT).show();
}

public class UserHolder extends RecyclerView.ViewHolder {

private TextView name, email;

public UserHolder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.name);
email = itemView.findViewById(R.id.email);

}
}
}[/java]

XML file

[java]<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto">

<android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardElevation="1dp" app:cardBackgroundColor="@color/white" android:layout_marginBottom="1dp" >
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginLeft="20dp" android:layout_marginRight="10dp" android:layout_marginBottom="10dp" android:layout_marginTop="10dp" >

<TextView android:id="@+id/name" android:textColor="@color/black" android:textSize="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:text=" " />

<TextView android:id="@+id/email" android:textSize="12dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="" />
</LinearLayout>
</android.support.v7.widget.CardView>

</RelativeLayout>[/java]

6) Add/update Data :

Create an activity named AddUserActivity . We will use this activity for both add new user and update user.

[java]
import android.arch.persistence.room.Room;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.constraint.solver.GoalRow;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.adndigitalbd.androidroomdatabase.R;
import com.adndigitalbd.androidroomdatabase.database.DatabaseClass;
import com.adndigitalbd.androidroomdatabase.entity.User;
import com.adndigitalbd.androidroomdatabase.globalVariables.GlobalVariables;

public class AddUserActivity extends AppCompatActivity {

private EditText mName,mEmail;
private Button mAddUser;
private String nameString,emailString;

private Context mContext;
DatabaseClass db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_user);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

mContext = AddUserActivity.this;

mName = findViewById(R.id.name);
mEmail = findViewById(R.id.email);
mAddUser = findViewById(R.id.addUser);

if (GlobalVariables.updateFlag.equals("update")){
mName.setText(GlobalVariables.name);
mEmail.setText(GlobalVariables.email);
}

db = Room.databaseBuilder(getApplicationContext(),
DatabaseClass.class, "myDatabase").allowMainThreadQueries().build();

mAddUser.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

nameString = mName.getText().toString();
emailString = mEmail.getText().toString();

if (nameString.length()>0 && emailString.length()>0){

if (GlobalVariables.updateFlag.equals("update")){
User user = new User();
user.setId(GlobalVariables.id);
user.setName(nameString);
user.setEmail(emailString);
db.daoClass().updateUser(user);
Toast.makeText(mContext, "Successful", Toast.LENGTH_SHORT).show();
GlobalVariables.updateFlag = "";

startActivity(new Intent(AddUserActivity.this,MainActivity.class));
}else {

User user = new User();
user.setName(nameString);
user.setEmail(emailString);
db.daoClass().addUser(user);
Toast.makeText(mContext, "Successful", Toast.LENGTH_SHORT).show();

startActivity(new Intent(AddUserActivity.this, MainActivity.class));

}

}

}
});

}

@Override
public void onBackPressed() {
super.onBackPressed();
GlobalVariables.updateFlag = "";
}
}[/java]

XML

[java]

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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=".activities.AddUserActivity">

<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_add_user" />

</android.support.design.widget.CoordinatorLayout>

[/java]

and

[java]
<?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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context=".activities.AddUserActivity" tools:showIn="@layout/activity_add_user">

<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_margin="50dp">

<EditText android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:inputType="textPersonName" android:hint="Name" tools:layout_editor_absoluteX="84dp" tools:layout_editor_absoluteY="137dp" tools:ignore="MissingConstraints" />

<EditText android:id="@+id/email" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Email" android:inputType="textEmailAddress" tools:layout_editor_absoluteX="84dp" tools:layout_editor_absoluteY="197dp" tools:ignore="MissingConstraints" />

<Button android:id="@+id/addUser" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Submit" android:layout_marginTop="10dp" android:textColor="@color/white" android:background="@color/colorPrimary" tools:layout_editor_absoluteX="148dp" tools:layout_editor_absoluteY="273dp" tools:ignore="MissingConstraints" />

</LinearLayout>

</RelativeLayout>
[/java]

7) Display list :
Now create an Activity . It’s actually main activity . That will display user data as list . also there a button to add new user data .

[java]
import android.arch.persistence.room.Room;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.InputType;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.adndigitalbd.androidroomdatabase.R;
import com.adndigitalbd.androidroomdatabase.adapters.UserAdapter;
import com.adndigitalbd.androidroomdatabase.database.DatabaseClass;
import com.adndigitalbd.androidroomdatabase.entity.User;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.content.DialogInterface;

public class MainActivity extends AppCompatActivity {

DatabaseClass db;

private RecyclerView mRecyclerView;
public UserAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
List<User> userList;

private String name = "";
private String emailString = "";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

getSupportActionBar().setTitle("Room Database");

mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setLayoutManager(mLayoutManager);

db = Room.databaseBuilder(getApplicationContext(),
DatabaseClass.class, "myDatabase").allowMainThreadQueries().build();
getAllData();

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

startActivity(new Intent(MainActivity.this,AddUserActivity.class));
}
});

}

private void getAllData() {
List<User> userList = new ArrayList<>();
userList = db.daoClass().getUsers();

if (userList.size() > 0) {
mAdapter = new UserAdapter(userList);
mRecyclerView.setAdapter(mAdapter);

} else {
Toast.makeText(this, "No data ", Toast.LENGTH_SHORT).show();
}

}

private void deleteUser() {
User user = new User();
user.setId(3);
db.daoClass().deleteUser(user);

Toast.makeText(this, "Delete user", Toast.LENGTH_SHORT).show();
}

private void updateUser() {
User user = new User();
user.setId(4);
user.setEmail("arifhasnat.com@gmail.com");
user.setName("arif hasnat");
db.daoClass().updateUser(user);

Toast.makeText(this, "User Updated", Toast.LENGTH_SHORT).show();
}

}[/java]

XML

[java]<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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=".activities.MainActivity">

<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_main" />

<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" app:srcCompat="@drawable/pencil" />

</android.support.design.widget.CoordinatorLayout>[/java]

and

[java]<?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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context=".activities.MainActivity" tools:showIn="@layout/activity_main" android:background="@color/gray">

<android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent">

</android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>
[/java]

And All Done . You can also download full project code from Github.

 

Download Project Code From Github

 

 

 

 

Node JS tutorial – Introduction and Environment setup.

Introduction:

Node.js is a very powerful JavaScript-based framework/platform. It’s all about backend development and rest API.For more details https://nodejs.org/en/.

Installations: 

Download NoteJS from https://nodejs.org/en/download/ . After downloading just install it.Open Command line tool and type node to test if it’s install correctly or not.

Text Editor : 

To work with node project you can download and install sublime text editor or atom text editor . That’s are good enough.

 

 

 

 

Your app(s) are using a content provider that contains a SQL Injection vulnerability.

Fixing a SQL Injection Vulnerability

This information is intended for developers with app(s) that contain the SQL Injection Vulnerability.

What’s happening

One or more of your apps contain a SQL Injection vulnerability that must be fixed. Please refer to the notice on your Play Console for the deadline to fix this vulnerability. After this deadline, updates to affected apps will be blocked if the vulnerability is still present. Your published APK version will remain unaffected.

Action required

Implementations of queryupdate, and delete in exported ContentProviders can be vulnerable to SQL Injection if they pass unsanitized inputs to SQL statements. A malicious app can supply a crafted input to access private data or corrupt database contents. You can fix this problem in the following ways:

If an affected ContentProvider  does not need to be exposed to other apps:

If an affected ContentProvider  needs to be exposed to other apps:

  • You can prevent SQL Injection into SQLiteDatabase.query by using strict mode with a projection map. Strict mode protects against malicious selection clauses and projection map protects against malicious projection clauses. You must use both of these features to ensure that your queries are safe.
  • You can prevent SQL Injection into SQLiteDatabase.update and SQLiteDatabase.delete by using a selection clause that uses "?" as a replaceable parameter and a separate array of selection arguments. Your selection clause should not be constructed from untrusted inputs.

Next Steps

  1. Update your app using the steps highlighted above.
  2. Sign in to your Play Console and submit the updated version of your app.
  3. Check back after five hours; we’ll show a warning message if the app hasn’t been updated correctly.

 

 

Reference: https://support.google.com/faqs/answer/7668308

Android google admob implementation – Banner

Before Follow this tutorial please first complete the project configuration about how to integrate admob in android . 

 

Step 1- Set banner ads on layout :

Set banner elements on layout file

[java]

<com.google.android.gms.ads.AdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true" ads:adSize="BANNER"
ads:adUnitId="ca-app-pub-3940256099942544/6300978111">
</com.google.android.gms.ads.AdView>

[/java]

As like –

[java]
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

<com.google.android.gms.ads.AdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
ads:adSize="BANNER" ads:adUnitId="ca-app-pub-3940256099942544/6300978111">
</com.google.android.gms.ads.AdView>

</RelativeLayout>

[/java]

Note the following required attributes:

  • ads:adSize – Set this to the ad size you’d like to use. If you don’t want to use the standard size defined by the constant, you can set a custom size instead. See the banner size section below for details.
  • ads:adUnitId – Set this to the unique identifier given to the ad unit in your app where ads are to be displayed. If you show banner ads in different activities, each would require an ad unit.

You can alternatively create AdView programmatically:

[java]
AdView adView = new AdView(this);
adView.setAdSize(AdSize.BANNER);
adView.setAdUnitId("ca-app-pub-3940256099942544/6300978111");
// TODO: Add adView to your view hierarchy.
[/java]

Step 2- Load Banner ads :

        mAdView = findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);


As like - 

import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;

public class MainActivity extends AppCompatActivity {
    private AdView mAdView;

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

        MobileAds.initialize(this,
            "ca-app-pub-3940256099942544~3347511713");

        mAdView = findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);
    }
}


Step 2- Banner ads events :

 
mAdView.setAdListener(new AdListener() {
    @Override
    public void onAdLoaded() {
        // Code to be executed when an ad finishes loading.
    }

    @Override
    public void onAdFailedToLoad(int errorCode) {
        // Code to be executed when an ad request fails.
    }

    @Override
    public void onAdOpened() {
        // Code to be executed when an ad opens an overlay that
        // covers the screen.
    }

    @Override
    public void onAdLeftApplication() {
        // Code to be executed when the user has left the app.
    }

    @Override
    public void onAdClosed() {
        // Code to be executed when when the user is about to return
        // to the app after tapping on an ad.
    }
});

Android FloodFill Algorithm

[java]

public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor,
int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {

int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x – 1, y) == target) {
x–;

}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0
&& image.getPixel(x, y – 1) == target) {
queue.add(new Point(x, y – 1));
spanUp = true;
} else if (spanUp && y > 0
&& image.getPixel(x, y – 1) != target) {
spanUp = false;
}
if (!spanDown && y < height – 1
&& image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < height – 1
&& image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}

[/java]

The ARCore dependency minimum version code com.google.ar.core.min_apk_version is missing from the AndroidManifest.xml file although the meta-data tag com.google.ar.core has been specified.

Problem :

The ARCore dependency minimum version code com.google.ar.core.min_apk_version is missing from the AndroidManifest.xml file although the meta-data tag com.google.ar.core has been specified.

 

Solution :

This is Unity ARCode dependency problem.

just add this line in menifest

  <meta-data android:name=”com.google.ar.core.min_apk_version” android:value=”24″ />

[java]<application

android:icon="@drawable/app_icon"

android:label="@string/app_name"

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

android:debuggable="false">

<meta-data android:name="com.google.ar.core.min_apk_version" android:value="24" />

<activity android:name="com.unity3d.player.UnityPlayerNativeActivity"

android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

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

</intent-filter>

<meta-data android:name="unityplayer.UnityActivity" android:value="true" />

<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />

</activity>

<uses-library android:name="com.osterhoutgroup.api.ext" android:required="false" />

</application>

[/java]

Android best libraries for android developers

Fancy Toast:

Coloring toast message. It’s looking good and user friendly.
Fancy Toast is awesome library for developers.

Speed Dial Fab : 

Android library providing an implementation of the Material Design Floating Action Button Speed Dial.

Features

    •  MinSdk 14
    •  Highly customizable for your customer portal software (label, icon, ripple, fab and label background colors, themes support)
    •  Option to have different icons for open/close state
    •  Optional overlay/touch guard layout
    •  Support for bottom, left and right menu expansion (left and right have no labels)
    •  Out-of-the box support for Snackbar behavior
    •  Optional support for RecyclerView and NestedScrollView behavior
    •  Support for VectorDrawable
  •  Easy to use