したがって、このメソッドをどこで/どのように実装してサービスをフォアグラウンドで実行するかはわかりません。現在、別のアクティビティで次のようにサービスを開始しています。
Intent i = new Intent(context, myService.class);
context.startService(i);
そして、myServicesのonCreate()でstartForeground()を試してみます...?
Notification notification = new Notification();
startForeground(1, notification);
ええ、私は少し迷ってしまい、これをどのように実装するのか分かりません。
Notification
を完全に埋めることから始めます。 これはサンプルプロジェクトですstartForeground()
の使用方法を示しています。
メインアクティビティから、次のコードでサービスを開始します。
Intent i = new Intent(context, MyService.class);
context.startService(i);
次に、onCreate()
のサービスで通知を作成し、次のようにフォアグラウンドとして設定します。
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.app_icon)
.setContentTitle("My Awesome App")
.setContentText("Doing some work...")
.setContentIntent(pendingIntent).build();
startForeground(1337, notification);
これは、サービスをフォアグラウンドに設定する私のコードです:
private void runAsForeground(){
Intent notificationIntent = new Intent(this, RecorderMainActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText(getString(R.string.isRecording))
.setContentIntent(pendingIntent).build();
startForeground(NOTIFICATION_ID, notification);
}
通知からメインアクティビティを開始できるように、PendingIntentを使用して通知を作成する必要があります。
通知を削除するには、stopForeground(true)を呼び出すだけです。
OnStartCommand()で呼び出されます。次のコードを参照してください: https://github.com/bearstand/greyparrot/blob/master/src/com/xiong/richard/greyparrot/Mp3Recorder.Java
最新バージョンのAndroidで無効なチャンネルIDが原因でRemoteServiceExceptionなどの問題が発生しました。これは私がそれを解決した方法です:
アクティビティ:
override fun onCreate(savedInstanceState: Bundle?) {
val intent = Intent(this, BackgroundService::class.Java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
}
BackgroundService:
override fun onCreate() {
super.onCreate()
startForeground()
}
private fun startForeground() {
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel()
} else {
// If earlier version channel ID is not used
// https://developer.Android.com/reference/Android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(Android.content.Context)
""
}
val notificationBuilder = NotificationCompat.Builder(this, channelId )
val notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(PRIORITY_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build()
startForeground(101, notification)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(): String{
val channelId = "my_service"
val channelName = "My Background Service"
val chan = NotificationChannel(channelId,
channelName, NotificationManager.IMPORTANCE_HIGH)
chan.lightColor = Color.BLUE
chan.importance = NotificationManager.IMPORTANCE_NONE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.createNotificationChannel(chan)
return channelId
}
Java EQUIVALENT
public class YourService extends Service {
// Constants
private static final int ID_SERVICE = 101;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
// do stuff like register for BroadcastReceiver, etc.
// Create the Foreground Service
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? createNotificationChannel(notificationManager) : "";
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(PRIORITY_MIN)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.build();
startForeground(ID_SERVICE, notification);
}
@RequiresApi(Build.VERSION_CODES.O)
private String createNotificationChannel(NotificationManager notificationManager){
String channelId = "my_service_channelid";
String channelName = "My Foreground Service";
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
// omitted the LED color
channel.setImportance(NotificationManager.IMPORTANCE_NONE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationManager.createNotificationChannel(channel);
return channelId;
}
}
RAWA answerに加えて、このコードの平和:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
以下に変更できます。
ContextCompat.startForegroundService(context, yourIntent);
このメソッドの内部を見ると、このメソッドがすべてのチェック作業を行っていることがわかります。
onHandleIntent()
のようにオーバーライドする必要があります
Override
protected void onHandleIntent(@Nullable Intent intent) {
startForeground(FOREGROUND_ID,getNotification()); //<-- Makes Foreground
// Do something
stopForeground(true); // <-- Makes it again a normal Service
}
シンプル。これがgetNotification()
メソッドです
public Notification getNotification()
{
Intent intent = new Intent(this, SecondActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);
NotificationCompat.Builder foregroundNotification = new NotificationCompat.Builder(this);
foregroundNotification.setOngoing(true);
foregroundNotification.setContentTitle("MY Foreground Notification")
.setContentText("This is the first foreground notification Peace")
.setSmallIcon(Android.R.drawable.ic_btn_speak_now)
.setContentIntent(pendingIntent);
return foregroundNotification.build();
}
これが起こる
前景サービス、
通知を提供することにより、ユーザーがバックグラウンドで何かが行われていることを積極的に認識するようにします。
(最も重要なこと)システムがメモリ不足になるとシステムによって殺されない
「OS> = Build.VERSION_CODES.O」の特定のコードサービスクラスを追加 onCreate()
@Override
public void onCreate(){
super.onCreate();
.................................
.................................
//For creating the Foreground Service
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? getNotificationChannel(notificationManager) : "";
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
// .setPriority(PRIORITY_MIN)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.build();
startForeground(110, notification);
}
@RequiresApi(Build.VERSION_CODES.O)
private String getNotificationChannel(NotificationManager notificationManager){
String channelId = "channelid";
String channelName = getResources().getString(R.string.app_name);
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
channel.setImportance(NotificationManager.IMPORTANCE_NONE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationManager.createNotificationChannel(channel);
return channelId;
}
マニフェストファイルにこの権限を追加:
<uses-permission Android:name="Android.permission.FOREGROUND_SERVICE" />
注:アプリがAPIレベル26以上をターゲットにしている場合、アプリ自体がフォアグラウンドにない限り、システムはバックグラウンドサービスの使用または作成に制限を課します。
アプリがフォアグラウンドサービスを作成する必要がある場合、アプリはstartForegroundService()
を呼び出す必要がありますそのメソッドはバックグラウンドサービスを作成しますが、このメソッドはサービスがフォアグラウンドに昇格することをシステムに通知します。
サービスが作成されたら、サービスはそのstartForeground() method within five seconds.
を呼び出す必要があります
私の場合、オレオでサービスを開始するアクティビティがなかったため、まったく異なっていました。
以下は、このフォアグラウンドサービスの問題を解決するために使用した手順です。
public class SocketService extends Service {
private String TAG = this.getClass().getSimpleName();
@Override
public void onCreate() {
Log.d(TAG, "Inside onCreate() API");
if (Build.VERSION.SDK_INT >= 26) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.drawable.ic_launcher);
mBuilder.setContentTitle("Notification Alert, Click Me!");
mBuilder.setContentText("Hi, This is Android Notification Detail!");
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// notificationID allows you to update the notification later on.
mNotificationManager.notify(100, mBuilder.build());
startForeground(100, mBuilder.mNotification);
}
Toast.makeText(getApplicationContext(), "inside onCreate()", Toast.LENGTH_LONG).show();
}
@Override
public int onStartCommand(Intent resultIntent, int resultCode, int startId) {
Log.d(TAG, "inside onStartCommand() API");
return startId;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "inside onDestroy() API");
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
そして、このサービスを開始するために、cmdの下でトリガーしました-
adb -s "+ serial_id +"シェルam startforegroundservice -n com.test.socket.sample/.SocketService
だから、これはOreoデバイスでアクティビティなしでサービスを開始するのに役立ちます:)
使用してサービスのstartCommandの意図を処理します。
stopForeground(true)
この呼び出しはフォアグラウンド状態からサービスを削除するであり、より多くのメモリが必要な場合にサービスを強制終了できます。 これはサービスを停止しません実行を停止します。そのためには、stopSelf()または関連するメソッドを呼び出す必要があります。
値を渡すtrueまたはfalseは、通知を削除するかどうかを示します。
val ACTION_STOP_SERVICE = "stop_service"
val NOTIFICATION_ID_SERVICE = 1
...
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
if (ACTION_STOP_SERVICE == intent.action) {
stopForeground(true)
stopSelf()
} else {
//Start your task
//Send forground notification that a service will run in background.
sendServiceNotification(this)
}
return Service.START_NOT_STICKY
}
DestroyがstopSelf()によって呼び出されたときにタスクを処理します。
override fun onDestroy() {
super.onDestroy()
//Stop whatever you started
}
通知を作成して、サービスをフォアグラウンドで実行し続けます。
//This is from Util class so as not to cloud your service
fun sendServiceNotification(myService: Service) {
val notificationTitle = "Service running"
val notificationContent = "<My app> is using <service name> "
val actionButtonText = "Stop"
//Check Android version and create channel for Android O and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//You can do this on your own
//createNotificationChannel(CHANNEL_ID_SERVICE)
}
//Build notification
val notificationBuilder = NotificationCompat.Builder(applicationContext, CHANNEL_ID_SERVICE)
notificationBuilder.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_location)
.setContentTitle(notificationTitle)
.setContentText(notificationContent)
.setVibrate(null)
//Add stop button on notification
val pStopSelf = createStopButtonIntent(myService)
notificationBuilder.addAction(R.drawable.ic_location, actionButtonText, pStopSelf)
//Build notification
val notificationManagerCompact = NotificationManagerCompat.from(applicationContext)
notificationManagerCompact.notify(NOTIFICATION_ID_SERVICE, notificationBuilder.build())
val notification = notificationBuilder.build()
//Start notification in foreground to let user know which service is running.
myService.startForeground(NOTIFICATION_ID_SERVICE, notification)
//Send notification
notificationManagerCompact.notify(NOTIFICATION_ID_SERVICE, notification)
}
ユーザーが必要なときにサービスを停止するには、通知に停止ボタンを付けます。
/**
* Function to create stop button intent to stop the service.
*/
private fun createStopButtonIntent(myService: Service): PendingIntent? {
val stopSelf = Intent(applicationContext, MyService::class.Java)
stopSelf.action = ACTION_STOP_SERVICE
return PendingIntent.getService(myService, 0,
stopSelf, PendingIntent.FLAG_CANCEL_CURRENT)
}