Всегда показывать службу в панели уведомлений

Я хочу добавить свое приложение в панель уведомлений, чтобы он всегда показывался, как некоторые приложения в магазине Google Play.

Я хочу, чтобы это было похоже на этот снимок экрана:

enter image description here

Я хочу, чтобы мое уведомление не очищалось, и мое приложение должно быть открыто при нажатии на уведомление.

Здесь мой код класса обслуживания:

package com.demo;

import java.util.Random;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.widget.Toast;

public class ServiceExample extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(this,"Service Created",300).show();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this,"Service Destroy",300).show();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        Toast.makeText(this,"Service LowMemory",300).show();
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Toast.makeText(this,"Service start",300).show();
        Notification notification = new Notification(R.drawable.ic_launcher,
                "Rolling text on statusbar", System.currentTimeMillis());

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, ServiceDemoActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

        notification.setLatestEventInfo(this,
                "Notification title", "Notification description", contentIntent);

        startForeground(1, notification);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Toast.makeText(this,"task perform in service",300).show();
        /*ThreadDemo td=new ThreadDemo();
        td.start();*/
        Notification notification = new Notification(R.drawable.ic_launcher,
                "Rolling text on statusbar", System.currentTimeMillis());

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, ServiceDemoActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

        notification.setLatestEventInfo(this,
                "Notification title", "Notification description", contentIntent);

        startForeground(1, notification);

        return super.onStartCommand(intent, flags, startId);
    }

    private class ThreadDemo extends Thread{
        @Override
        public void run() {
            super.run();
            try{
            sleep(70*1000); 
            handler.sendEmptyMessage(0);
            }catch(Exception e){
                e.getMessage();
            }
        }
    }
   private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        showAppNotification();
    }
   };

   void showAppNotification() {
       try{
        NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        // The PendingIntent to launch our activity if the user selects this
        // notification.  Note the use of FLAG_CANCEL_CURRENT so that, if there
        // is already an active matching pending intent, cancel it and replace
        // it with the new array of Intents.
//      PendingIntent contentIntent = PendingIntent.getActivities(this, 0,
//             "My service completed", PendingIntent.FLAG_CANCEL_CURRENT);

        // The ticker text, this uses a formatted string so our message could be localized
        String tickerText ="djdjsdjkd";

        // construct the Notification object.
        Notification notif = new Notification(R.drawable.ic_launcher, tickerText,
                System.currentTimeMillis());

        // Set the info for the views that show in the notification panel.
//      notif.setLatestEventInfo(this, from, message, contentIntent);

        // We'll have this notification do the default sound, vibration, and led.
        // Note that if you want any of these behaviors, you should always have
        // a preference for the user to turn them off.
        notif.defaults = Notification.DEFAULT_ALL;

        // Note that we use R.layout.incoming_message_panel as the ID for
        // the notification.  It could be any integer you want, but we use
        // the convention of using a resource id for a string related to
        // the notification.  It will always be a unique number within your
        // application.
        nm.notify(0, notif);
       }catch(Exception e){
           e.getMessage();
       }
    }
}

И я объявляю свою службу в файле манифеста проекта:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.demo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".ServiceDemoActivity"
            android:label="@string/app_name"  >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".ServiceExample"></service>
    </application>

</manifest>

Здесь мой класс для запуска и остановки службы:

package com.demo;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ReceiverCallNotAllowedException;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

public class ServiceDemoActivity extends Activity implements OnClickListener {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.start).setOnClickListener(this);
        findViewById(R.id.stop).setOnClickListener(this);
    }

    private Intent inetnt;
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.start:

            inetnt=new Intent(this,ServiceExample.class);
            startService(inetnt);
            break;
        case R.id.stop:

            inetnt=new Intent(this,ServiceExample.class);
            stopService(inetnt);
            break;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
//      
    }
}

Здесь мой код макета:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="StartService" 
        android:id="@+id/start"/>

        <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="StopService"
        android:id="@+id/stop" />

</LinearLayout>

Ответ 1

Если вы хотите, чтобы ваше приложение постоянно присутствовало в строке состояния, вам необходимо написать службу и вызвать startForeground(id, notification) в методах onStart(...) и onStartCommand(...) и соответственно вызвать метод stopForeground() в onDestroy() метод службы.

Идентификатор - это целое число, которое вы можете назначить уведомлению, а уведомление - это объект Notification (вы можете прочитать об этом здесь: http://developer.android.com/guide/topics/ui/notifiers/notifications.html).

Таким образом, пока ваша служба будет запущена, появится сообщение о статусной строке.

Notification notification = new Notification(R.drawable.statusbar_icon,
        "Rolling text on statusbar", System.currentTimeMillis());

PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
        new Intent(this, YourActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

notification.setLatestEventInfo(this,
        "Notification title", "Notification description", contentIntent);

startForeground(1, notification);

Вы можете поместить этот код в методы службы onStart(...) и onStartCommand(...).

Также вы можете узнать больше об услугах здесь: http://developer.android.com/reference/android/app/Service.html

Ответ 2

Чтобы ваше уведомление всегда присутствовало, вы должны установить эти два флага:

notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;

Обратите внимание, что при установке службы на переднем плане также вы получите постоянное событие, это очень неуместно, если вам действительно не нужно, чтобы ваша служба выполнялась на переднем плане. Музыкальный проигрыватель - хороший пример приложения, которое должно это сделать - у пользователя есть ожидание, что их музыка будет воспроизводиться без перерыва, даже когда вы делаете много других вещей с устройством.

Большинство служб, однако, могут позволить себе временно остановить систему при низкой памяти, а затем автоматически перезагрузиться, когда память снова будет доступна. Поэтому правильный способ подумать об этом состоит в том, чтобы отделить две идеи.

  • Если вы хотите, чтобы ваше уведомление всегда было видимым, используйте два упомянутых флага.
  • Если вам также понадобится ваша служба для запуска на переднем плане, вы можете и должны вызывать Service.startForeground(), но не думайте об этом как способе получения текущего уведомления.

Ответ 3

Здесь пример с использованием класса NotificationCompact.Builder, который является последней версией для создания уведомлений.

private void startNotification() {

     //Sets an ID for the notification

  int mNotificationId = 001;

    // Build Notification , setOngoing keeps the notification always in status bar
    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ldb)
                    .setContentTitle("Stop LDB")
                    .setContentText("Click to stop LDB")
                    .setOngoing(true);




    // Gets an instance of the NotificationManager service
    NotificationManager mNotifyMgr =
            (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    // Build the notification and issues it.
    mNotifyMgr.notify(mNotificationId, mBuilder.build());


}

Ответ 4

Просто используйте ниже код, чтобы всегда показывать панель уведомлений.

    Notification.Builder builder = new Notification.Builder(MainActivity.this);
    builder.setSmallIcon(R.mipmap.ic_launcher)
            .setContentText("Call Recorder")
            .setAutoCancel(false);
    Notification notification = builder.getNotification();

    notification.flags |= Notification.FLAG_NO_CLEAR
            | Notification.FLAG_ONGOING_EVENT;

    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    notificationManager.notify(1, notification);