Using bundles inside the intent isn't about security, it's because the Android guys made it that way plain and simple. In my opinion using bundles and intents to pass larger objects is not a good idea. it gets too complicated to implement, makes you get the object down to the primitives (when using parcelable) and also makes a copy on the other side in memory (you take one object, set everything inside the intent and then re-create it on the other side making a new copy out of it) which for objects that have a bigger memory footprint isn't good.
I would suggest:
- either using a singleton store
- Using the application class (which also acts like a singleton)
I am often using a singleton which has a hashMap inside where an integer key is generated by me (from atomic Integer) and an object placed inside the map. You just send the ID inside the intent as an extra and retrieve it on the other side by getting the key from the intent and accessing your singleton to retrieve and remove the object (from that map) and use it in your new activity/service.
Here is a sample of something like this:
(Note: this is a part from my lib for rest requests (https://github.com/darko1002001/android-rest-client) in case you want to see more details on how everything is implemented). in your case you will need to strip some of the code and replace it with your own, but the general idea is the same.
/**
* @author Darko.Grozdanovski
*/
public class HttpRequestStore {
public static final String TAG = HttpRequestStore.class.getSimpleName();
public static final String KEY_ID = "id";
public static final String IS_SUCCESSFUL = "isSuccessful";
private static final HashMap<Integer, RequestWrapper> map = new HashMap<Integer, RequestWrapper>();
private final AtomicInteger counter = new AtomicInteger();
private static Class<?> executorServiceClass = HTTPRequestExecutorService.class;
private final Context context;
private static HttpRequestStore instance;
private HttpRequestStore(final Context context) {
this.context = context;
}
public static HttpRequestStore getInstance(final Context context) {
if (instance == null) {
instance = new HttpRequestStore(context.getApplicationContext());
}
return instance;
}
public static void init(final Class<?> executorServiceClass) {
HttpRequestStore.executorServiceClass = executorServiceClass;
}
public Integer addRequest(final RequestWrapper block) {
return addRequest(counter.incrementAndGet(), block);
}
public Integer addRequest(final Integer id, final RequestWrapper block) {
map.put(id, block);
return id;
}
public void removeBlock(final Integer id) {
map.remove(id);
}
public RequestWrapper getRequest(final Integer id) {
return map.remove(id);
}
public RequestWrapper getRequest(final Intent intent) {
final Bundle extras = intent.getExtras();
if (extras == null || extras.containsKey(KEY_ID) == false) {
throw new RuntimeException("Intent Must be Filled with ID of the block");
}
final int id = extras.getInt(KEY_ID);
return getRequest(id);
}
public Integer launchServiceIntent(final HttpRequest block) {
return launchServiceIntent(block, null);
}
public Integer launchServiceIntent(final HttpRequest block, RequestOptions options) {
if (executorServiceClass == null) {
throw new RuntimeException("Initialize the Executor service class in a class extending application");
}
if (isServiceAvailable() == false) {
throw new RuntimeException("Declare the " + executorServiceClass.getSimpleName() + " in your manifest");
}
final Intent service = new Intent(context, executorServiceClass);
final RequestWrapper wrapper = new RequestWrapper(block, options);
final Integer requestId = addRequest(wrapper);
service.putExtra(KEY_ID, requestId);
context.startService(service);
return requestId;
}
public boolean isServiceAvailable() {
final PackageManager packageManager = context.getPackageManager();
final Intent intent = new Intent(context, executorServiceClass);
final List<ResolveInfo> resolveInfo = packageManager.queryIntentServices(intent,
PackageManager.MATCH_DEFAULT_ONLY);
if (resolveInfo.size() > 0) {
return true;
}
return false;
}
}