Я исследовал это на пару дней и получил решение. Теперь в Android O вы можете установить ограничение фона как ниже
Служба, вызывающая класс обслуживания
Intent serviceIntent = new Intent(SettingActivity.this,DetectedService.class);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){
SettingActivity.this.startForegroundService(serviceIntent);
}else{
startService(serviceIntent);
}
и класс обслуживания, должна быть как
public class DetectedService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
int NOTIFICATION_ID = (int) (System.currentTimeMillis()%10000);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_ID, new Notification.Builder(this).build());
}
// Do whatever you want to do here
}
}
Это происходит потому, что команда, переданная в Runtime.exec(String)
, не выполняется в оболочке. Оболочка выполняет множество общих служб поддержки для программ, и когда оболочка не собирается их выполнять, команда будет терпеть неудачу.
Команда будет если это зависит от свойств оболочки. Оболочка имеет много общих и полезных вещей, о которых мы обычно не думаем:
"My File.txt"
остается единственным аргументом. Runtime.exec(String)
наивно разбивается на пробелы и передает это как два отдельных имени файла. Это явно не получается. ls *.doc
, оболочка перезаписывает ее в ls letter.doc notes.doc
. Runtime.exec(String)
нет, он просто передает их в качестве аргументов. ls
не знает, что *
, поэтому команда не работает. ls mydir > output.txt
, оболочка открывает «output.txt» для вывода команды и удаляет ее из командной строки, предоставляя ls mydir
. Runtime.exec(String)
нет. Он просто передает их в качестве аргументов. ls
не знает, что означает >
, поэтому команда не работает. ls "$HOME"
или ls "$(pwd)"
, оболочка перезаписывает его на ls /home/myuser
. Runtime.exec(String)
нет, он просто передает их в качестве аргументов. ls
не знает, что означает $
, поэтому команда не работает. Существует два способа выполнения произвольно сложных команд :
Простая и неаккуратная: делегировать оболочку.
Вы можете просто использовать Runtime.exec(String[])
(обратите внимание на параметр массива) и передать команду непосредственно оболочке, которая может выполнять весь тяжелый подъем:
// Simple, sloppy fix. May have security and robustness implications
String myFile = "some filename.txt";
String myCommand = "cp -R '" + myFile + "' $HOME 2> errorlog";
Runtime.getRuntime().exec(new String[] { "bash", "-c", myCommand });
Безопасный и надежный: возьмите на себя ответственность оболочки.
Это не исправление, которое можно механически применить, но требует понимания модели исполнения Unix, каких оболочек и как вы можете сделать то же самое. Тем не менее, вы можете получить надежное, надежное и надежное решение, сняв оболочку с рисунка. Этому способствует ProcessBuilder
.
Команда из предыдущего примера, которая требует, чтобы кто-то обрабатывал 1. кавычки, 2. переменные и 3. перенаправления, может быть записан как:
String myFile = "some filename.txt";
ProcessBuilder builder = new ProcessBuilder(
"cp", "-R", myFile, // We handle word splitting
System.getenv("HOME")); // We handle variables
builder.redirectError( // We set up redirections
ProcessBuilder.Redirect.to(new File("errorlog")));
builder.start();