Showing posts with label android. Show all posts

How to Create a Music Previewer in Android

musicpreviewer
Introduction:
In this article, we will learn how to create a music previewer like Google play music and register the app as Music Player to the phone. Registering mobile app as Music Player will show our app in suggestions while opening audio files.
Intent Filter:
Registering app as music player will be achieved by intent-filters in AndroidManifest.xml against our activity. To know more about Intent-Filters, read the link.
Coding Part:
Steps:
I have split this part into 3 steps as in the following.
Step 1: Creating New Project with Empty Activity.
Step 2: Implementation of Music Previewer UI.
Step 3: Setting up Manifest with Intent Filters.
Step 4: Implementation of Music Previewer in Android.
Step 1: Creating New Project with Android Studio
  1. Open Android Studio and Select Create new project.
  2. Name the project as your wish and select your activity template.
  3. Click “finish” button to create new project in Android Studio.
Step 2: Implementation of Music Previewer UI
In this part, we will see how to create a dialog for music previewer.
  1. We will create an activity named as MainActivity.java and we need this activity to be show like Dialog. So, we have add the following lines in styles.xml file.
    <resources>
    
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light.Dialog">
            <item name="windowNoTitle">true</item>
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
            <item name="windowMinWidthMajor">90%</item>
            <item name="windowMinWidthMinor">90%</item>
            <item name="android:windowCloseOnTouchOutside">false</item>
        </style>
    
    </resources>
  2. Theme.Appcompat.Light.Dialog is used to apply dialog like style to an activity.
  3. By default, the dialog style applied based on children width. To apply full width to the dialog, use windowMinWidthMinor key with value 90%.
  4. In the same way, windowCloseOnTouchOutside is used to handle dialog cancel on touch outside of the views. It is similar setCancelableOnTouchOutside method for dialogs.
  5. Then open your layout file (for example: activity_main.xml) and add the followings lines.
    <?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="70dp"
        android:layout_margin="10dp"
        android:background="@android:color/white"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:padding="10dp"
        tools:context=".MainActivity">
    
            <ImageView
                android:id="@+id/song_art"
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:scaleType="fitXY"
                android:contentDescription="@string/image_desc"
                android:src="@mipmap/ic_launcher" />
    
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="9"
                android:orientation="vertical"
                android:paddingLeft="10dp"
                android:paddingStart="10dp"
                tools:ignore="RtlSymmetry">
    
                <TextView
                    android:id="@+id/song_title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@string/tv_song_title" />
    
                <TextView
                    android:id="@+id/song_artist"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:text="@string/tv_song_artist" />
            </LinearLayout>
    
            <ImageView
                android:id="@+id/play_pause"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:contentDescription="@string/image_desc"
                android:src="@drawable/ic_play" />
    
    </LinearLayout>
  6. Your layout shown like in the following figure.
    scrn 1
  7. Then click Run to view the output activity as dialog in the following figure.
scrn 2
Step 3: Setting up manifest with Intent-Filter:
In this step, we will learn How to apply intent-filter to register your music player app. The following line of codes will help us to register the app.
<activity android:name=".MainActivity">
 <intent-filter>
  <action android:name="android.intent.action.MAIN" />

  <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 <intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <data android:scheme="file"/>
  <data android:mimeType="audio/*"/>
 </intent-filter>
</activity>
This filters will lead the app to be in suggestions when we opening/selecting any audio files. The following figure for your reference.
scrn 3
Step 4: Implementation of Music Previewer in Android.
In this step, we will how to handle media options using Media Player API in Android (i.e., play, pause…).
  1. Media Player can be initialized as shown in the following.
    MediaPlayer mp = new MediaPlayer();
  2. The selected song’s path can be get using Intent and activity opening option can be identified with its action.
    if (Intent.ACTION_VIEW.equals(getIntent().getAction())) {
      try {
       assignSongDetails(getIntent().getData().getPath());
       mp.setDataSource(getIntent().getData().getPath());
       mp.prepare();
       mp.start();
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
  3. Selected song can be played with start method in media player API.
    mp.start();
  4. Media Player can be paused using pause method in media player API.
    if (mp.isPlaying()) {
      mp.pause();
     }
     
  5. Then click Run or Shift + F10 to deploy the app in debug mode. Close your app and select any audio file you want to open and select your app. Now you can find your music player works fine.
  6. Next we will see, how to get the details of the selected audio file. MediaMetadataRetriever is used here.
  7. The MediaMetaDataRetriever can be initialized like below.
    metaRetriever = new MediaMetadataRetriever();
     metaRetriever.setDataSource(filePath);
  8. Song’s album can be retrieved using the following code.
    metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
  9. Song’s artist can be retrieved using the following code.
    metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
  10. In the same way, we can read the album art using the following method.
    byte[] art = metaRetriever.getEmbeddedPicture();
     Bitmap songImage = BitmapFactory.decodeByteArray(art, 0, art.length);
     imgSongArt.setImageBitmap(songImage);
     
  11. The media player can be stopped using stop method in media player API with onPause method of the activity.
    @Override
     protected void onPause() {
      super.onPause();
      assert mp != null;
      if (mp.isPlaying()) {
       mp.stop();
      }
     }
    scrn 4
    Full Code:
    You can find the full code implementation here.
    public class MainActivity extends AppCompatActivity {
    
        TextView tvSongTitle, tvSongArtist;
        ImageView playPause, imgSongArt;
        MediaPlayer mp = new MediaPlayer();
    
        MediaMetadataRetriever metaRetriever;
        byte[] art;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            tvSongTitle = findViewById(R.id.song_title);
            tvSongArtist = findViewById(R.id.song_artist);
            playPause = findViewById(R.id.play_pause);
            imgSongArt = findViewById(R.id.song_art);
    
            if (Intent.ACTION_VIEW.equals(getIntent().getAction())) {
                try {
                    assignSongDetails(getIntent().getData().getPath());
                    mp.setDataSource(getIntent().getData().getPath());
                    mp.prepare();
                    mp.start();
                    playPause.setImageResource(R.drawable.ic_pause);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            playPause.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (mp.isPlaying()) {
                        mp.pause();
                        playPause.setImageResource(R.drawable.ic_play);
                    } else {
                        mp.start();
                        playPause.setImageResource(R.drawable.ic_pause);
                    }
                }
            });
    
            mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                public void onCompletion(MediaPlayer mp) {
                    playPause.setImageResource(R.drawable.ic_play);
                }
            });
    
        }
    
        void assignSongDetails(String filePath) {
            metaRetriever = new MediaMetadataRetriever();
            metaRetriever.setDataSource(filePath);
            try {
                tvSongTitle.setText(metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM));
                tvSongArtist.setText(metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST));
                try {
                    art = metaRetriever.getEmbeddedPicture();
                    Bitmap songImage = BitmapFactory.decodeByteArray(art, 0, art.length);
                    imgSongArt.setImageBitmap(songImage);
                } catch (Exception ex) {
                    imgSongArt.setImageResource(R.mipmap.ic_launcher);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            assert mp != null;
            if (mp.isPlaying()) {
                mp.stop();
            }
        }
    }
Download Code:
You can download the full source code of the article in GitHub. If you like this article, do star the repo in GitHub. Hit like the article.

Circular Reveal Animation In Android

Figure 1

Introduction 

In this article, we will learn how to create layout reveal animation in Android. This feature is available by default from Lollipop. For pre-Lollipop Android versions, an awesome library is available and it is very easy to use.

Circular Reveal animations can be found in WhatsApp while clicking attachment option. It’s more interactive to users. We will learn in detail how to use in Lollipop and Pre-Lollipop devices separately.

Circular Reveal Animation

We already know this feature is available from Lollipop devices. To perform the same features in pre-Lollipop devices we will go for a third party library and it’s awesome to use.

Steps

I have divided this Implementation into 4 steps as shown in the following.
Step 1 - Creating New Project with Android Studio
Step 2 - Setting up the library for the project.
Step 3 - Implementation of Circular Reveal for Pre-Lollipop devices.
Step 4 - Implementation of Circular Reveal for Lollipop devices.

Step 1: Creating New Project with Android Studio

  1. Open Android Studio and Select create a new project.
  2. Name the project as per your wish and select an Empty activity.
    Android
    Figure 5
  3. Click finish button to create a new project in Android Studio.

Step 2 - Setting up the library for the project

  1. Open App Level gradle file and add the following lines to add the Libraries.
    dependencies {  
        ...  
        implementation 'com.android.support:appcompat-v7:26.1.0'  
        implementation 'com.android.support:support-annotations:27.1.1'  
        implementation 'com.android.support.constraint:constraint-layout:1.1.2'  
        implementation 'com.android.support:design:26.1.0'  
      
        // Third Party Library  
        implementation 'com.github.ozodrukh:CircularReveal:1.1.0'  
        ...  
    }  
      
    repositories {  
        maven {  
            url "https://jitpack.io"  
        }  
    }
  2. Then click “Sync Now” to add the library.

Step 3 - Implementation of Circular Reveal for Pre-Lollipop devices

  1. Open your designer file that is your XML layout file (In my case, I have opened my xml file) and paste the following code below toolbar if you want.
    <io.codetail.widget.RevealFrameLayout  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"> 
      
        <LinearLayout  
            android:id="@+id/reveal_items"  
            android:layout_width="match_parent"  
            android:layout_height="match_parent"  
            android:background="@android:color/white"  
            android:orientation="horizontal"  
            android:gravity="center"  
            android:padding="16dp"> 
      
            <LinearLayout  
                android:layout_width="match_parent"  
                android:layout_height="wrap_content"  
                android:orientation="horizontal"> 
      
                <ImageView  
                    android:layout_gravity="center"  
                    android:id="@+id/imageView"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:background="@drawable/ic_search_green" /> 
      
                <EditText  
                    android:id="@+id/search_box"  
                    android:layout_width="match_parent"  
                    android:layout_height="wrap_content"  
                    android:hint="Search Here..."  
                    android:inputType="text"  
                    android:imeOptions="actionSearch"  
                    android:maxLines="1"/> 
            </LinearLayout> 
        </LinearLayout> 
      
    </io.codetail.widget.RevealFrameLayout>
  2. Here, Reveal Frame Layout itself is used to handle Reveal animation. The Reveal effect can be applied to the whole screen.
  3. We have initialized the immediate child of the RevealFrameLayout and by default its state should be GONE or INVISIBLE. While changing its View states, the RevealFrameLayout will clips its child’s shape
    revealLayout = findViewById(R.id.reveal_items);  
    revealLayout.setVisibility(View.INVISIBLE);
  4. To perform the animation, import SupportAnimator class from the third party library included for Pre-Lollipop devices.
    import io.codetail.animation.SupportAnimator;  
    import io.codetail.animation.ViewAnimationUtils;
  5. Then add the following to perform the animation in forth and reverse. We need X, Y co-ordinates to perform the animation.
    SupportAnimator animator = ViewAnimationUtils.createCircularReveal(layout, cx, cy, 0, radius);  
    animator.setInterpolator(new AccelerateDecelerateInterpolator());  
    animator.setDuration(800);  
      
    SupportAnimator animator_reverse = animator.reverse();  
      
    if (hidden) {  
        layout.setVisibility(View.VISIBLE);  
        animator.start();  
        invalidateOptionsMenu();  
        hidden = false;  
    } else {  
        animator_reverse.addListener(new SupportAnimator.AnimatorListener() {  
            @Override  
            public void onAnimationStart() {  
      
            }  
      
            @Override  
            public void onAnimationEnd() {  
                layout.setVisibility(View.INVISIBLE);  
                invalidateOptionsMenu();  
                hidden = true;  
            }  
      
            @Override  
            public void onAnimationCancel() {  
      
            }  
      
            @Override  
            public void onAnimationRepeat() {  
      
            }  
        });  
        animator_reverse.start();  
    }
  6. Here,
    cx - co-ordinate in X axis.
    cy – co-ordinate in Y axis.
    These two are required for starting the animation in X, Y axis of the screen. It can be calculated by the following code.
    int cx = revealLayout.getRight();  
    int cy = revealLayout.getTop();
    radius - can be calculated by the following code.
    int radius = Math.max(layout.getWidth(), layout.getHeight());
    Animation can be started by SupportAnimator and it is assigned to another SupportAnimator which is used to start the reverse animation. So, the reverse animation will be handled by itself.
    SupportAnimator animator = ViewAnimationUtils.createCircularReveal(layout, cx, cy, 0, radius);  
    animator.setInterpolator(new AccelerateDecelerateInterpolator());  
    animator.setDuration(800);  
      
    SupportAnimator animator_reverse = animator.reverse();  
      
    if (hidden) {  
        layout.setVisibility(View.VISIBLE);  
        animator.start();  
        invalidateOptionsMenu();  
        hidden = false;  
    } else {  
        animator_reverse.addListener(new SupportAnimator.AnimatorListener() {  
            @Override  
            public void onAnimationStart() {  
      
            }  
      
            @Override  
            public void onAnimationEnd() {  
                layout.setVisibility(View.INVISIBLE);  
                invalidateOptionsMenu();  
                hidden = true;  
            }  
      
            @Override  
            public void onAnimationCancel() {  
      
            }  
      
            @Override  
            public void onAnimationRepeat() {  
      
            }  
        });  
        animator_reverse.start();  
    }
    hidden – is a Boolean value used to know the View State.
  7. Probably this does not seem to work from Lollipop devices. So we have to go for a different method which is shown in the next step.

Step 4 - Implementation of Circular Reveal for Lollipop devices

  1. No 5 in the previous step is slightly changed for Lollipop devices. Instead of “io.codetail.animation.ViewAnimationUtils”, use “android.view.ViewAnimationUtils”.
  2. No need to assign animation.reverse(). Instead of it, use the following.
    if (hidden) {  
        Animator anim = android.view.ViewAnimationUtils.createCircularReveal(layout, cx, cy, 0, radius);  
        layout.setVisibility(View.VISIBLE);  
        anim.start();  
        invalidateOptionsMenu();  
        hidden = false;  
      
    } else {  
    Animator anim = android.view.ViewAnimationUtils.createCircularReveal(layout, cx, cy, radius, 0);  
        anim.addListener(new AnimatorListenerAdapter() {  
            @Override  
            public void onAnimationEnd(Animator animation) {  
                super.onAnimationEnd(animation);  
                layout.setVisibility(View.INVISIBLE);  
                hidden = true;  
                invalidateOptionsMenu();  
            }  
        });  
        anim.start();  
    }
  3. To reverse the animation, the radius value is interchanged. The animation is handled from toolbar menu options.

Full Code

You can find the full code implementation here.
public class MainActivity extends AppCompatActivity {  
  
    Toolbar toolbar;  
    LinearLayout revealLayout;  
    EditText searchBox;  
    boolean hidden = true;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
  
        toolbar = findViewById(R.id.toolbar);  
        setSupportActionBar(toolbar);  
  
        revealLayout = findViewById(R.id.reveal_items);  
        revealLayout.setVisibility(View.INVISIBLE);  
        searchBox = findViewById(R.id.search_box);  
        searchBox.setOnEditorActionListener(new TextView.OnEditorActionListener() {  
            @Override  
            public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {  
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {  
                    handleKeyboard(searchBox);  
                    searchBox.clearFocus();  
                    Toast.makeText(MainActivity.this, textView.getText().toString(), Toast.LENGTH_SHORT).show();  
                    return true;  
                }  
                return false;  
            }  
        });  
    }  
  
    void handleKeyboard(View view) {  
        InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);  
        assert inputManager != null;  
        inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);  
    }  
  
    @Override  
    public boolean onCreateOptionsMenu(Menu menu) {  
        getMenuInflater().inflate(R.menu.menu_reveal, menu);  
        if (hidden) {  
            menu.findItem(R.id.action_search).setIcon(R.drawable.ic_search);  
        } else {  
            menu.findItem(R.id.action_search).setIcon(R.drawable.ic_close);  
        }  
        return true;  
  
    }  
  
    @Override  
    public boolean onOptionsItemSelected(MenuItem item) {  
        switch (item.getItemId()) {  
            case R.id.action_search:  
                int cx = revealLayout.getRight();  
                int cy = revealLayout.getTop();  
                makeEffect(revealLayout, cx, cy);  
                searchBox.setText(null);  
                return true;  
            case android.R.id.home:  
                supportFinishAfterTransition();  
                return true;  
        }  
  
        return super.onOptionsItemSelected(item);  
    }  
  
    private void makeEffect(final LinearLayout layout, int cx, int cy) {  
  
        int radius = Math.max(layout.getWidth(), layout.getHeight());  
  
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {  
  
            SupportAnimator animator = ViewAnimationUtils.createCircularReveal(layout, cx, cy, 0, radius);  
            animator.setInterpolator(new AccelerateDecelerateInterpolator());  
            animator.setDuration(800);  
  
            SupportAnimator animator_reverse = animator.reverse();  
  
            if (hidden) {  
                layout.setVisibility(View.VISIBLE);  
                animator.start();  
                invalidateOptionsMenu();  
                hidden = false;  
            } else {  
                animator_reverse.addListener(new SupportAnimator.AnimatorListener() {  
                    @Override  
                    public void onAnimationStart() {  
  
                    }  
  
                    @Override  
                    public void onAnimationEnd() {  
                        layout.setVisibility(View.INVISIBLE);  
                        invalidateOptionsMenu();  
                        hidden = true;  
                    }  
  
                    @Override  
                    public void onAnimationCancel() {  
  
                    }  
  
                    @Override  
                    public void onAnimationRepeat() {  
  
                    }  
                });  
                animator_reverse.start();  
            }  
        } else {  
            if (hidden) {  
                Animator anim = android.view.ViewAnimationUtils.createCircularReveal(layout, cx, cy, 0, radius);  
                layout.setVisibility(View.VISIBLE);  
                anim.start();  
                invalidateOptionsMenu();  
                hidden = false;  
  
            } else {  
                Animator anim = android.view.ViewAnimationUtils.createCircularReveal(layout, cx, cy, radius, 0);  
                anim.addListener(new AnimatorListenerAdapter() {  
                    @Override  
                    public void onAnimationEnd(Animator animation) {  
                        super.onAnimationEnd(animation);  
                        layout.setVisibility(View.INVISIBLE);  
                        hidden = true;  
                        invalidateOptionsMenu();  
                    }  
                });  
                anim.start();  
            }  
        }  
    }  
}

Output Demo

You can find the output of this example.

Download Code

You can download the full source code of the article in GitHub. If you like this article, do star the repo in GitHub.

CRUD Operations With Firebase Cloud Fire Store


Introduction
In this article, we will learn how to use Firebase Cloud Fire Store in Android and how to do CRUD operations with Firebase Cloud Fire Store.
Getting started with Firebase
Read the following to learn how to set up the Firebase in your Android project.
Reference - https://androidmads.blogspot.in/2016/10/android-getting-started-with-firebase.html
Additionally, do the following for Cloud Firestore.
You can enable the test mode to make the database accessible to all users.
Android
At this point, the empty DB is created as shown in the figure below.
Android
Firebase Cloud Fire store
It is a flexible, scalable NoSQL cloud database to store and sync data for client- and server-side development.
Key capabilities
  • Flexibility
  • Expressive Querying
  • Real-time Updates
  • Offline Support
  • Designed to Scale
Concepts
Firestore hosted the data like NoSQL Database.
Database             ->            Collections
Table                     ->            Document
Column                ->            Field
Coding Part
I have split this part into 3 steps as in the following.
Step 1 - Creating New Project with Empty Activity.
Step 2 - Setting up the Firebase Library.
Step 3 - Implementation of CRUD with Cloud Firestore.
Step 1 - Create a new project with Empty Activity
  1. Open Android Studio and Select create a new project.
  2. Name the project as per your wish and select an Empty activity.

    Android
  3. Click finish button to create a new project in Android Studio.
Step 2 - Setting up the Firebase Library
In this part, we will see how to setup the library for the project.
1. Open your project level build.gradle file and add the following lines in dependencies
dependencies {  
    …  
    classpath 'com.google.gms:google-services:3.1.0'  
              …  
}
2. Then add the following lines in all projects in the project level build.gradle file.
allprojects {  
    repositories {  
        google()  
        jcenter()  
        maven {  
            url "https://maven.google.com"  
        }  
    }  
}
3. Then add the following lines in app level build.gradle file to apply Google services to your project.
dependencies {  
    ...  
    implementation 'com.google.firebase:firebase-firestore:11.8.0'  
}
4. Then click “Sync Now” to set up your project.
Step 3 - Implementation of CRUD with Cloud Firestore
In this part, we will see how to implement CRUD operations with Firestore.
First, we will initialize the Firestore Database.
FirebaseFirestore myDB;  
// Init FireStore  
myDB = FirebaseFirestore.getInstance();
INSERT DATA
You can insert the data to Firestore like the following.
Map data = new HashMap<>();  
data.put("task_name", edtData.getText().toString());  
myDB.collection("tasks")  
 .add(data)  
 .addOnSuccessListener(new OnSuccessListener() {  
  @Override  
  public void onSuccess(DocumentReference documentReference) {  
   toastResult("Data added successfully");  
  }  
 })  
 .addOnFailureListener(new OnFailureListener() {  
  @Override  
  public void onFailure(@NonNull Exception e) {  
   toastResult("Error while adding the data : " + e.getMessage());  
  }  
 });
Here, we created a collection named “tasks” and we inserted the data with “task_name”. The add() method automatically generates and assigns a unique alphanumeric identifier to every document it creates. If you want your documents to have your own custom IDs instead, you must first manually create those documents by calling the document() method, which takes a unique ID string as its input. You can then populate the documents by calling the set() method, which, like the add method, expects a map as its only argument.
You can set user preferred document name instead of auto generated unique identifier using the following method
myDB.collection("tasks").document("user_preferred_id").set(data)  
The following figure shows the DB after inserting the data.
Android
READ DATA
You can read the collection of data from firestore using “addSnapShotListener”. The code explains how to read data from Cloud Firestore.
myDB.collection("tasks").document("user_preferred_id").set(data)myDB.collection("tasks").addSnapshotListener(new EventListener() {  
        @Override  
        public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {  
            if (e != null)  
                toastResult(e.getMessage());  
            list.clear();  
            for (DocumentSnapshot doc : documentSnapshots) {  
                list.add(doc.getString("task_name"));  
            }  
        }  
    });
UPDATE DATA
You can update the record in the collection if you know the name/Id of the document. The following code shows how to update the data. Map is used to update the data with the same in the document.
Map data = new HashMap<>();  
data.put("data", edtData.getText().toString());  
myDB.collection("myData").document("1").update(data)  
        .addOnSuccessListener(new OnSuccessListener() {  
            @Override  
            public void onSuccess(Void aVoid) {  
                toastResult("Data updated successfully");  
            }  
        })  
        .addOnCompleteListener(new OnCompleteListener() {  
            @Override  
            public void onComplete(@NonNull Task task) {  
                toastResult("Data update Completed");  
            }  
        })  
        .addOnFailureListener(new OnFailureListener() {  
            @Override  
            public void onFailure(@NonNull Exception e) {  
                toastResult("Error while updating the data : " + e.getMessage());  
            }  
        });
DELETE DATA
The existing data can be deleted from Firestore using delete() function. The following code shows how to implement the delete function.
myDB.collection("myData").document("1").delete()  
    .addOnSuccessListener(new OnSuccessListener() {  
        @Override  
        public void onSuccess(Void aVoid) {  
            toastResult("Data deleted successfully");  
        }  
    })  
    .addOnFailureListener(new OnFailureListener() {  
        @Override  
        public void onFailure(@NonNull Exception e) {  
            toastResult("Error while deleting the data : " + e.getMessage());  
        }  
    });
Download Code
If you think this article is informative do like and star the repo in GitHub. You can download the full sample code here.
Demo
You can find the demo video on YouTube.

How To Create Live Templates In Android Studio


In this article, we will see how to create Live Templates in Android Studio or IntelliJ IDE products like WebStorm, PHPStorm, etc. Live Templates are very useful to increase the speed of development, efficiency, and accuracy.
Predefined Live Templates
Android Studio has some predefined live templates such as “psfi” which is a simplification of “private state final int”. The following are some additional predefined templates.
How to create your own Live Templates
We can create our own live templates using the following method.
  1. Open Android Studio and select File >> Settings as shown in Figure 1.

    Android
    Figure 1
  1. Now, the Settings popup is shown. Select Editor >> Live Templates. It lists the Live Templates categorized by their type or Languages as shown in Figure 2.

    Android
    Figure 2
  1. Then, select or click plus +.Select TemplateGroup and give a name for your Template Group as shown in Figure 3.

    Android
    Figure 3
  1. Select your Template Group and click plus +. Select Live Template and name your template, add your code and define your language like XML by selecting clicking Define like in Figure 4.

    Android
    Figure 4
  1. To use it, type the template abbreviation we have created and hit enter which replaces the code written in your template.
  2. Typing the abbreviation shows the template saved as shown in Figure 5 and hit Enter.

    Android
    Figure 5
  1. Which replaces the code typed by you.

    Android
We can do the same for all languages. This will increase the development speed, efficiency, and accuracy of code construction. If you like this article, do like and share and post your doubts in the comments section.

How to custom fonts to Views - Android


In this article, we will learn how to apply custom fonts to Views in Android like Toolbar, MenuItem apart from the views like TextView, EditText.

FontUtils:

FontUtils is a tiny font utility library used to apply custom fonts to Views. It supports the following views.
  • Toolbar
  • NavigationView
  • Menu
  • Submenu
  • Other Views like EditText, TextView, etc.
This library is support the following Languages.
  • Android – Java
  • Android – Kotlin
  • Android

Coding Part:

Steps:

I have split this part into 3 steps as in the following.
Step 1: Creating New Project with Empty Activity.
Step 2: Setting up the Library for Android Views.
Step 3: Applying Custom fonts to Android Views.

Step 1:Creating New Project with Empty Activity

  1. Open Android Studio and Select Create new project.
  2. Name the project as your wish and select Empty activity.
  3. Click “finish” button to create new project in Android Studio.

Step 2:Setting up the Library for Android Views

In this part, we will see how to setup the library for the project.
  1. Open your app level build.gradle file and add the following lines to download the library.
    …
    implementation 'com.ajts.androidmads.fontutils:fontutils:1.0.1'
    …
    
  2. Then Click “Sync Now” to download the library.
  3. We need to use “compile” instead of “implementation” if we have using Android Studio Version below 3.0.

Step 3:Applying Custom fonts to Android Views

In this part, we will see how to apply custom fonts to Views. Here, we have to use “Typeface” and to more about “TypeFace” Click here.
  1. In this article, I am assigning the fonts from Assets folder. To create assets folder, right on the app folder and select New. Then select Folder and click assets folder.
  2. Then Copy and Paste the fonts you want to use with your application.
  3. The following line shows how to initialize the library.
    // Applying Custom Font
    Typeface typeface = Typeface.createFromAsset(getAssets(), "custom_font.ttf");
    // Init Library
    FontUtils fontUtils = new FontUtils();
  4. Then Initialize your Views and apply the fonts to the Views. The following example shows how to apply the fonts to Toolbar of your application.
    // Apply font to Toolbar
    fontUtils.applyFontToToolbar(toolbar, typeface);
  5. You can apply custom fonts to other views like NavigationView, Menu, Submenu, TextView like in following example.
    // Apply font to NavigationView
    fontUtils.applyFontToNavigationView(navigationView, typeface);
    // Apply font to Menu
    fontUtils.applyFontToMenu(menu, typeface);
    // Apply font to Other Views like TextView...
    fontUtils.applyFontToView(textview, typeface);
    fontUtils.applyFontToView(editText, typeface);
    fontUtils.applyFontToView(radioButton, typeface);
    fontUtils.applyFontToView(checkBox, typeface);

For Kotlin

We need to do the same steps mentioned. But we need to include Kotlin support while creating the project. Apply font to Views in Kotlin as show below.
// Applying Custom Font
val typeface = Typeface.createFromAsset(assets, "custom_font.ttf")
// Init Library
val fontUtils = FontUtils()
// Apply font to Toolbar
fontUtils.applyFontToToolbar(toolbar, typeface)
// Apply font to NavigationView
fontUtils.applyFontToNavigationView(navigationView, typeface)
// Apply font to Menu
fontUtils.applyFontToMenu(menu, typeface)
// Apply font to Other Views like TextView...
fontUtils.applyFontToView(textview, typeface)
fontUtils.applyFontToView(editText, typeface)
fontUtils.applyFontToView(radioButton, typeface)
fontUtils.applyFontToView(checkBox, typeface)

For Xamarin.Android

We can apply the same with Xamarin.Android. To know more Click Here.


Download Code

The article is informative do like and star the repo in GitHub. You can download the code here.
Note:
Java and Kotlin Android Support
https://github.com/androidmads/FontUtils
Xamarin.Android Support
https://github.com/Xamarin-Gists/XAFontUtilsLibrary

Android Form Validation using Saripaar Validator


In this tutorial, we will learn how to validate forms in Android using Saripaar Library. Android Saripaar is a simple, feature-rich and powerful rule-based UI form validation library for Android. It is the Simplest UI validation library available for Android. To learn about Butter Knife, read my previous article.

Advantages of using Saripaar:

  1. Simple to Use.
  2. Easily Customizable
  3. Supports all annotation services in Android like Butter Knife, Android Annotations, Robo Guice, etc.,

Project Setup:

In this tutorial, I have used Saripaar with Butter Knife. Open Project Level Gradle file and paste the following
dependencies {
 classpath 'com.android.tools.build:gradle:2.3.3'
 classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1'
}
Open App level Gradle file and add the following dependencies
apply plugin: 'com.jakewharton.butterknife'
...
dependencies {
    ...
    compile 'com.mobsandgeeks:android-saripaar:2.0.2'
    compile 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

Examples:

The following example is used to validate email id with EditText. 
@BindView(R.id.email)
@NotEmpty
@Email
EditText emailEditText;
@NotEmpty is used to make mandatory input of EditText.
@Email is used to validate Email input.
@BindView used for Butter Knife
The following example is used to validate Password with Confirm Password.
@BindView(R.id.password)
@Password(min = 6, scheme = Password.Scheme.ALPHA_NUMERIC_MIXED_CASE_SYMBOLS)
EditText passwordEditText;
@BindView(R.id.conf_password)
@ConfirmPassword
EditText confirmPasswordEditText;
@Password is used to validate password with ALPHA_NUMERIC_MIXED_CASE_SYMBOLS
@ConfirmPassword used to match @Password input with Confirm Password input.
The following example is used to validate with custom pattern and custom message.
@BindView(R.id.phone)
@Pattern(regex = "^[7-9][0-9]{9}$", message = "Invalid Mobile Number")
EditText phoneEditText;
@Pattern is used to validate custom pattern.
regex is used to set custom pattern.
message used to set custom message.

Validation Process:

You can set validation listener like below.
public class MainActivity extends AppCompatActivity 
   implements Validator.ValidationListener {
   
   ...   

    @Override
    public void onValidationSucceeded() {
        Toast.makeText(this, "Validation Success", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onValidationFailed(List errors) {
        for (ValidationError error : errors) {
            View view = error.getView();
            String message = error.getCollatedErrorMessage(this);

            // Display error messages ;)
            if (view instanceof EditText) {
                ((EditText) view).setError(message);
            } else {
                Toast.makeText(this, message, Toast.LENGTH_LONG).show();
            }
        }
    }
   
}
The Form validated with the following code
validator = new Validator(this);
validator.setValidationListener(this);
...
@OnClick(R.id.submit)
public void onButtonClick(View view) {
 validator.validate();
}

Download Code:

You can the download code for this post from Github. If you like this, tutorial star it on Github.

Download file using Okio in Android


Okio is a library that complements java.io and java.nio to make it much easier to access, store, and process your data. Simply Okio is a modern I/O API for Java. 

In this post, we will see how to download image or any file using Okio. Okio is component for OkHttp

Coding Part

Create a new project in Android Studio.

Add following dependencies to your app-level build.gradle file.
compile 'com.squareup.okhttp3:okhttp:3.6.0'
Don't forget to add the following permission in your AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Implementation

Paste the following code in your Activity and Here, I have kept as MainActivity.java
public void downloadImg(View view) {
 try {
  Request request = new Request.Builder()
    .url(imageLink)
    .build();
  new OkHttpClient().newCall(request).enqueue(new Callback() {
   @Override
   public void onFailure(Call call, IOException e) {
   }

   @Override
   public void onResponse(Call call, Response response) 
    throws IOException {
    if (!folder.exists()) {
     boolean folderCreated = folder.mkdir();
     Log.v("folderCreated", folderCreated + "");
    }
    file = new File(folder.getPath() + "/savedImg.png");
    if (file.exists()) {
     boolean fileDeleted = file.delete();
     Log.v("fileDeleted", fileDeleted + "");
    }
    boolean fileCreated = file.createNewFile();
    Log.v("fileCreated", fileCreated + "");
    BufferedSink sink = Okio.buffer(Okio.sink(file));
    sink.writeAll(response.body().source());
    sink.close();
    new DownloadImage(file).execute();
   }
  });
 } catch (Exception e) {
  e.printStackTrace();
 }
}
It is similar to Java I/O API. It has two important components as BufferSource and BufferSink.
  • BufferSource is like InputStream in Java I/O API and BufferSink is like OutputStream.
  • You can view any Source as an InputStream, and you can view any InputStream as a Source. Similarly for Sink and OutputStream. 

Demo


Download Code

You can download the full source code for this tutorial from the following Github link. If you Like this tutorial, Please star it in Github.

Download From Github

Youtube Video link to mp3 file

Youtube Video link to mp3 file

It is a light weight library to download YouTube video as mp3 files

Created By

API

How to Download

Gradle:
compile 'com.ajts.androidmads.youtubemp3:youtubemp3:1.0.0'
Maven:
<dependency>
  <groupId>com.ajts.androidmads.youtubemp3</groupId>
  <artifactId>youtubemp3</artifactId>
  <version>1.0.0</version>
  <type>pom</type>
</dependency>

How to use this Library:

This Library is used to download mp3 file from youtube video link.
new YTubeMp3Service.Builder(MainActivity.this)
    .setDownloadUrl("https://youtu.be/nZDGC-tXCo0")
    .setFolderPath(new File(Environment.getExternalStorageDirectory(), "/YTMp3/Downloads").getPath())
    .setOnDownloadListener(new YTubeMp3Service.Builder.DownloadListener() {
        @Override
        public void onSuccess(String savedPath) {
            Log.v("exce", savedPath);
            progressDialog.dismiss();
        }

        @Override
        public void onDownloadStarted() {
        }

        @Override
        public void onError(Exception e) {
            Log.v("exce", e.getMessage());
            progressDialog.dismiss();
        }
    }).build();

Download From Github

Firebase Cloud Messaging in Android

Firebase Cloud Messaging in Android

Firebase Cloud Messaging (FCM) is the new version of GCM. It inherits the reliable and scalable GCM infrastructure, plus new features. If you are integrating messaging in a new app, start with FCM. GCM users are strongly recommended to upgrade to FCM, in order to benefit from new FCM features today and in the future.

Firebase Cloud Messaging is very easy to integrate into your Application. Just like GCM, FCM is a cross-platform messaging solution that allows you to send messages. FCM is completely free and there are no limitations

Firebase Setup

The Feature and Settings up of Application in Application is Explained in Previous post. After this, follow the tutorial as in below. In This post, I am not explaining about any Layouts. Simply explains the Java code build to FCM Application.

Adding Firebase Messaging to Your Project

  • Now come back to your android project. Go to app folder and paste google-services.json file.
  • Now go to your root level build.gradle file and add the following code
// Add this line
classpath 'com.google.gms:google-services:3.0.0'
  • Inside app level build.gradle file make the following changes.
// Add this line
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile 'com.google.firebase:firebase-core:9.0.2'
    compile 'com.google.firebase:firebase-messaging:9.0.2'
}
apply plugin: 'com.google.gms.google-services'

Implementing Firebase Cloud Messaging

Create a class named  FireBaseInstanceIDService.java and write the following code.
// Add this line
public class FireBaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = FireBaseInstanceIDService.class.getSimpleName();
    public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";
    public static final String REGISTRATION_TOKEN = "token";

    @Override
    public void onTokenRefresh() {
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed_token: " + refreshedToken);

        // Used to get Device token to store in database 
        Intent intent1 = new Intent(REGISTRATION_SUCCESS);
        intent1.putExtra(REGISTRATION_TOKEN, refreshedToken);
        sendBroadcast(intent1);
    }

}
Create a class named  FireBaseMessagingService.java and write the following code.
// Add this line
private static final String TAG = FireBaseMessagingService.class.getSimpleName();

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        //Displaying data in log
        //It is optional
        Log.d(TAG, "remoteMessage: " + remoteMessage);
        //Calling method to generate notification
        sendNotification(remoteMessage.getNotification().getBody());
    }

    //This method is only generating push notification
    //It is same as we did in earlier posts
    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("FireBase Push Notification")
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notificationBuilder.build());
    }
  • Now we have to define the above services in our AndroidManifest.xml file. Don't forget to add Internet Permission.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androidmads.firebasecloudmessaging">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        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>

        <!-- Defining Services -->
        <service android:name=".FireBaseMessagingService" >
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        <service android:name=".FireBaseInstanceIDService" >
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>
    </application>

</manifest>

  • Thats all. Now run your app (Make sure your device is having google play service or else it won’t work). After running you will see the token in the logcat or in your Main Screen. Copy the token.

Sending Push Notification using Firebase Console :
  • Go to firebase console and select the app you created.
  • From the left menu select notification.
  • Click on new message.
  • Enter message, select single device and paste the token you copied and click on send

For more, Details Please download whole project source from Github.

Download From Github

If you find this post is useful, Please provide star in Github and Having any trouble or doubt while using this project leave your comment.