Совместимость с POSIX:
command -v <the_command>
Для bash
определенных сред:
hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords
Избегайте which
. Мало того, что это внешний процесс, который вы запускаете для выполнения очень мало (это означает, что встроенные функции, такие как hash
, type
или command
, намного дешевле), вы также можете полагаться на встроенные функции, чтобы фактически делать то, что вы хотите, в то время как эффекты внешних команд могут легко варьироваться от системы к системе.
Зачем нужна помощь?
which
, который даже не устанавливает статус выхода , что означает, что if which foo
там даже не работает, и всегда будет сообщать, что foo
существует, даже если это не так (обратите внимание, что некоторые оболочки POSIX тоже делают это для hash
). which
обычным и злым, как изменение вывода или даже привязка к менеджеру пакетов. Итак, не используйте which
. Вместо этого используйте один из них:
$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
(Незначительная сторона: некоторые подскажут, что 2>&-
тот же 2>/dev/null
, но короче - это неверно . 2>&-
закрывает FD 2, который вызывает ошибку в программе, когда он пытается записать в stderr, что сильно отличается от успешной записи на него и отбрасывания вывода (и опасно!))
Если ваш хэш-сигнал /bin/sh
, тогда вы должны заботиться о том, что говорит POSIX. Коды выхода type
и hash
не очень хорошо определены POSIX, и hash
, как видно, успешно завершает работу, когда команда не существует (еще не видели этого с type
). Статус выхода command
хорошо определен POSIX, поэтому, вероятно, наиболее безопасно использовать.
Если ваш скрипт использует bash
, хотя правила POSIX больше не имеют значения, и оба type
и hash
становятся абсолютно безопасными в использовании. type
теперь имеет -P
, чтобы искать только PATH
, а hash
имеет побочный эффект, что местоположение команды будет хэшировано (для более быстрого поиска в следующий раз, когда вы его используете), что обычно хорошо, поскольку вы, вероятно, проверяете его существование, чтобы фактически использовать его.
Как простой пример, вот функция, которая запускает gdate
, если она существует, в противном случае date
:
gnudate() {
if hash gdate 2>/dev/null; then
gdate "$@"
else
date "$@"
fi
}
То, что будет устаревать, - это возможность для фонового приложения получать изменения состояния сетевого подключения.
Поскольку Дэвид Вассер сказал, что вы все равно можете получить уведомление об изменениях в подключении, если приложение (не уничтожен), и вы зарегистрировали ваш приемник программно с его контекстом, а не выполняете его в манифесте.
Или вы можете использовать NetworkCallback
g2]. В частности, вам нужно будет переопределить onAvailable для связанных изменений состояния.Позвольте мне быстро отредактировать фрагмент:
public class ConnectionStateMonitor extends NetworkCallback {
final NetworkRequest networkRequest;
public ConnectionStateMonitor() {
networkRequest = new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();
}
public void enable(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.registerNetworkCallback(networkRequest , this);
}
// Likewise, you can have a disable method that simply calls ConnectivityManager#unregisterCallback(networkRequest) too.
@Override
public void onAvailable(Network network) {
// Do what you need to do here
}
}
Документация для Android N:
Приложения, ориентированные на Android N, не получают трансляции CONNECTIVITY_ACTION, даже если они имеют манифестные записи для запроса уведомления об этих событиях. Приложения, запущенные на переднем плане, все равно могут прослушивать CONNECTIVITY_CHANGE в своем основном потоке, если они запрашивают уведомление с помощью BroadcastReceiver.
blockquote>Это означает, что вы все равно можете зарегистрировать
BroadcastReceiver
, если приложение работает в на переднем плане, чтобы обнаружить изменения в сетевом подключении.
Я столкнулся с той же проблемой несколько дней назад, и решил использовать эту библиотеку Android-Job
В этой библиотеке используются JobSchedular
, GcmNetworkManager
и BroadcastReceiver
в зависимости от версии Android, на которой запущено приложение.
Запуск задания довольно легко
new JobRequest.Builder(DemoSyncJob.TAG)
.setRequiresCharging(true)
.setRequiresDeviceIdle(false)
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED) // this is what gets the job done
.build()
.schedule();