ServiceConnection.onServiceConnected() nie aufgerufen, nachdem die Bindung an Dienst gestartet

In einem Spiel habe ich Folgendes Szenario:

  • Von der Haupt-Spiel Activity beginnt der player die mehrere Spiel-Aufgaben, die im hintergrund laufen mit unterschiedlicher Dauer.
  • Der Spieler sollte in der Lage sein, um den Fortschritt des Laufenden Spiel-Aufgaben in einer separaten View.

Dazu, ich habe zwei Activitys und eine Service wie folgt definiert:

  • Service ProgressService Griffen mehrere ProgressBars gleichzeitig laufen parallele threads.

  • Activity WorkScreen2 erstellt ein Spiel, Aufgabe, startet die Service mit startService() mit der Aufgabe, die übergebenen Parameter in ein Bundle.

  • Activity ProgressScreen bindet an die Service zum abrufen und anzeigen der ProgressBars der Laufenden Aufgaben.

  • Beide Aktivitäten laufen unter eigenen TabHosts von einem TabActivity.


Das problem das ich habe ist, dass die ServiceConnection.onServiceConnected() - Methode niemals aufgerufen wird. Ich bekomme eine Java.lang.NullPointerException weil ich versuche, eine Methode aufrufen die Service Objekt, das zugewiesen werden soll, die in dieser Methode. Siehe code unten.

Benutze ich getApplicationContext().bindService() zu binden Activity zu den Service weil TabSpec kann nicht binden an Services. Diese Methode gibt true. Deshalb, die Bindung erfolgreich ist.


Hier ist die Service:

public class ProgressService extends Service implements GameConstants {
    public static final String BROADCAST_PROGRESS = "com.mycompany.android.mygame.progressbroadcast";
    private static final long UPDATE_INTERVAL = 500;
    private IBinder mBinder;
    private List<ProgressBar> mProgressBarList;
    private List<String> mStaffNameList;

    private final class ServiceHandler extends Handler {

        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            ProgressBar progressBar = new ProgressBar(ProgressService.this);
            mProgressBarList.add(progressBar);

            Bundle bundle = msg.getData();
            String staffName = bundle.getString(WorkScreen2.STAFF_NAME);
            mStaffNameList.add(staffName);

            int taskDurationMillis = bundle.getInt(WorkScreen2.TASK_DURATION) * 1000;
            progressBar.setMax(taskDurationMillis / 1000);

            long startTimeMillis = SystemClock.uptimeMillis();
            long elapsedTimeMillis = SystemClock.uptimeMillis()
                    - startTimeMillis;

            Intent intent = new Intent();
            intent.setAction(BROADCAST_PROGRESS);

            while (elapsedTimeMillis < taskDurationMillis) {
                try {
                    Thread.sleep(UPDATE_INTERVAL);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                elapsedTimeMillis = SystemClock.uptimeMillis()
                        - startTimeMillis;
                int elapsedTimeSeconds = (int) elapsedTimeMillis / 1000;
                progressBar.setProgress(elapsedTimeSeconds);
                sendBroadcast(intent);
            }

            progressBar.setVisibility(View.GONE);
            mProgressBarList.remove(progressBar);
            mStaffNameList.remove(staffName);
            sendBroadcast(intent);

            if (mProgressBarList.isEmpty()) {
                stopSelf(msg.arg1);
            }
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mBinder = new ProgressServiceBinder();
        mProgressBarList = Collections
                .synchronizedList(new ArrayList<ProgressBar>());
        mStaffNameList = Collections.synchronizedList(new ArrayList<String>());
    }

    /*
     * Creates a thread for each game task with parameters passed in
     * <code>intent</code>
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "starting service", Toast.LENGTH_LONG).show();

        HandlerThread thread = new HandlerThread("ServiceStartArguments",
                Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        Handler serviceHandler = new ServiceHandler(thread.getLooper());

        Message msg = serviceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.setData(intent.getExtras());
        serviceHandler.sendMessage(msg);

        return START_STICKY;
    }

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

    public class ProgressServiceBinder extends Binder {
        ProgressService getService() {
            return ProgressService.this;
        }
    }

    public List<ProgressBar> getProgressBarList() {
        return mProgressBarList;
    }

    public List<String> getStaffNameList() {
        return mStaffNameList;
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service done", Toast.LENGTH_SHORT).show();
    }
}

- Und dies ist die Activity bindet:

public class ProgressScreen extends ListActivity {
    private final String TAG = "ProgressScreen";

    private ProgressScreenAdapter mAdapter;
    private ProgressService mProgressService;
    private List<ProgressBar> mProgressBarList;
    private List<String> mStaffNameList;

    @Override
    public void onCreate(Bundle bundle) {
        Log.i(TAG, "ProgressScreen oncreate");

        super.onCreate(bundle);
        setContentView(R.layout.progress_screen_layout);
        IntentFilter filter = new IntentFilter();
        filter.addAction(ProgressService.BROADCAST_PROGRESS);
        registerReceiver(receiver, filter);
        doBindService();

        mAdapter = new ProgressScreenAdapter(this, mStaffNameList, mProgressBarList);
        setListAdapter(mAdapter); //Returns true

        /*
         * This is where I get the NullPointerException
         * mProgressService is null here
         */
        mProgressBarList = mProgressService.getProgressBarList();
        mStaffNameList = mProgressService.getStaffNameList();
    }

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ProgressService.BROADCAST_PROGRESS);
        registerReceiver(receiver, filter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }

    boolean doBindService() {
        return getApplicationContext().bindService(new Intent(this, ProgressService.class), mConnection, Context.BIND_AUTO_CREATE);
    }

    void doUnbindService() {
        getApplicationContext().unbindService(mConnection);
    }

    ServiceConnection mConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className, IBinder binder) {
            mProgressService = ((ProgressService.ProgressServiceBinder) binder).getService();
            Toast.makeText(ProgressScreen.this, "Connected to ProgressService", Toast.LENGTH_SHORT).show();
        }

        public void onServiceDisconnected(ComponentName name) {
            mProgressService = null;
        }
    };

    private BroadcastReceiver receiver = new BroadcastReceiver () {
        @Override
        public void onReceive(Context context, Intent intent) {
            mAdapter.notifyDataSetChanged();
        }
    };
}

Und die Service gestartet wird von der Haupt - Activity wie folgt:

Intent intent = new Intent(WorkScreen2.this, ProgressService.class);
intent.putExtra(TASK_DURATION, task.getDuration());
intent.putExtra(STAFF_NAME, staff.getName());
startService(intent);

Den AndroidManifest.xml enthält

<service
    android:name=".ProgressService"
    android:label="@string/progress_service">
</service>

InformationsquelleAutor Wesam | 2012-02-12

Schreibe einen Kommentar