How to add Shadow and Text on ImageView in AndroidAndroid Development

How to add Shadow and Text on ImageView in AndroidAndroid Development
Basically, it works like a stack where each view is stacked on top of the other.
Create a drawable file for shadow view and assign the name image_shadow and add the below code in this file.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp" />
<gradient
android:angle="270"
android:centerX="300%"
android:endColor="#99000000"
android:startColor="#00000000"
android:type="linear" />
<size
android:width="270dp"
android:height="60dp" />
<stroke
android:width="1dp"
android:color="#878787" />
</shape>
Now, open xml file and add the below code into it, and set this drawable file as view background.
<androidx.appcompat.widget.LinearLayoutCompat
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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/imageView"
android:layout_width="250dp"
android:layout_height="250dp"
android:scaleType="centerCrop"
android:src="@drawable/shopping_image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<View android:id="@+id/view"
android:layout_width="250dp"
android:layout_height="250dp"
android:background="@drawable/image_shadow"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textColor="@android:color/white"
android:text="Write your text here"
android:textSize="25sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@+id/view"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
That's it. You should be ready to go.
How to Customize Snackbar in AndroidAndroid Development

How to Customize Snackbar in AndroidAndroid Development
dependencies { implementation "com.google.android.material:$latest_version" }
Snackbar.make(view, "Show some message here", Snackbar.LENGTH_SHORT).show()
<?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:id="@+id/coordinatorLayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.application.snackbarapp.MainActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="show snackbar" /> </RelativeLayout> </android.support.design.widget.CoordinatorLayout>
import android.graphics.Color; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private CoordinatorLayout coordinatorLayout; private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); coordinatorLayout = findViewById(R.id.coordinatorLayout); button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showSnackbar(); } }); } public void showSnackbar() { Snackbar snackbar = Snackbar.make(coordinatorLayout, "Marked as Read", Snackbar.LENGTH_INDEFINITE) .setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View v) { Snackbar snackbar1 = Snackbar.make(coordinatorLayout, "Undo successful", Snackbar.LENGTH_SHORT); snackbar1.show(); } }) .setActionTextColor(Color.RED); snackbar.show(); } }
How to Implement Splash Screen in AndroidAndroid Development

How to Implement Splash Screen in AndroidAndroid Development
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/white" /> <item android:drawable="@drawable/ic_icon_vector" android:gravity="center" /> </layer-list>
<!-- Splash Screen theme. --> <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar"> <item name="android:windowBackground">@drawable/splash_background</item> </style>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.exmple.splash"> <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/Theme"> <activity android:name=".SplashActivity" android:theme="@style/SplashTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
public class SplashActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); startActivity(new Intent(SplashActivity.this, MainActivity.class)); finish(); } }
How to Create Custom CardView in AndroidAndroid Development

How to Create Custom CardView in AndroidAndroid Development
dependencies { implementation ‘androidx.cardview:cardview:1.0.0’ }
res > drawable > New > Drawable Resource File.
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <gradient android:startColor="#FFAB00" android:endColor="#FFAB00"> </gradient> </shape>
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <gradient android:startColor="#0091EA" android:endColor="#00BFA5"> </gradient> </shape>
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <gradient android:startColor="#AEEA00" android:endColor="#FFD600"> </gradient> </shape>

You can change it according to your needs.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical"> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="173dp" android:layout_marginStart="20dp" android:layout_marginTop="20dp" android:layout_marginEnd="20dp" app:cardCornerRadius="8dp"> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg1" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="30dp" android:layout_marginTop="20dp" android:layout_marginEnd="30dp" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Assam" android:textColor="#000000" android:textSize="22sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Current Location" android:textColor="#000000" android:textSize="14sp" /> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginStart="30dp" android:layout_marginTop="20dp" android:layout_marginEnd="30dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="25" android:textColor="#000000" android:textSize="28sp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="6dp" android:text="o" android:textColor="#000000" android:textSize="13sp" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="18 %" android:textColor="#000000" android:textSize="14sp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_marginStart="6dp" android:text="11.25 AM" android:textColor="#000000" android:textSize="14sp" /> </RelativeLayout> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="173dp" android:layout_marginStart="20dp" android:layout_marginTop="20dp" android:layout_marginEnd="20dp" app:cardCornerRadius="8dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg2" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="30dp" android:layout_marginTop="20dp" android:layout_marginEnd="30dp" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Delhi" android:textColor="@color/white" android:textSize="22sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2 days ago" android:textColor="@color/white" android:textSize="14sp" /> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginStart="30dp" android:layout_marginTop="20dp" android:layout_marginEnd="30dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="39" android:textColor="@color/white" android:textSize="28sp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="6dp" android:text="o" android:textColor="@color/white" android:textSize="13sp" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="35 %" android:textColor="@color/white" android:textSize="14sp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_marginStart="6dp" android:text="01.05 PM" android:textColor="#D6D6D6" android:textSize="14sp" /> </RelativeLayout> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="173dp" android:layout_marginStart="20dp" android:layout_marginTop="20dp" android:layout_marginEnd="20dp" app:cardCornerRadius="8dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg3" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="30dp" android:layout_marginTop="20dp" android:layout_marginEnd="30dp" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Darjeeling" android:textColor="#000000" android:textSize="22sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2 weeks ago" android:textColor="#000000" android:textSize="14sp" /> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginStart="30dp" android:layout_marginTop="20dp" android:layout_marginEnd="30dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="12" android:textColor="#000000" android:textSize="28sp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="6dp" android:text="o" android:textColor="#000000" android:textSize="13sp" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="9 %" android:textColor="#000000" android:textSize="14sp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_marginStart="6dp" android:text="05.00 AM" android:textColor="#000000" android:textSize="14sp" /> </RelativeLayout> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout>
How To Integrate onesignal push notification in AndroidAndroid Development

How To Integrate onesignal push notification in AndroidAndroid Development
Add OneSignal dependency and plugin to your build.Gradle app-level.
apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin' dependencies { implementation 'com.onesignal:OneSignal:3.12.6' }
buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:4.1.0' classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.4, 0.99.99]' } }
- login your OneSignal Account than create an app
- Enter Your Android Application Name & Select platform Google Android(FCM)
- Generate a Firebase Server Key Read the documentation.
- Enter your Firebase Server Key & Firebase Sender ID.
Step: 3 Add Your Created Onesignal App ID
android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { applicationId "com.myapplication.app" minSdkVersion 17 targetSdkVersion 30 versionCode 1 versionName "1.0.0" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" manifestPlaceholders = [onesignal_app_id : "Enter Your App ID", onesignal_google_project_number: " Enter Firebase Sender ID"] } buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
import android.app.Application; import android.content.Context; import androidx.multidex.MultiDex; import com.onesignal.OneSignal; public class MyApplication extends Application { public static Context context; @Override public void onCreate() { super.onCreate(); context = getApplicationContext(); context = this; OneSignal.startInit(this) .inFocusDisplaying(OneSignal.OSInFocusDisplayOption.Notification) .unsubscribeWhenNotificationsAreDisabled(true) .init(); } public static Context getContext() { return context; } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.myapplication.app"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:name="com.myapplication.app.MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:requestLegacyExternalStorage="true" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name="com.myapplication.app.activity.SplashActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
How to Create Floating Widget in AndroidAndroid Development

How to Create Floating Widget in AndroidAndroid Development
Service stops are one of the biggest problems when you clear the application from background functions.
public class FloatingViewService extends Service { private WindowManager mWindowManager; private View mFloatingView; private View floatingButton; private final static float CLICK_DRAG_TOLERANCE = 10; private float downRawX, downRawY; private float dX, dY; int LAYOUT_FLAG; private SpeechRecognizer speechRecognizer; public FloatingViewService() { } Context context; public FloatingViewService(Context applicationContext) { super(); context = applicationContext; Log.i("HERE", "here service created!"); } @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { KeyguardManager myKM = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE); if( myKM.inKeyguardRestrictedInputMode()) { Intent i = new Intent(this,FloatingViewService.class); startService(i); // //it is locked } else { Intent i = new Intent(this, FloatingViewService.class); startService(i); //it is not locked } return START_STICKY; } @Override public void onCreate() { super.onCreate(); mFloatingView = LayoutInflater.from(this).inflate(R.layout.floating_layout, null); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; } else { LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE; } final WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, LAYOUT_FLAG, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mWindowManager.addView(mFloatingView, params); floatingButton.setOnTouchListener(new View.OnTouchListener() { private int initialX; private int initialY; private float initialTouchX; private float initialTouchY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: initialX = params.x; initialY = params.y; initialTouchX = event.getRawX(); initialTouchY = event.getRawY(); downRawX = event.getRawX(); downRawY = event.getRawY(); dX = v.getX() - downRawX; dY = v.getY() - downRawY; return true; case MotionEvent.ACTION_UP: float upRawX = event.getRawX(); float upRawY = event.getRawY(); float upDX = upRawX - downRawX; float upDY = upRawY - downRawY; return true; case MotionEvent.ACTION_MOVE: params.x = initialX + (int) (event.getRawX() - initialTouchX); params.y = initialY + (int) (event.getRawY() - initialTouchY); mWindowManager.updateViewLayout(mFloatingView, params); return true; } return false; } }); } @Override public void onDestroy() { super.onDestroy(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.endless"> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"></uses-permission> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.WAKE_LOCK" /> <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"> <service android:name=".FloatingViewService" android:enabled="true" android:exported="false"> </service> <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>
You can use the following code to check if the service is running. If the service is already in running mode, it does not need to be restarted otherwise start in your MainActivity.
FloatingViewService mFloatingService = new FloatingViewService(getApplicationContext()); Intent mServiceIntent = new Intent(getApplicationContext(), mFloatingService.getClass()); if (!isMyServiceRunning(mFloatingService.getClass())) { startService(mServiceIntent); }
Method isMyServiceRunning() is below add this in your MainActivity. private boolean isMyServiceRunning(Class<?> serviceClass) { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (serviceClass.getName().equals(service.service.getClassName())) { Log.i ("isMyServiceRunning?", true+""); return true; } } Log.i ("isMyServiceRunning?", false+""); return false; }
<?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" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <RelativeLayout android:id="@+id/rl_close_button" android:layout_width="100dp" android:layout_height="wrap_content"> <RelativeLayout android:id="@+id/relativeLayoutParent" android:layout_width="80dp" android:layout_height="70dp"> <RelativeLayout android:layout_width="70dp" android:layout_height="70dp" android:background="@drawable/floating_round_main_shape"> <RelativeLayout android:layout_width="50dp" android:layout_height="50dp" android:layout_centerInParent="true" android:background="@drawable/floating_inner_round_shape"> <ImageView android:layout_width="25dp" android:layout_height="25dp" android:layout_centerInParent="true" android:src="@drawable/ic_voice_icon" /> </RelativeLayout> </RelativeLayout> </RelativeLayout> </RelativeLayout> </RelativeLayout>
I hope it will help these services.
Note:-This service will run better in Oreo and above versions.
Send Device-to-Device Push Notification using Firebase Cloud MessagingAndroid Development

Send Device-to-Device Push Notification using Firebase Cloud MessagingAndroid Development
Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you deliver messages for free.
It allows you to send push notifications from the Firebase console or from the application server or some trusted server where logic runs.
Step 1:- Create a new Android Studio Project
First, create a new Android Studio project and add the dependencies. First set up Firebase in your project. You can find a good tutorial.
Add Firebase messaging dependency to your app-level.
build.Gradle
dependencies {
implementation 'com.google.firebase:firebase-messaging:19.0.1'
}
Step 2: Create a Firebase Service
The next step is to create Firebase Services:- MyFirebaseInstanceIDService
and MyFirebaseMessagingService
. first MyFirebaseInstanceIDService
service will handle the device registration process and the second MyFirebaseInstanceIDService
will handle the reception and display of notifications. The services have no visual interface and are used for operations that run in the background.
To create a service, right-click and select the Applications folder New -> Service -> Service.
Type in your service name, and click the Finish button. Repeat the same steps for the second service.
AndroidManifest.xml file and update your service declarations under the application tag. Also, add INTERNET
and CLOUD TO DEVICE MESSAGING
permissions so your app can interact with the FCM server.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exmple.notify">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<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>
<service android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service
android:name=".MyFirebaseMessagingService"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
</application>
</manifest>
To handle the device registration process, MyFirebaseInstanceIDService
must increase the FireBaseInstenside service class. Under this service, override the tokenrefresh()
method so that whenever the system decides to refresh the tokens, it will be requested. This usually happens when the user installs/reinstalls the application or when the user clears the application data.
Since you are sending notifications between devices, each user must subscribe to an issue with a different user_id
. This ensures that users receive notifications sent to topics that match their user_id
. Here is the implementation of MyFirebaseInstanceIDSericiclass
.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private final String ADMIN_CHANNEL_ID = "admin_channel";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
final Intent intent = new Intent(this, MainActivity.class);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int notificationID = new Random().nextInt(3000);
/*
Apps targeting SDK 26 or above (Android O) must
implement notification channels and add their notifications to at least one of them. Therefore, confirm if the version is Oreo or higher, then setup notification channel
*/
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
setupChannels(notificationManager);
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.drawable.notify_icon);
Uri notificationSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIF CATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, ADMIN_CHANNEL_ID)
.setSmallIcon(R.drawable.notify_icon)
.setLargeIcon(largeIcon)
.setContentTitle(remoteMessage.getData().get("title"))
.setContentText(remoteMessage.getData().get("message"))
.setAutoCancel(true)
.setSound(notificationSoundUri)
.setContentIntent(pendingIntent);
// Set notification color to match your app color template
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
notificationBuilder.setColor(getResources().getColor(R.color.colorPrimaryDark));
}
notificationManager.notify(notificationID, notificationBuilder.build());
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void setupChannels(NotificationManager notificationManager) {
CharSequence adminChannelName = "New notification";
String adminChannelDescription = "Device to device notification ";
NotificationChannel adminChannel;
adminChannel = new NotificationChannel(ADMIN_CHANNEL_ID, adminChannelName, NotificationManager.IMPORTANCE_HIGH);
adminChannel.setDescription(adminChannelDescription);
adminChannel.enableLights(true);
adminChannel.setLightColor(Color.RED);
adminChannel.enableVibration(true);
if (notificationManager != null) {
notificationManager.createNotificationChannel(adminChannel);
}
}
}
Step 4: Implement the notification sending logic
This is the most important part of the whole article. This is where you define the content of the instruction and how it will be modeled. However, before you dive into coding, follow these steps to get your server key from the Firebase console.
Navigate to the Cloud Messaging tab, and copy your Server key
Implement the Sending Logic:
An FCM server with the following request properties only needs an HTTP
post request to send a push notification:
Method Type: POST
URL: https://fcm.googleapis.com/fcm/send
Headers:
Authorization: key="Firebase server key" Content-Type: application/json
Body:
{
"to": "/topics/notification_userId",
"data": {
"title": "Notification title",
"message": "Notification message",
"key1" : "value1",
"key2" : "value2" //additional data you want to pass
}
}
With these concepts in mind, you will first create a JsonObject of Notification body within your activity class. This object budget will contain the subject of the receiver, the title of the notification, the notification message, and the other key/value pair you want to add.
public class MainActivity extends AppCompatActivity {
EditText edtTitle;
EditText edtMessage;
final private String FCM_API = "https://fcm.googleapis.com/fcm/send";
final private String serverKey = "key=" + "Your Firebase server key";
final private String contentType = "application/json";
final String TAG = "NOTIFICATION TAG";
String NOTIFICATION_TITLE;
String NOTIFICATION_MESSAGE;
String TOPIC;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edtTitle = findViewById(R.id.edtTitle);
edtMessage = findViewById(R.id.edtMessage);
Button btnSend = findViewById(R.id.btnSend);
btnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TOPIC = "/topics/userABC"; //topic must match with what the receiver subscribed to
NOTIFICATION_TITLE = edtTitle.getText().toString();
NOTIFICATION_MESSAGE = edtMessage.getText().toString();
JSONObject notification = new JSONObject();
JSONObject notifcationBody = new JSONObject();
try {
notifcationBody.put("title", NOTIFICATION_TITLE);
notifcationBody.put("message", NOTIFICATION_MESSAGE);
notification.put("to", TOPIC);
notification.put("data", notifcationBody);
} catch (JSONException e) {
Log.e(TAG, "onCreate: " + e.getMessage() );
}
sendNotification(notification);
}
});
}
private void sendNotification(JSONObject notification) {
...
}
}
The next step is to request the network server using the library volley, then use the parameters to the root server will request notification on the target device.
public class MainActivity extends AppCompatActivity {
....
private void sendNotification(JSONObject notification) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(FCM_API, notification,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response)
{
Log.i(TAG, "onResponse: " + response.toString());
edtTitle.setText("");
edtMessage.setText("");
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "Request error", Toast.LENGTH_LONG).show();
Log.i(TAG, "onErrorResponse: Didn't work");
}
}){
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Authorization", serverKey);
params.put("Content-Type", contentType);
return params;
}
};
MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjectRequest);
}
}
Finally, add a MySingleton class that will serve as a request queue for instruction requests.
public class MySingleton {
private static MySingleton instance;
private RequestQueue requestQueue;
private Context ctx;
private MySingleton(Context context) {
ctx = context;
requestQueue = getRequestQueue();
}
public static synchronized MySingleton getInstance(Context context) {
if (instance == null) {
instance = new MySingleton(context);
}
return instance;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
return requestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
}
With it, you're done creating your app. You can start sending push notifications between devices without typing any server-side code. Always make sure that the notification will not be delivered to you if the subject of the recipient is correct. If you do everything right, you will get the same result.