How do I show text in android system status bar
I'm trying to develop an app for Android Nougat and I want to show some info/text in the status bar generating from a android service routine. So my problem is, I don't know how to show the text in the status bar.
I added a sample image to show what exactly do I mean (red circle). I know it is possible, because I saw it in a battery monitor app from play store.
I already tried NotificationCombat.Builder, but I think this is not the right way. Maybe an overlay is, but after searching I didn't find something.
Can someone show me how to do it or give me a hint, please?
Edit: Here my test code for NotificationCompat.Builder
MainActivity.java
import android.app.Notification;
import android.app.NotificationManager;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
public class MainActivity extends AppCompatActivity
{
private final int NOTIFICATION_ID = 10;
@Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Value");
mBuilder.setContentText("123");
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
mBuilder.setOngoing(true);
mBuilder.setAutoCancel(false);
//Intent resultIntent = new Intent(this, MainActivity.class);
//PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(NOTIFICATION_ID, notification);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#000000"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:weightSum="100" >
<TextView
android:id="@+id/tv_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>
Result:
I do found a solution, the keyword is overlay with a floating window.
int statusBarHeight = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) statusBarHeight = getResources().getDimensionPixelSize(resourceId);
final WindowManager.LayoutParams parameters = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
statusBarHeight,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, // Allows the view to be on top of the StatusBar
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, // Keeps the button presses from going to the background window and Draws over status bar
PixelFormat.TRANSLUCENT);
parameters.gravity = Gravity.TOP | Gravity.CENTER;
LinearLayout ll = new LinearLayout(this);
ll.setBackgroundColor(Color.TRANSPARENT);
LinearLayout.LayoutParams layoutParameteres = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
ll.setLayoutParams(layoutParameteres);
TextView tv = new TextView(this);
ViewGroup.LayoutParams tvParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
tv.setLayoutParams(tvParameters);
tv.setTextColor(Color.WHITE);
tv.setGravity(Gravity.CENTER);
tv.setText("123");
ll.addView(tv);
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
windowManager.addView(ll, parameters);
Well, I did it. I used the way of converting text
to an icon and then displaying it on the status bar. some members are trying to overlay the status bar which android does not allow(SDK>=22), I don't know if that worked for someone or not. But converting text
to an icon worked for me perfectly. Tested it on Oreo
Pseudo code
- Convert text to
Bitmap
- Then convert
Bitmap
to icon. - show that icon on statusBar.
Output
Here is the code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
displayNotification("5F");
}
public void displayNotification(String text) {
Notification.Builder builder = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
builder = new Notification.Builder(this, CHANNEL_ID);
}
//convert text to bitmap
Bitmap bitmap = createBitmapFromString(text.trim());
//setting bitmap to staus bar icon.
builder.setSmallIcon(Icon.createWithBitmap(bitmap));
builder.setContentTitle("Simple Notification");
builder.setContentText("This is a simple notification");
builder.setPriority(Notification.PRIORITY_MAX);
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(this);
notificationManagerCompat.notify(NOTIFICATION_ID, builder.build());
createNotificationChannel();
}
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (VERSION.SDK_INT >= VERSION_CODES.O) {
CharSequence name = "testing";
String description = "i'm testing this notification";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
assert notificationManager != null;
notificationManager.createNotificationChannel(channel);
}
}
private Bitmap createBitmapFromString(String inputNumber) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(100);
paint.setTextAlign(Paint.Align.CENTER);
Rect textBounds = new Rect();
paint.getTextBounds(inputNumber, 0, inputNumber.length(), textBounds);
Bitmap bitmap = Bitmap.createBitmap(textBounds.width() + 10, 90,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawText(inputNumber, textBounds.width() / 2 + 5, 70, paint);
return bitmap;
}
If someone knows a better way then please do mention