简体   繁体   English

如何在android系统状态栏中显示文字

[英]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.我正在尝试为 Android Nougat 开发一个应用程序,我想在从 android 服务例程生成的状态栏中显示一些信息/文本。 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.我知道这是可能的,因为我在 Play 商店的电池监视器应用程序中看到了它。

样本

I already tried NotificationCombat.Builder, but I think this is not the right way.我已经尝试过 NotificationCombat.Builder,但我认为这不是正确的方法。 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编辑:这是我的 NotificationCompat.Builder 测试代码

MainActivity.java主活动.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 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:结果:

结果 1

结果 2

I do found a solution, the keyword is overlay with a floating window .我确实找到了解决方案,关键字是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 used the way of converting text to an icon and then displaying it on the status bar.嗯,我用的是把text转成图标,然后显示在状态栏上的方式。 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.一些成员试图覆盖android不允许的状态栏(SDK>=22),我不知道这是否对某些人有用。 But converting text to an icon worked for me perfectly.但是将text转换为图标非常适合我。 Tested it on OreoOreo上测试过

Pseudo code伪代码

  1. Convert text to Bitmap将文本转换为Bitmap
  2. Then convert Bitmap to icon.然后将Bitmap转换为图标。
  3. 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如果有人知道更好的方法,请提及

You can find your answer in the doc, here: https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html您可以在此处的文档中找到答案: https ://developer.android.com/reference/android/support/v4/app/NotificationCompat.html

Edit:: Well, the answer is in the doc.编辑:嗯,答案在文档中。 However, after a good bit of research and digging, it seems as though the consensus amongst the community is that this is not possible for just any application.然而,经过大量的研究和挖掘,似乎社区之间的共识是这对任何应用程序都是不可能的。 Only specific icons can be placed on the right side of the status bar (ie Clock, Weather, System info, etc...).只有特定的图标可以放置在状态栏的右侧(即时钟、天气、系统信息等...)。

I'm sorry there isn't a more exciting answer, but at least you can stop stressing out about why you can't figure it out.很抱歉,没有比这更令人兴奋的答案了,但至少您可以不再为自己无法弄明白的原因而苦恼。

Edit 2:: Apparently, pre-lollipop devices had access to private apis that allowed you to work with system icons (again, think about the alarm icon).编辑 2:: 显然,棒棒糖之前的设备可以访问允许您使用系统图标的私有 api(再次,想想警报图标)。 Afterward, the apis were removed.之后,这些 api 被删除了。 This stackoverflow post goes over the whole situation pretty extensively.这篇stackoverflow 帖子非常广泛地介绍了整个情况。

Edit 3:: If you can live with placing you icon on the left side of the status bar you can convert text to bitmap like this:编辑 3:: 如果您可以将图标放在状态栏的左侧,您可以像这样将文本转换为位图:

 TextView textView = new TextView(activity.getContext());
 textView.setText("Hello World");
 textView.setDrawingCacheEnabled(true);
 textView.destroyDrawingCache();
 textView.buildDrawingCache();
 Bitmap bitmap = getTransparentBitmapCopy(textView.getDrawingCache());
 private Bitmap getTransparentBitmapCopy(Bitmap source) { 
    int width = source.getWidth(); 
    int height = source.getHeight(); 
    Bitmap copy = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    int[] pixels = new int[width * height];
    source.getPixels(pixels, 0, width, 0, 0, width, height);
    copy.setPixels(pixels, 0, width, 0, 0, width, height);
    return copy;
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM