5

下面是启动前台服务的代码。它适用于三星、moto、Vivo、Oppo 等许多设备,也适用于 Android 版本的牛轧糖和奥利奥,但不适用于一加设备。谁能告诉我是否需要任何额外的更改或许可才能在一加设备中运行,或者是否有任何模拟器支持一加手机。

public class ForegroundService extends Service {

private Context ctx;
private static final String PRIMARY_NOTIF_CHANNEL = "default";

@Override
public void onCreate() {
    super.onCreate();
    ctx = this;
    createNotificationService();
}

private void createNotificationService(){

    TelephonyManager mTelephonyManager = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
    if(mTelephonyManager != null)
        mTelephonyManager.listen(new CellTowerStateListener(ctx), PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);

    Intent notificationIntent = new Intent(this, MainActivity.class);
    notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    //PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    RemoteViews notificationView = new RemoteViews(this.getPackageName(), R.layout.notification);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        setupChannel();
    }

    Notification notification = new NotificationCompat.Builder(this, PRIMARY_NOTIF_CHANNEL)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setColor(Color.parseColor("#00f6d8"))
            .setContent(notificationView)
            .setPriority(Notification.PRIORITY_MIN)
            .setOngoing(true).build();

    startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE, notification);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
    return START_REDELIVER_INTENT;
}

private void setupChannel(){
    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    NotificationChannel chan1;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        chan1 = new NotificationChannel(
                PRIMARY_NOTIF_CHANNEL,
                PRIMARY_NOTIF_CHANNEL,
                NotificationManager.IMPORTANCE_NONE);

        chan1.setLightColor(Color.TRANSPARENT);
        chan1.setLockscreenVisibility(Notification.VISIBILITY_SECRET);

        if(notificationManager != null)
            notificationManager.createNotificationChannel(chan1);
    }
}


@Override
public IBinder onBind(Intent intent) {
    // Used only in case of bound services.
    return null;
}

}

4

2 回答 2

7

所以我在一小时前解决了这个问题:

显现

<application
    android:name=".AppNotification"
    android:allowBackup="true"
    android:icon="@mipmap/pro_icon"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/pro_icon"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
<service
        android:name=".services.TrackingBackgroundService"
        android:enabled="true"
        android:exported="true" />

应用程序 - 创建通知通道

public class AppNotification extends Application {

public static final String CHANNEL_ID = "AppNotificationChannel";
private void CreateNotificationChannel() {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
        NotificationChannel serviceChannel = new NotificationChannel(
                CHANNEL_ID,
                "App Notification",
                NotificationManager.IMPORTANCE_HIGH
        );
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(serviceChannel);
    }
}

}

活动

首先,您需要要求用户禁用电池优化:

Intent intent = new Intent();
    String packageName = this.getPackageName();
    PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
    if (pm.isIgnoringBatteryOptimizations(packageName))
        intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
    else {
        intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + packageName));
        startActivity(intent);
    }

那么你需要像这样启动服务来处理不同的版本:

public void startService() {
    Intent serviceIntent = new Intent(InitSkipperActivity.this, TrackingBackgroundService.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(serviceIntent);
    } else {
        startService(serviceIntent);
    }
}

服务

public class TrackingBackgroundService extends Service {

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

@Override
public void onCreate() {
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Intent notificationIntent = new Intent(this, TrackingActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("title")
            .setContentText("content")
            .setSmallIcon(R.mipmap.pro_icon)
            .setPriority(5)
            .setContentIntent(pendingIntent)
            .build();
    startForeground(1, notification);

    return START_STICKY;
}

}

在此之后,您需要使用 android profiler 测试您的服务:

当我离线跟踪时,我的应用程序的 CPU 使用率异常,并且在 Oppo、OnePlus、小米和三星上使用 50% 到 60% 的 CPU。发现这是一些我称之为中断但仍在运行的线程

在学会使用之后,开始记录你的应用程序片段并分析它们,你有两个不错的选择:

  • 示例 Java 方法

  • 跟踪 Java 方法

Android Logcat 很高兴看到 BG 检测到 oneplus 试图删除您的服务以及如果需要您的应用程序。

PS:BGDetect消除无所畏惧。我需要将我的在线和离线跟踪性能在应用程序中平均提高 20% 到 30%,在睡眠中提高 15% 到 20%,然后 OnePlus 和 Oppo 停止杀死我而不给我重新启动服务的机会。

正如您可能已经注意到,当这些操作系统想要杀死他们从应用程序而不是服务启动的东西时,请记住:如果您这样做,请不要将应用程序绑定到服务我不知道为什么,但操作系统甚至更多狠。

BG-Detect 太多了->他们应该在重新实现该功能时向 android 开发人员发出警告

PPS 这太多了,但我戴上我的帽子 OnePlus BugHunters,它的实施很好。

希望我能帮上忙。

在 OP3 Oreo 8.0.1 上测试

已编辑

重启时的 OnePlus 会将您的应用再次优化。正在测试解决问题

于 2019-05-18T01:16:01.973 回答
0

使用我的方法在所有设备上工作

 private void checkOptimization() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        String packageName = getApplicationContext().getPackageName();
        PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
        if (pm != null) {
            if (!pm.isIgnoringBatteryOptimizations(packageName)) {
                Intent intent = new Intent();
                intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + getPackageName()));
                startActivity(intent);
            }
        }
    }

}
于 2020-06-18T10:06:19.537 回答