1

I have an app with some activities. These activities need common resources (matrix arrayLists), so in order to avoid reload several times this resources (when change to another activity or on an orientation change), I've created a service.

Firstly I call it with startService(Intent) for let it be sticky. After that, I bind the service to the activity, bindService(sIntent, mConnection, BIND_AUTO_CREATE);

Finally, I have some code which try to get data from the service, but it generates a NullPointerException. I know that's because (as I see with logs) the service starts after the app has crashed, although I put startService and bindService before the accessing data code.

Anyone knows how can I ensure to get loaded data before trying to access it?

Thanks in advance.

user1205781
  • 40
  • 1
  • 9

3 Answers3

2

It might be easier for you to save your common resources in SharedPreference, The SharedPreference is accessible by all threads of your application, and is persistent between runs. This depending on what your resources are.

If you want your services to work for your method you could do this with a transparent Activity. AsyncTask might be an easier and simpler solution though.

Try to load your data with an AsyncTask, you can choose whatever you want what the Activity does while loading (Progress dialog? ) and make sure you continue your app using your data after when your AsyncTask calls the ready method ( onPostExecute() ). This means AsyncTask will replace your idea of a service as background thread, managing your resources. (loading, downloading, etc).

Also post your logs next time, they might help.

Community
  • 1
  • 1
Timmetje
  • 7,641
  • 18
  • 36
  • Thank your for your answer, but the objects that I want to share aren't primitive data, therefore I can't use shared preferences. – user1205781 Feb 20 '13 at 23:58
  • then either start up your service with transparent activity or use asynctask. I've provided a link, in the answer. Good luck! – Timmetje Feb 21 '13 at 09:16
  • I think I'm going to do a mixture between your answer and Raghav ones. So I'll try to launch an Async Task from Application class which will act also as a resources holder (I don't know if it is possible...). – user1205781 Feb 21 '13 at 18:53
  • Sounds good, if I were you, I would create a Class with public static variables to hold your resources. – Timmetje Feb 21 '13 at 19:06
  • @user1205781 So the answer wasn't good enough, if so mark it as answered ;) – Timmetje Feb 22 '13 at 09:18
1

Start your Service in the onCreate() of a class that extends Application. Or even better, do the work the Service is doing in your Application class, which is guaranteed to be created before any other part of your app. A Service may take a while to start up and you may encounter a race condition, but the class extending Application is always the first part of an app to be launched.

Raghav Sood
  • 81,899
  • 22
  • 187
  • 195
  • The point is that I need a service or something which hosts data and where I could get access. If I put what my service does on onCreate() of Application class, how can I refer from my activities to the loaded data? – user1205781 Feb 21 '13 at 00:13
1

I recently came across this problem and created a solution. Similar to the invisible activity, but the idea is to create a "loading" activity that does not need the service. Here is an example:

in AndriodManifest.xml:

...
<application
    ... >
    <activity 
        android:name="com.example.LoadingActivity"
        android:label="@string/app_name" >
        <!-- A do-nothing activity that is used as a placeholder while the service is started. -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name="com.example.MyActivity"
        android:label="@string/app_name" >
        <!-- The real activity, started by the loading activity. -->
    </activity>
    <service
        android:name="com.example.MyService" >
        <!-- The background service, started by the loading activity. -->
    </service>
</application>
...

com/example/LoadingActivity.java:

package com.example;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class LoadingActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_loading);

        super.startService(new Intent(this, MyService.class)); // listed first so it will start before the activity
        Intent intent = new Intent(this, MyActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // makes it so the 'loading' activity is not kept on the back-stack
        super.startActivity(intent);
    }
}

The MyActivity.java and MyService.java files are just standard. You also need an activity_loading.xml layout resource, probably just an ImageView.

coderforlife
  • 1,378
  • 18
  • 31