I'd like to implement an update checker in an application, and I obviously only need this to show up once when you start the application. If I do the call in the onCreate() or onStart() method, it'll be shown every time the activity is created and this is not a viable solution.
So my question is: Is there a way to do something, like check for updates, just once per application start / launch?
I'm sorry if it's a bit hard to understand, I'm having difficulties explaning myself on this one.
SharedPreferences seems like ugly solution to me. It's much more neat when you use application constructor for such purposes.
All you need is to use your own Application class, not default one.
public class MyApp extends Application {
public MyApp() {
// this method fires only once per application start.
// getApplicationContext returns null here
Log.i("main", "Constructor fired");
}
#Override
public void onCreate() {
super.onCreate();
// this method fires once as well as constructor
// but also application has context here
Log.i("main", "onCreate fired");
}
}
Then you should register this class as your application class inside AndroidManifest.xml
<application android:label="#string/app_name" android:name=".MyApp"> <------- here
<activity android:name="MyActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
You even can press Back button, so application go to background, and will not waste your processor resources, only memory resource, and then you can launch it again and constructor still not fire since application was not finished yet.
You can clear memory in Task Manager, so all applications will be closed and then relaunch your application to make sure that your initialization code fire again.
looks like you might have to do something like this
PackageInfo info = getPackageManager().getPackageInfo(PACKAGE_NAME, 0);
int currentVersion = info.versionCode;
this.versionName = info.versionName;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int lastVersion = prefs.getInt("version_code", 0);
if (currentVersion > lastVersion) {
prefs.edit().putInt("version_code", currentVersion).commit();
// do the activity that u would like to do once here.
}
You can do this every time, to check if the app has been upgraded, so it runs only once for app upgrade
The shared preferences approach is messy, and the application class has no access to an activity.
Another alternative I've used is to have a retained fragment instance, and within that instance, a lot more stuff can be done especially if you need access to the main activity UI.
For this example, I've used asynctask within the retained fragment. My AsyncTask has callbacks to the parent activity. It is guaranteed to run only once per application because the fragment is never destroyed-recreated when the same activity is destroyed-recreated. It is a retained fragment.
public class StartupTaskFragment extends Fragment {
public interface Callbacks {
void onPreExecute();
void onProgressUpdate(int percent);
void onCancelled();
void onPostExecute();
}
public static final String TAG = "startup_task_fragment";
private Callbacks mCallbacks;
private StartupTask mTask;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallbacks = (Callbacks) activity;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true); // this keeps fragment in memory even if parent activity is destroyed
mTask = new StartupTask();
mTask.execute();
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
private class StartupTask extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
if (mCallbacks != null) {
mCallbacks.onPreExecute();
}
}
#Override
protected Void doInBackground(Void... ignore) {
// do stuff here
return null;
}
#Override
protected void onProgressUpdate(Integer... percent) {
if (mCallbacks != null) {
mCallbacks.onProgressUpdate(percent[0]);
}
}
#Override
protected void onCancelled() {
if (mCallbacks != null) {
mCallbacks.onCancelled();
}
}
#Override
protected void onPostExecute(Void ignore) {
if (mCallbacks != null) {
mCallbacks.onPostExecute();
}
}
}
}
Then, in main (or parent) activity where you want this startup task fragment to run once.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fm = getFragmentManager();
StartupTaskFragment st = (StartupTaskFragment) fm.findFragmentByTag(StartupTaskFragment.TAG);
if(st == null) {
fm.beginTransaction().add(mStartupTaskFragment = new StartupTaskFragment(), StartupTaskFragment.TAG).commit();
}
...
}
Ideas for retained fragment came from here: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html. I just figured out its other uses aside from config changes.
Yes you can do it Using SharedPrefernce concept of android. Just create a boolean flag and save it in SharedPrefernce and check its value in your onCreate() method .
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (!prefs.getBoolean("onlyonce", false)) {
// <---- run your one time code here
// mark once runned.
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("onlyonce", true);
editor.commit();
}
}
This continues on #Vitalii's answer.
After having setup the Application class, if access to the Activity is required, we can use the aptly named android library "Once" https://github.com/jonfinerty/Once.
In the Application class's onCreate method
Once.initialise(this)
In the Activity / Fragment class's onCreate / onViewCreated method.
val helloTag = "hello"
if (!Once.beenDone(Once.THIS_APP_SESSION, helloTag)) {
//Do something that needs to be done only once
Once.markDone(helloTag) //Mark it done
}
I do this the same way as described in the other answer. I just have a global variable in the first activity which matches the release number from the manifest. I increment it for every upgrade and when the check sees a higher number, it executes the one-time code.
If successful, it writes the new number to shared preferences so it wont do it again until the next upgrade.
Make sure you assign the default to -1 when you retrieve the version from shared preferences so that you error on the side of running the code again as opposed to not running it and not having your app update correctly.
Use SharedPreference for this-
If you are not restarting your launcher activity again once your app is active then in that case you case use it.
Use this in a Splash screen if you are implementing it in the app.
If you are not using any splash screen then you need to create a activity with no view set and on it's oncreate call you can do start updation and start your main activity.
you can use counter value or boolean for this.
Here is SharedPreference doc:
http://developer.android.com/reference/android/content/SharedPreferences.html
try {
boolean firstboot = getSharedPreferences("BOOT_PREF",MODE_PRIVATE)
.getBoolean("firstboot", true);
if(firstboot){
//place your code that will run single time
getSharedPreferences("BOOT_PREF",MODE_PRIVATE).edit().
putBoolean("firstboot", false)
.commit();
}
I just solved doing this myself, I reopen my main activity multiple times throughout the application's execution. While the constructor is a valid approach for some things it doesn't let you access the current Application context to write toasts among other things.
My solution was to create a simple 'firstRun' boolean set to true in the class of my MainActivity, from there I run the contents of the if statement then set it to true. Example:
public class MainActivity extends AppCompatActivity
{
private static boolean firstRun = true;
#Override
protected void onCreate(Bundle savedInstanceState)
{
if(firstRun)
{
Toast.makeText(getApplicationContext(), "FIRST RUN", Toast.LENGTH_SHORT).show();
//YOUR FIRST RUN CODE HERE
}
firstRun = false;
super.onCreate(savedInstanceState);
//THE REST OF YOUR CODE
}
public class troopcard extends Activity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.troopcard);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.pekkacard:
setContentView(R.layout.pekkacard);
break;
case R.id.dragcard:
setContentView(R.layout.dragcard);
}
}
}
The question here is why isnt the set content view working?as in the xml isnt opening of which i want. as making a intent then directing to a class then setting content view will take a hell load of time. I thought by directly setting the content view it might work. it isnt. What could be the solution. i really dont want to make a separate class for this as i have 40 + xmls. so is there a way to directly set content view without having to make a class?
This is not a true programming architecture. If you have more than one layout you should use more than one activity or fragment.
Switching on R.id won't work. You are never actually calling
setContentView(R.layout.pekkacard);
or
setContentView(R.layout.dragcard);
Try:
Override
public void onClick(View v) {
setContentView(R.layout.pekkacard);
}
to see if it displays the other layout.
I'm a Android-Beginner and want to make a if-question in my settings/preferences-Activity.
Here is my Preferences.java:
package net.dominik.genpush;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class Preferences extends PreferenceActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
}
...and my Prefs.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="pushCheckBox"
android:title="#string/pushnachr_headline"
android:summary="#string/pushnachr_explain"
android:defaultValue="true">
</CheckBoxPreference>
</PreferenceScreen>
Now I wanted to make something like
public void onCheckboxPush(View b)
{
if (pushCheckBox.isChecked())
{
//CODE
}
else...
but don't know how I can start the methode when the checkbox changes.
In a other way I could use
android:onClick="MethodeNameHere" in my activity.xml-File. This don't work in my PreferenceActivity class so no message.
Is there a (easy) way to do something like the "onClick" in a similar manner?
You can set listener for checkbox.
CheckBoxPreference checkBox = (CheckBoxPreference) findPreference("pushCheckBox");
checkBox.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
//your code here
return true;
}
});
According to documentation return true will update the state of the Preference with the new value.
And simply check inside of listener if checkBox is checked.
If you are simply trying to make one attribute depend on another, you can use the android:dependency attribute. Will that do what you want? E.g.,
<CheckBoxPreference
android:key="pushCheckBox"
android:title="#string/pushnachr_headline"
android:summary="#string/pushnachr_explain"
android:defaultValue="true">
<!-- This setting will be disabled if pref_one is not checked -->
<CheckBoxPreference
android:defaultValue="false"
android:key="preference_two"
android:dependency="pushCheckBox"
android:title="Pref Two" />
But, if you really just want to get the click event to do something else, put something like this in the onResume method.
Preference pushCheckBox = findPreference("pushCheckBox");
pushCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
// do something here
return false;
}
});
Ok so every post i find i cannot get this to work, i am trying to inside my list preference
Settingsbasic.xml
<ListPreference
android:title="themes"
android:summary="Select the option of the list"
android:key="listPref"
android:entries="#array/Themes"
android:entryValues="#array/list"
android:defaultValue="default" />
Now about as you can see above this is my listpreference inside my settingsbasic.xml file. Now what i need to know how to do is i have 2 java files, my main activity. and my preferences java file. I need to know how i can when the user clicks one of the the entries it does something, likes opens something or changes the ui, just something i think i can take it from there. I just need to know how and where the code would go. inside the main acitivty or preference activity.
here is my preference java file
public class Prefs extends PreferenceActivity {
ListPreference listPref;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settingsbasic);
}
protected void onResume() {
super.onResume();
// Registers a callback to be invoked whenever a user changes a preference.
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
protected void onPause() {
super.onPause();
// Unregisters the listener set in onResume().
// It's best practice to unregister listeners when your app isn't using them to cut down on
// unnecessary system overhead. You do this in onPause().
getPreferenceScreen()
.getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// Sets refreshDisplay to true so that when the user returns to the main
// activity, the display refreshes to reflect the new settings.
WebViewClientDemoActivity.????? = true;
}
}
Any example code would help, or adding on to my code above. I just need someone whom can shed some light on this code. i've tried so many different things and none of it works.
Ok so using the method of the sample app that was recommended below here is some more code i have .
Main Activity
public class WebViewClientDemoActivity extends Activity {
public static String sPref = null;
public void onStart() {
super.onStart();
// Gets the user's network preference settings
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// Retrieves a string value for the preferences. The second parameter
// is the default value to use if a preference value is not found.
sPref = sharedPrefs.getString("listPref", "Default");
}
This is the way I used PreferenceActivity:
public class EditPrefs extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.screen_prefs);
}
}
Then in /res/xml folder I have the XML file:
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:key="txtColor"
android:title="textView Color"
android:summary="select color for textViews"
android:entries="#array/txtColor"
android:entryValues="#array/txtColorValues" />
</PreferenceScreen>
And in /res/values I have this XML file includes items and their values:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="txtColor">
<item>blue</item>
<item>brown</item>
<item>gray</item>
<item>violet</item>
</string-array>
<string-array name="txtColorValues">
<item>#ff000099</item>
<item>#5F1E02</item>
<item>#333333</item>
<item>#421C52</item>
</string-array>
</resources>
Then I easily call this class from another android class for instance when user clicks on a menu item:
startActivity(new Intent(this, EditPrefs.class));
You can call the preferences in onCreate and onResume like:
#Override
protected void onResume() {
super.onResume();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String txtColor = prefs.getString("txtColor", DEFAULT COLOR); // for instanse : #ff000099
textView.setBackgroundColor(Color.parseColor(txtColor));
}
I have resolved my question by this.
Prefs
public static String theme = "Theme1";
#Override
public void onBackPressed() {
ListPreference listPreference = (ListPreference) findPreference("listPref");
String currValue = listPreference.getValue();
theme = currValue;
super.onBackPressed();
}
Main Activity
if (Prefs.theme.equals("Theme1"))
setContentView(R.layout.main);
else
setContentView(R.layout.main2);
Preference XML
<ListPreference
android:title="themes"
android:summary="Select the option of the list"
android:key="listPref"
android:entries="#array/listReturnValue"
android:entryValues="#array/listDisplayWord" />
Right now when I push a specific button it starts an intent to open a web page into a webView, but instead it opens a Browser Application, revealing the address bar which is not what I want.
After doing some research I found out I can use the shouldOverrideUrlLoading() method to stop this from happening and just open the page in a webView, but I don't know how to implement this method in my code, help would be greatly appreciated!
This is what I have in the class where I'm opening the web page:
public class Codes extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.codes);
View titleView = getWindow().findViewById(android.R.id.title);
if (titleView != null) {
ViewParent parent = titleView.getParent();
if (parent != null && (parent instanceof View)) {
View parentView = (View)parent;
parentView.setBackgroundColor(Color.rgb(228, 108, 10));
}
}
WebView codes = (WebView)findViewById(R.id.codesWebView);
codes.getSettings().setJavaScriptEnabled(true);
codes.loadUrl("http://dev10.affirmaconsulting.com:24009/keyentry");
shouldOverrideUrlLoading(codes, "http://dev10.affirmaconsulting.com:24009/keyentry");
}
}
I had this same problem, that pages were not loading in my webview but instead via the browser application. I resolved the issue by implementing a WebViewClient class and overriding the shouldOverrideUrlLoading method.
WebViewClient webClient = new WebViewClient()
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
return false;
}
};
webView.setWebViewClient(webClient);
The following link proved to be helpful:
http://www.firstdroid.com/2010/08/05/override-url-loading-in-webview-android-tutorial/
We do this exact task in one of our activities and haven't ran into this issue. Here is what ours looks like:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.document_viewer_activity);
WebView wv = (WebView) findViewById(R.id.documentViewerWebview);
wv.getSettings().setJavaScriptEnabled(true);
String url = getString(R.string.document_viewer_url) +
getIntent().getExtras().getString("media");
wv.loadUrl(url);
}
With the webview defined in the layout file looking like this:
<WebView
android:id="#+id/documentViewerWebview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
Hope this helps.