sendBroadcast (намерение) дает исключение нулевого указателя - PullRequest
0 голосов
/ 26 сентября 2011

Это мой второй пост сегодня, поскольку исправление 1-го поста привело к другой проблеме, с которой я действительно борюсь. Я хочу использовать широковещательные рассылки и намерен отправлять пакеты данных обратно из сервиса в пользовательский интерфейс. Мне удалось связать и запустить сервис успешно см. Мой другой пост, если вы хотите историю и код

Исключение с нулевым указателем возникает в sendBroadcast () внутри службы. Класс сервиса имеет свой конструктор, повторно называемый после , связывающего пользовательский интерфейс со службой. Это происходит из другого класса, поэтому контекст не может быть легко использован. Так что я думаю, что sendBroadcast не имеет куда идти :( Я подозреваю, что это моя проблема ... повторный вызов конструктора службы после первоначальной привязки. У меня onDestroy, onPause и onResume покрыты привязкой unbinding. Любые идеи или предложения были бы хорошими, или, может быть, я просто ошибаюсь, есть другой способ?

EDIT Предыдущая проблема с привязкой теперь решена, и из-за того, что я новичок в форумах, я немного задержался с принятием ответа ... извините.

Диаграмма классов выглядит следующим образом (это портированный код C #)

Activity doBind (on Curve.class) ---> Activity запускает рабочий класс (не рассматривается как служба) Comm.class с обработчиком для некоторых сообщений -> Comm запускает другой рабочий класс -> предыдущий рабочий наконец, класс вызывает новый класс Curve.

Это последний класс Curve.class, где sendBroadcastReceiver () затем генерирует нулевой указатель ref, потому что связыватель потерян. Я протестировал трансивер только с помощью простого таймера, вырезавшего рабочие классы между ними, и он отлично работает. Проблемы начинаются, когда класс Curve.class вызывается позже по иерархии и связыватель обнуляется или «теряется».

Я удалил все ссылки на связыватель из Curve, кроме onBind (). Это не может быть хорошей идеей. Снова приведенный ниже код работает, если используется с простым таймером, запускаемым непосредственно из пользовательского интерфейса (никаких других рабочих классов).

Еще немного кода здесь: Услуга

    public class Curve extends Service
{
    private NewCurvePointEventArgs newpoint = null;
    private static final String TAG = "Curve";

    Intent intent;
    int counter = 0;


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

    }

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        IBinder mBinder = new LocalBinder<Curve>(this);
        return mBinder;
    }
    @Override
    public void onStart(Intent intent, int startId) {

    }
    @Override
    public void onDestroy() {

    }
    public Curve(){

    }
    private void refreshintent(NewCurvePointEventArgs tmp)
    {
        ArrayList<String> thepoint = new ArrayList<String>();
        thepoint.add()//various things added here

         Bundle bundle = new Bundle();
            // add data to bundle
            bundle.putStringArrayList("New_Point", thepoint);

        intent = new Intent();
        intent.setAction(NEWCURVE_POINT);
        intent.putExtra("NEW_POINT", bundle

        sendBroadcast(intent);

    }

У активности теперь есть этот код. doBind () вызывается после onCreate действия.

        private BroadcastReceiver CurveReceiver  = new BroadcastReceiver(){

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Curve.NEWCURVE_POINT)) {
            displaynewpoint(intent); 

        }
    }
};
private ServiceConnection CurveServiceConncetion = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // TODO Auto-generated method stub

        CurveService = ((LocalBinder<Curve>) service).getService();

    }
    @Override
    public void onServiceDisconnected(ComponentName name) {

        // TODO Auto-generated method stub
        CurveService = null;
    }
};

@Override
public synchronized void onResume() {
    super.onResume();
    if(D) Log.e(TAG, "+ ON RESUME +");

}

@Override
public synchronized void onPause() {
    super.onPause();
    if(D) Log.e(TAG, "- ON PAUSE -");
}

@Override
public void onStop() {
    super.onStop();
    if(D) Log.e(TAG, "-- ON STOP --");
}

@Override
public void onDestroy() {
    super.onDestroy();

    if(D) Log.e(TAG, "--- ON DESTROY ---");

    unregisterReceiver(CurveReceiver);
    unbindService(CurveServiceConncetion); 
}
public  void doBind(){
    Boolean tmp;
    tmp = bindService(new Intent(this, Curve.class), CurveServiceConncetion, Context.BIND_AUTO_CREATE);//Context.BIND_AUTO_CREATE

    IntentFilter filter = new IntentFilter(Curve.NEWCURVE_POINT);  
    registerReceiver(CurveReceiver, filter);
}

Эта проблема для меня заключается в том, что у Curve.class снова вызывается конструктор после начальной doBind (). Конечно, должен быть способ обойти это, иначе я должен загрузить свои рабочие классы ближе по иерархии к пользовательскому интерфейсу с кодом из Curve.class ???

EDIT Кривая - это объект, который обрабатывает данные, константы и т. Д., Отправленные с внешнего компьютера, и содержит обработанные данные в массивах. LogCat, конечно, существовал, я просто не смотрел в нужном месте, это

ARN / System.err (10505): java.lang.NullPointerException WARN / System.err (10505): на android.content.ContextWrapper.sendBroadcast (ContextWrapper.java:271) WARN / System.err (10505): на pi.droid.Core.Curve.refreshintent (Curve.java:206) WARN / System.err (10505): в pi.droid.Core.Curve.AddPoint (Curve.java:400) WARN / System.err (10505): в pi.droid.Core.Comm.CommMeasure $ CommMeasurement.AddPoint (CommMeasure.java:363) WARN / System.err (10505): в pi.droid.Core.Comm.CommMeasure $ GenericCommMeasurement.TryProcessData (CommMeasure.java:168) WARN / System.err (10505): в pi.droid.Core.Comm.CommMeasure $ CommMeasurement.ProcessData (CommMeasure.java:302) WARN / System.err (10505): в pi.droid.Core.Comm.ClientConnection $ timer_tick.run (ClientConnection.java:164) WARN / System.err (10505): на java.util.Timer $ TimerImpl.run (Timer.java:289)

Вы также можете увидеть цепочку двух других рабочих классов, которые я использую. Конструктор Curve вызывается после привязки из CommMeasure. Так что это моя проблема. Нужно ли полностью менять настройку моей программы или есть другие способы обойти это?

Окончательное редактирование Этот код взят из c # и Curve использовал обработчики событий для передачи данных. Я избавился от всех них (слушатели Java) и использовал Android-обработчик и вещательный приемник.Было предложено, чтобы я обошел CurveService, но это будет проблематично, поскольку у Curve есть несколько конструкторов.Параметр no для службы 1, а затем 1, например,

    public Curve(Unit XUnit, Unit YUnit)
    {           this.Title = "Curve";
        this.finished = false;
        this.XUnit = XUnit;
        this.YUnit = YUnit;
        this.YDirection = CurveDirection.Unspecified;

    }

, поэтому создание такого экземпляра будет проблемой с CurveService, которая должна выглядеть следующим образом: public Curve () {} ??В любом случае большое спасибо за вашу помощь и советы.

Окончательное редактирование + 1 .. lol

Пользовательский интерфейс создает новый экземпляр ClientConnection, который, в свою очередь, создает новыйэкземпляр CommMeasure и, наконец, CommMeasure создает новый экземпляр Curve для доступа к Curve.addpoint.Я думаю, что этот поток и другие связанные 1 выходят за рамки простой проблемы Android и подчеркивает трудности переноса кода.Любой разработчик .Net, например, прочитав это, узнает некоторые особенности Android намного быстрее, чем я.Там также есть хороший рабочий код.Спасибо всем, кто особенно помог Джастину Брайтфеллеру

1 Ответ

0 голосов
/ 26 сентября 2011

Лучшее, что вы можете сделать, - это следовать примеру Android APIDemos.

Сервис, который вы хотите использовать так, как вы хотите: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html

Посмотрите на класс Binding внутри этого файла, чтобы увидеть класс, который выполняет связывание, как вы должны: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html

Наконец, если ваш конструктор вызывается дважды в вашем сервисе, вы не привязываетесь к своему сервису должным образом, или, возможно, вы отменяете привязку к нему и неожиданно привязываетесь к нему снова.

EDIT Из трассировки стека видно, что CommMeasure должна иметь ссылку на экземпляр Curve, который вы получаете в onServiceConnected.

РЕДАКТИРОВАТЬ 2 Если вы действительно хотите упростить свою жизнь, передайте getApplicationContext () своему классу CommMeasure и просто appContext.sendBroadcast () из этого класса, чтобы отправить свою точку зрения. Это не позволит вам ссылаться на службу в вашей долгосрочной задаче.

...