OnServiceConnected никогда не вызывается после метода bindService
У меня есть особая ситуация:
служба, запущенная широковещательным приемником, начинает свою деятельность. Я хочу, чтобы это мероприятие связывалось с службой. Я решил использовать AIDL, чтобы сделать это возможным. Кажется, что все работает хорошо, за исключением метода bindService()
, вызванного в onCreate()
активности. bindService(), по сути, выбрасывает исключение нулевого указателя, потому что onServiceConnected()
никогда не вызывается, а метод onBind()
службы. Во всяком случае bindService()
возвращает true.
Очевидно, что услуга активна, потому что она начинает свою деятельность.
Я знаю, что вызов активности из службы может звучать странно, но, к сожалению, это единственный способ распознавания речи в сервисе.
Заранее спасибо
Ответы
Ответ 1
Я не могу составить точную проблему из вашего описания, поэтому я собираюсь угадать здесь!
Как bindService()
вывести NullPointerException
? Единственный способ, которым это могло (/должен) произойти, это когда вы не поставляете прослушиватель Service
или ServiceConnection
.
bindService()
не может выбрать NullPointerException
, потому что onServiceConnected()
не вызывается. Вызов onServiceConnected()
является произведением bindService()
.
Итак, я думаю, вы вызываете метод AIDL
, прежде чем Service
действительно связан?
Ответ 2
Я только что испытал другую версию этой проблемы, с тем же симптомом onServiceConnected(...)
, который не был вызван. В моем случае причина была другой.
Вы должны обязательно иметь объявление службы в вашем AndroidManifest.xml в теге приложения - это был корень проблемы для меня.
<application android:name=".YourAppTitle" android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Main" android:label="@string/app_name">
</activity>
<service android:name="YourService" />
</application>
Там есть дополнительное усложнение, если вы используете отдельную библиотеку Android в Eclipse - добавление этого тега службы только, кажется, устраняет проблему, если ссылочная служба находится в том же пакете, что и манифест; то есть, если ваше приложение находится в пакете a.b.c, и здесь находится AndroidManifest.xml, тогда "YourService" также должен быть в пакете a.b.c. (при необходимости вручную копируется из другой библиотеки), иначе тег <service..>
может/быть проигнорирован и onServiceConnected(...)
по-прежнему не будет вызываться.
Это было для моего проекта, хотя я использовал подходящий оператор импорта для Сервиса в своем коде. Eclipse не обнаружил ошибки, поэтому импорт правильно идентифицировал класс из другой библиотеки в рабочей области Eclipse.
НТН
Ответ 3
По прошествии нескольких часов и часов, чтобы понять это, проблема заключается в том, что примеры, показывающие создание службы, не включают метод onBind или они имеют следующий примерный код, или он генерирует это для вас:
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
Это приводит к тому, что метод onServiceConnected завершается с ошибкой или никогда не выполняется. Исправление очень простое:
public IBinder onBind(Intent intent) {
return mBinder;
}
Если вы можете создать простое связующее, например следующее:
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public ConferenceService getService() {
return ConferenceService.this;
}
}
Ответ 4
Событие onServiceConnected никогда не вызывалось в моем приложении.
Проблема заключалась в том, что у меня было имя службы, указанное в моем манифесте приложения, как:
<service android:name="MyService" android:enabled="true"></service>
Как только я сменил его на полное имя класса, он работал:
<service android:name="com.example.MyService" android:enabled="true"></service>
Обновление:. Вы также можете использовать относительное имя класса:
<service android:name=".MyService" android:enabled="true"></service>
Укажите имя класса, используя полный com.example.MyServiceClass, а не только MyServiceClass.
Ответ 5
Еще одна вещь: если вы вызываете метод bindservice
внутри метода oncreate
, тогда onserviceconnected
вызывается после завершения метода oncreate
.
Таким образом, любые ссылки на интерфейсные функции перед концом oncreate
(или перед тем, как onserviceconnected
вызывается) показывают исключение нулевого указателя.
Ответ 6
Еще одна причина для исходного вопроса может заключаться в том, что служба еще не запущена, и вы передаете 0 как флаг в bindService. Например:
bindService(intent, serviceConnection, 0);
Когда вы ищете, что:
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
Ответ 7
Может быть другое объяснение, а не очень частая ситуация, но мне удалось войти в него и потерять 2 часа, чтобы решить эту проблему.
Итак, я сделал то, что я хотел повторно использовать пакет из намерения, полученного методом onBind. Но я пошел на ленивую версию и изменил класс намерений. По-видимому, это приводит к тому, что onServiceConnected не будет вызван. Вероятно, потому что система сохраняет ссылку на намерение и использует ее при вызове onServiceConnected.
В заключение не изменяйте намерения, которые вы получаете в onBind.
Ответ 8
Я вызывал bind с пустым Intent - getContext().bindService(new Intent(), mConnection, Context.BIND_AUTO_CREATE)
. Я должен сделать намерение более конкретным, чтобы указать, к какой услуге я хочу привязать. Это, очевидно, ошибка кода, но выход Logcat, к сожалению, недостаточно ясен.
Ответ 9
Вы должны дождаться завершения метода onCreate(). Пример: установите сервис покупки в кнопке:
Button button_useservice=findViewById(R.id.button_useservice);
button_useservice.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UsinService();
}
});
Ответ 10
Если кто-то все еще ищет ответ после попытки всех остальных, это может помочь.. onServiceConnected()
не вызывается сразу после bindService(...)
. это займет несколько секунд. Поэтому, если вы получаете какое-либо значение из onServiceConnected()
и вам нужно использовать его где-то еще в onCreate
или onStart
оно выдаст onStart
NullPointerException из-за задержки. Поэтому, если вы можете сместить строку кода, для которой необходимо значение из onCreate
или onStart
, внутри onServiceConnected(){......}
, ниже строки объявления onServiceConnected(){......}
значения, это может сработать.