Workmanager launching each time at launch without doing anything - java

First time using Stackoverflow !
I have an issue with my Workmanager and I'm asking for help:
When I run my app, its executing without switching my switch to ON. It's happening every time when I install (run) my app, my notification appears without doing anything. (it still works when I'm using my switch after launching )
MyWorker.java
public class MyWorker extends Worker {
private Workmate workmate;
private String messageBody;
public MyWorker(#NonNull Context context, #NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
#NonNull
#Override
public Result doWork() {
retrievesWorkmateData();
return Result.success();
}
SettingsActivity.java
#Override
public int getLayout() {
return R.layout.activity_settings;
}
#Override
protected void onConfigureDesign() {
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
configureToolbar();
spinnerLanguage();
final SharedPreferences.Editor editor = mSharedPreferences.edit();
boolean notificationBoolean = mSharedPreferences.getBoolean(BOOLEAN, false);
final OneTimeWorkRequest simpleRequest = new OneTimeWorkRequest.Builder(MyWorker.class)
.build();
UUID workId = simpleRequest.getId();
if (notificationBoolean) {
mSwitch.setChecked(true);
}
mSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (mSwitch.isChecked()) {
editor.putBoolean(BOOLEAN, true);
WorkManager.getInstance().enqueue(simpleRequest);
Toast.makeText(this, getResources().getString(R.string.Alarm_manager_start), Toast.LENGTH_SHORT).show();
} else {
editor.putBoolean(BOOLEAN, false);
WorkManager.getInstance().cancelWorkById(workId);
Toast.makeText(this, getResources().getString(R.string.Alarm_manager_cancel), Toast.LENGTH_SHORT).show();
}
editor.apply();
});
}
Have a nice day.

inside onConfigureDesign you are creating OneTimeWorkRequest an obtain its UUID workId = simpleRequest.getId(). this id is used inside OnCheckedChangeListener for starting or canceling work for WorkManager. consider this scenario: app doesn't have any pending work to do and user navigates to this switch and schedule work with given UUID. then user quits app, even kill it, and then got back to app and navigates again to this switch. onConfigureDesign is called again, new OneTimeWorkRequest is created and it have new UUID. this id won't cancel your previously set request, because it had/have another id... still switch is checked, as its checked/unchecked state is basing just on some boolean in SharedPreferences
solution would be to store in SharedPreferences this UUID (String in fact, use toString() and fromString(str)) when work is scheduled and remove it from there when canceling or doWork() gets called. initial state of switch should be also set basing on presence of this (any) id in shared prefs
welcome on SO :)

Related

How to make activity to show data got from the service?

I need write a service which will update the list in MainActivity every 30sec. I use MVVM with ViewModel and LiveData and so my Service class looks like this:
public class ArticleJobService extends JobService {
public static String TAG = "ArticleJobService";
private Context context = this;
#Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d(TAG, "onStartJob");
MainActivity.PAGE_NUMBER++;
LiveData<List<Article>> liveArticles = ArticleRepository.getInstance(getApplication()).getArticles(MainActivity.PAGE_NUMBER);
liveArticles.observeForever(new Observer<List<Article>>() {
#Override
public void onChanged(#Nullable List<Article> articles) {
Log.d(TAG, "onStartJob - onChanged!!!!!!");
liveArticles.removeObserver(this);
NotificationUtils.showNotification(context, articles.get(0).getSectionName(), articles.get(0).getWebTitle());
jobFinished(jobParameters, true);
}
});
return true;
}
}
Class for my notification:
public static void showNotification(Context context, String section, String title) {
PendingIntent contentPendingIntent = PendingIntent.getActivity
(context, REQUEST_CODE, new Intent(context, MainActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager manager =
(NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
manager.createNotificationChannel(createNotificationChannel(context));
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle(section)
.setContentText(title)
.setContentIntent(contentPendingIntent)
.setSmallIcon(R.drawable.app_icon)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setAutoCancel(true);
manager.notify(0, builder.build());
}
When Onchanged in JobService works I get the list and show a notification. Notification opens MainActivity which makes new call to api as it always did. What changes do I have to make in order the MainActivity to show the list that I got from the service??? I really can't tie this up together.
I heard of IPC but wouldn't do that, I want some simpler practice which I sure exists which I just don't know about.
Also, there are two cases: Notification came and MainActivity is open, app is open but MainActivity is not in the foreground and app is on the background or closed. How should I handle each of these cases?
See also piece of code from MainActivity onCreate:
mArticleViewModel = ViewModelProviders.of(this).get(ArticleViewModel.class);
mArticleViewModel.getArticleList(PAGE_NUMBER).observe(this, articles -> {
Log.d(TAG, "List<Result> onChanged!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
mProgressBar.setVisibility(View.GONE);
mProgressBarMain.setVisibility(View.GONE);
mIsLoading = false;
mArticles = articles;
Please provide the best practices for this task, I know it's very common I just do it first time and using LiveData makes it way more complicated.
Here is Also Repository code:
public static ArticleRepository getInstance(Application application){
if(INSTANCE == null){
return new ArticleRepository(application);
}
return INSTANCE;
}
private ArticleRepository(Application application) {
Log.d(TAG, "ArticleRepository constructor");
mContext = application;
mArticles = new MutableLiveData<>();
ArticleRoomDatabase db = ArticleRoomDatabase.getInstance(application);
mArticleDao = db.articleDao();
}
public LiveData<List<Article>> getArticles(int page) {
Log.d(TAG, "getArticles");
if (NetworkUtils.isOnline(mContext)) {
Log.d(TAG, "isOnline");
mArticles = loadFromNetwork(page);
} else {
Log.d(TAG, "is NOT Online");
mArticles = loadFromDB(page);
}
}
You have this problem specifically because your Repository implementation is incorrect.
public LiveData<List<Article>> getArticles(int page) {
Log.d(TAG, "getArticles");
if (NetworkUtils.isOnline(mContext)) {
Log.d(TAG, "isOnline");
mArticles = loadFromNetwork(page);
} else {
Log.d(TAG, "is NOT Online");
mArticles = loadFromDB(page);
}
}
If you check the code for NetworkBoundResource, the trick is that you have a single LiveData that binds together the ability to both load from network, and to load from database.
In your case, you are replacing the database's auto-updating query results whenever you have network access - which is why you can't update the MainActivity.
The easiest way (without using a MediatorLiveData) is to have two separate functions on Repository: one for fetchFromNetwork, and one for fetchFromDatabase. The MainActivity should always fetch from database, while the Service always triggers load from network (and inserts it directly into database via a Dao).
This way, the observe function in MainActivity will receive the latest data when Service inserts the data into DB on background thread.

Strange LiveData behaviour?

Im trying to implement MVVM architecture using ViewModel and LiveData. These two methods are inside a Activity:
private void handleResult(BoardViewModel vm) {
vm.getLiveDataSingleObj("Result").observe(this, new Observer<Object>() {
#Override
public void onChanged(#Nullable Object resultObj) {
Result result = (Result) resultObj;
if (!result.isCompleted()) return;
gotoResult();
}
});
}
And
private void gotoResult() {
Log.w(LOG_TAG, "Result: Moving to next activity");
Intent intent = new Intent(boardActivity, ResultActivity.class);
intent.putExtra("LEVEL", levelIndex);
intent.putExtra("MAP", mapIndex);
startActivity(intent);
}
The handleResult method is setup to listen for result objects that indicate that the game has ended and it is time to move on to the next activity ("gotoResult"). However, this completely breaks the navigation of the app, when i go back and then say attempt to start a new game session i instead instantly go to the next activity telling me I've already won.
Any ideas as to why it fires multiple times and eventually stops, letting me start a new session. To clarify, if I remove the gotoResult the logic works every single time no errors with indexes out of bounds or what have you, it's only when I add the goto that everything breaks.
ViewModel:
private void setupHashTypes() {
hashLiveData.put(KEY_BOARD, liveDataBoardQuery);
hashLiveData.put(KEY_STEPS_COUNTER, game.getStepsTakenLiveData());
hashLiveData.put(KEY_PATH_CHANGE, game.getPathChangedLiveData());
hashLiveData.put(KEY_VALUE_CHANGE, game.getValueChangeLiveData());
hashLiveData.put(KEY_TIMER, game.getTimerLiveData());
hashLiveData.put(KEY_SELECTED, game.getSelectedLiveData());
hashLiveData.put(KEY_DESELECTED, game.getDeselectedLiveData());
hashLiveData.put(KEY_HOLD, game.getHoldLiveData());
hashLiveData.put(KEY_UNHOLD, game.getUnholdLiveData());
hashLiveData.put(KEY_RESULT, game.getResultLiveData());
}
public LiveData<Object> getLiveDataSingleObj(String type) {
if (hashLiveData.containsKey(type)) {
return (LiveData<Object>) hashLiveData.get(type);
}
throw new IllegalArgumentException("Invalid: key was not found: " + type);
}
And the Model has getters, example:
private final SingleLiveEvent<Result> resultLiveData = new SingleLiveEvent<>();
public LiveData<Result> getResultLiveData() {
return resultLiveData;
}
you should remove the observer in onDestroy() method
Changing from MutableLiveData which always resends the previous set values to new subscribers, to SingleLiveEvent which doesn't have this behaviour, solved the problem.
The class can be found here: https://github.com/googlesamples/android-architecture/tree/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp

Android Beacon Library, Null Object Reference when calling startRangingBeaconsInRegion

I'm developing an android app using beacon library, part of this app is about to search for a specific beacon via its minor ID (which is inserted by user via dialog).
if I write everything in the same activity things works fine but I'd like to keep dialogs separate in an external pure java class, so in the activity implementing BeaconConsumer I added a "method" creating and binding the beacon manager.
public class Activity03 extends AppCompatActivity
implements BeaconConsumer, RangeNotifier {
...
public void scanForBeacon(Context context, String selectedMinorId){
beaconManager = BeaconManager.getInstanceForApplication(context);
beaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
Identifier minorIdFilter = Identifier.parse(selectedMinorId);
myRegion = new Region(
"my_region",
null,
null,
minorIdFilter);
beaconManager.bind((BeaconConsumer) context);
}
...
}
The point is that when calling startRangingBeaconsInRegion, i got:
Attempt to invoke virtual method 'void org.altbeacon.beacon.BeaconManager.startRangingBeaconsInRegion(org.altbeacon.beacon.Region)' on a null object reference
The sequence is:
1. the user is asked (via GoogleApiClient) to switch on BLE and localization
2. inside onActivityResult the dialog for inserting minor ID is picked from the java class DialogUtilities
DialogUtilities.showSelectionDialog(Activity03.this);
3. pressing the button dialog is dismissed, an instance of the BeaconConsumer activity is created and the method called:
Activity03 a03 = new Activity03();
a03.scanForBeacon(context, minorId);
4. when the onBeaconServiceConnect() is called I got null object reference on the line of startRangingBeaconsInRegion
#Override
public void onBeaconServiceConnect() {
try {
beaconManager.startRangingBeaconsInRegion(myRegion);
} catch (RemoteException e) {
e.printStackTrace();
}
}
I'm new of java and android but it doesn't seems to me that problem is about the Region because I've the same response even if I set to null all the Identifiers so I cannot understand why null reference.
Is it possible that I create two different BeaconMangers because of the activity's istance I return by Dialog ? If so how I can solve it?
If not, how to avoid this null object reference?
Thanks in advance
EDIT
BeaconManager declaration
public class Activity03 extends AppCompatActivity implements BeaconConsumer, RangeNotifier {
static final int REQUEST_CHECK_SETTINGS = 1000;
private BeaconManager beaconManager;
private Region myRegion;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.AppTheme);
setContentView(R.layout.activity_03);
}
#Override
protected void onResume() {
#Override
super.onResume();
PermissionsUtilities.switchLocationAndBluetooth(Activity03.this);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode) {
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
DialogUtilities.showSensorSelectionDialog(Activity03.this);
break;
case Activity.RESULT_CANCELED:
...
break;
default:
break;
}
break;
}
}
You can try the code below to avoid null pointer exception:
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection beacons, Region region) {
if (beacons.size() > 0) {
Log.i(TAG, "The first beacon I see is about "+beacons.iterator().next().getDistance()+" meters away.");
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
} catch (RemoteException e) {
e.printStackTrace();
}
The question does not show the declaration of beaconManager and how it is scoped, so it is hard to say the exact cause.
Two tips:
The BeaconManager is a singleton, meaning there is one instance per Java process. So you can always get this instance from within an Activity like this: BeaconManager.getInstanceForApplication(this).startRangingBeaconsInRegion(myRegion);
Manually constructing a new Activity instance as shown below generally will not work in Android programming. You must create new Activity instance using an Intent. In your case I suspect you may not want to create a new Activity instance at all but to get a reference to the existing one. This may be unrelated to what you are asking, but it will certainly need to be changed: Activity03 a03 = new Activity03();
a03.scanForBeacon(context, minorId);

AsyncTask that checks current session based on time stored in shared preferences

I'm new to android, but in the interest of practicing and learning more I wanted to try to make a practice application that essentially allows the user to only be logged on within the minute that they first logged in. So in other words if you log in at 10:23, the user will be logged out as soon as the clock strikes 10:24. To do this, I log in via my LoginActivity I share the current minute in a SharedPreferences object. In the interest of making use of the onResume() method in my AppActivity, my application first opens the main activity,AppActivity, which then opens my LoginActivity in the onCreate() method of my AppActivity class. Hopefully without being too redundant in my explanation, the goal is to call sessionChecker_AsyncTask.execute() in the onResume() method of my AppActivity.
Here's my login button found in LoginActivity:
login_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int result = getTime();
SharedPreferences pref = getSharedPreferences(PREF, MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putInt(SESSION, result);
editor.commit();
finish();
}
});
with helper method getTime() seen here:
private int getTime() {
Calendar time = Calendar.getInstance();
return time.get(Calendar.MINUTE);
}
As you can see I'm simply storing the current minute in a SharedPreferences object via my login button. Now from here, I wanted to create an AsyncTask in my AppActivity class that checks every 500ms (.5 seconds) if my current minute in AppActivity matches the minute that was stored in my SharedPreferences object, if not I want to essentially log the user out and send them back to the LoginActivity.
My issue is, I'm a bit confused about the types that I should be implementing in my AsyncTask for my doInBackground() and onPostExecute() methods. Also do I need the onCancelled() method, and would implementing it perhaps be useful for configuration changes within AppActivity? As of now I'm thinking that I should set it up something like this:
private class SessionCheckerTask extends AsyncTask<Integer, Void, Boolean>
{
#Override
protected Boolean doInBackground(Integer... minute_in_SharedPreferences) {
//Create a thread that refreshes every 500ms that checks current time
return false; //if the current time doesn't match the time in shared preferences
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
/*
If false was returned create a toast that says "Activity session has expired"
then open the login activity again
*/
}
}
But then I'm also thinking that it shouldn't be necessary for doInBackground() to have a type at all. Instead onPostExecute() should only be called if the minute passed in doInBackground() doesn't match the current minute, but I'm not sure how to implement this in the typical AsyncTask format.
try this:
In your doInBackground:
do {
if (getTime >= pref.getInt (SESSION, result)) break;
try{
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (true);
In your onPostExecute:
Toast.makeText(context, "Activity session has expired", Toast.LENGTH_SHORT).show();
startActivity(new Intent(context, LoginActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
P.S.: I think it's wrong way to remember a minute and then compare current minute with your saved one. In case when it was, for example, 21:59 you save int "21", but in next second it will be "22". Try to do the same, but with seconds. Then in doInBackground make float a = pref.getInt (SESSION, result), in do..while cycle make a+=0.5

Maximum length of Intent putExtra method? (Force close)

I need some help with debugging my application. First of all: In emulator and on some other devices my app is running fine. On my device I got a force close (without a force close message).
The "crash" happens if the Activity of the app is changed.
Here is some code of the MainActivity class. It just reads html content from a web page over webview. And no, it is NOT possible to do this over HttpRequest because I was not able to simulate the post request.
public class MainActivity extends Activity {
public final static String EXTRA_HTML = "com.example.com.test.HTML";
private WebView mWebView;
private ProgressDialog mDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webView1);
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
mWebView.setBackgroundColor(0);
mWebView.setWebChromeClient(new WebChromeClient() {
public boolean onConsoleMessage(ConsoleMessage cmsg) {
if (cmsg.message().startsWith("MAGIC")) {
mDialog.cancel();
/*HashMap<String, String> message = new HashMap<String, String>();*/
String msg = cmsg.message().substring(5);
Intent intent = new Intent(MainActivity.this,
ReadDataActivity.class);
/*message.put("message", msg);*/
/*intent.putExtra(EXTRA_HTML, message);*/
intent.putExtra(EXTRA_HTML, msg);
startActivity(intent);
}
return false;
}
});
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginState(PluginState.OFF);
mWebView.getSettings().setLoadsImagesAutomatically(false);
mWebView.getSettings().setBlockNetworkImage(true);
mWebView.getSettings().setAppCacheEnabled(true);
mWebView.getSettings().setSavePassword(true);
mWebView.getSettings()
.setCacheMode(WebSettings.LOAD_NORMAL);
mWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String address) {
if (address.indexOf("mySession") != -1) {
view.loadUrl("javascript:console.log('MAGIC'+document.getElementsByTagName('html')[0].innerHTML);");
}
});
mWebView.loadUrl("http://www.myurl.de");
}
So, in the onConsoleMessage() method I just pass the html code to another Activity class which read, parse and display the content.
The problem is now that at this point when the ReadDataActivity class should be loaded the application just close and go back to the home screen without any message or user dialog.
Is it possible that the html code which is passed as a string to the ReadDataActivity is to big? I also try to add the html code as a string in a HashMap but the problem is the same.
Some ideas what I can do to debug the problem? Maybe I should try to create a Parcelable object?
In the emulator everything is working fine.
As per my experience (sometime ago), you are able to parcel up to 1MB of data in a Bundle for IPC. This limit can be reduced if a lot of transactions are happening at a given time. Further information here.
In order to overcome this issue, I would suggest you to save your content on a temp file and pass the path/URI of your temp file to your second activity. Then in your second activity, read the contents out from file, perform your desired operations and finally delete that file.
If you want, you may also incorporate Shared_Preferences for this task - if you think handling files is cumbersome.
I did some research on the maximum amount of data you can transfer using an Intent. And it seems that the limit is nowhere near 1MB or 90KB, it's more like 500KB (tested on API 10, 16, 19 and 23).
I wrote a blog post about this topic, you can find it here: http://web.archive.org/web/20200217153215/http://neotechsoftware.com/blog/android-intent-size-limit
The size limit of Intent is still pretty low in Jelly Bean, which is somewhat lower than 1MB (around 90K), so you should always be cautious about your data length, even if your application targets only latest Android versions.
I have seen that by writing and reading from a file consists of less performance .
Then I have seen this solution : . So I am using this solution :
public class ExtendedDataHolder {
private static ExtendedDataHolder ourInstance = new ExtendedDataHolder();
private final Map<String, Object> extras = new HashMap<>();
private ExtendedDataHolder() {
}
public static ExtendedDataHolder getInstance() {
return ourInstance;
}
public void putExtra(String name, Object object) {
extras.put(name, object);
}
public Object getExtra(String name) {
return extras.get(name);
}
public boolean hasExtra(String name) {
return extras.containsKey(name);
}
public void clear() {
extras.clear();
}
}
Then in MainActivity I have called it like the following :
ExtendedDataHolder extras = ExtendedDataHolder.getInstance();
extras.putExtra("extra", new byte[1024 * 1024]);
extras.putExtra("other", "hello world");
startActivity(new Intent(MainActivity.this, DetailActivity.class));
and in DetailActivity
ExtendedDataHolder extras = ExtendedDataHolder.getInstance();
if (extras.hasExtra("other")) {
String other = (String) extras.getExtra("other");
}
The fixed size of 1MB is not only limited to intents. As Intents, Content Providers, Messenger, all system services like Telephone, Vibrator etc. utilize IPC infrastructure provider by Binder. Moreover the activity lifecycle callbacks also use this infrastructure.
1MB is the overall limit on all the binder transactions executed in the system at a particular moment.
In case there are lot of transactions happening when the intent is sent,it may fail even though extra data is not large.
http://codetheory.in/an-overview-of-android-binder-framework/
A little late to the game, but I just ran up against the same issue. Writing the data to file didn't really make sense performance-wise in my case, but I came across this in my search for answers:
http://developer.android.com/guide/faq/framework.html#3
Using a singleton is better for me as there's no need for disk IO. Better performance if the data doesn't need to be persisted.
Here's an example implementation:
public class DataResult {
private static DataResult instance;
private List<SomeObject> data = null;
protected DataResult() {
}
public static DataResult getInstance() {
if (instance == null) {
instance = new DataResult();
}
return instance;
}
public List<SomeObject> getData() { return data; }
public void setData(List<SomeObject> data) { this.data = data; }
}
Then you can set using this in one activity:
DataResult.getInstance().setData(data);
And get it in the other activity like this:
List<SomeObject> data = DataResult.getInstance().getData();
The Binder transaction buffer has a limited fixed size - 1Mb.
But the problem is that buffer shared by all transactions in progress for the process.
So try to keep your intent's data as small as possible every time.
The use of static String variable is good. If there is a need for the user to go back & forth between different pieces of HTML, you can also use LruCache like this:
static LruCache<String, String> mMemoryCache;
final int kiloByte = 1024;
.
.
final int maxMemoryKB = (int) (Runtime.getRuntime().maxMemory() / kiloByte);
// then choose how much you want to allocate for cache
final int cacheSizeKB = maxMemoryKB / 8;
.
.
mMemoryCache = new LruCache<String, String>(cacheSizeKB) {
//#Override
protected int sizeOf(String key, String value) {
try {
byte[] bytesUtf8 = value.getBytes("UTF-8");
return bytesUtf8.length / kiloByte;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return -1;
}
};
.
.
String cacheKey = generateUniqueString(key);
if (mMemoryCache.get(key) == null) {
mMemoryCache.put(cacheKey, yourContent);
}
Intent intent = new Intent(getApplicationContext(), ReadDataActivity.class);
intent.putExtra(EXTRA_HTML, cacheKey);
startActivity(intent);
Then on the ReadDataActivity side
Intent intent = getIntent();
String cacheKey = intent.getStringExtra(EXTRA_HTML);
String contentString = MainActivity.mMemoryCache.get(cacheKey);
doSomethingWith(contentString);
This idea came from here.
An alternative solution for passing large data between activities is to use a static field. In your case add this line to ReadDataActivity class
public static String msg;
Then you can use the static field msg within MainActivity class as follows
ReadDataActivity.msg = cmsg.message().substring(5);
And finally start your activity without extra put
Intent intent = new Intent(MainActivity.this, ReadDataActivity.class);
startActivity(intent);

Categories

Resources