para - manual de programacion android pdf
¿Cómo puedo ejecutar algo solo una vez por cada inicio de la aplicación? (9)
Acabo de resolverlo, reabro mi actividad principal varias veces a lo largo de la ejecución de la aplicación. Si bien el constructor es un enfoque válido para algunas cosas, no le permite acceder al contexto actual de la aplicación para escribir tostadas, entre otras cosas .
Mi solución fue crear un booleano simple ''firstRun'' en true en la clase de mi MainActivity, a partir de ahí ejecuto el contenido de la instrucción if y luego lo configuro en verdadero. Ejemplo:
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
}
Me gustaría implementar un comprobador de actualizaciones en una aplicación, y obviamente solo necesito que aparezca una vez cuando inicie la aplicación. Si realizo la llamada en el onCreate()
o onStart()
, se mostrará cada vez que se cree la actividad y esta no es una solución viable.
Entonces mi pregunta es: ¿hay alguna manera de hacer algo, como verificar actualizaciones, una sola vez por cada inicio / inicio de la aplicación?
Lo siento si es un poco difícil de entender, tengo dificultades para explicarme en este caso.
El enfoque de preferencias compartidas es desordenado y la clase de aplicación no tiene acceso a una actividad.
Otra alternativa que he usado es tener una instancia de fragmentos retenidos, y dentro de esa instancia, se pueden hacer muchas más cosas, especialmente si necesita acceder a la IU de actividad principal.
Para este ejemplo, he usado asynctask dentro del fragmento retenido. My AsyncTask tiene devoluciones de llamada a la actividad principal. Se garantiza que se ejecute solo una vez por aplicación porque el fragmento nunca se destruye, se vuelve a crear cuando se destruye la misma actividad y se vuelve a crear. Es un fragmento retenido.
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();
}
}
}
}
Luego, en la actividad principal (o principal) donde desea que este fragmento de la tarea de inicio se ejecute una vez.
@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();
}
...
}
Las ideas para el fragmento retenido vinieron de aquí: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html . Acabo de descubrir sus otros usos aparte de los cambios de configuración.
Lo hago de la misma manera que se describe en la otra respuesta. Solo tengo una variable global en la primera actividad que coincide con el número de versión del manifiesto. Lo incremento para cada actualización y cuando el cheque ve un número más alto, ejecuta el código de una sola vez.
Si tiene éxito, escribe el nuevo número en las preferencias compartidas, por lo que no volverá a hacerlo hasta la próxima actualización.
Asegúrese de asignar el valor predeterminado a -1 cuando recupere la versión de las preferencias compartidas para que tenga el error de ejecutar el código nuevamente en lugar de no ejecutarlo y no tener la actualización de la aplicación correctamente.
Sí, puedes hacerlo usando el concepto SharedPrefernce de Android. Simplemente cree un indicador booleano y guárdelo en SharedPrefernce y verifique su valor en su método onCreate ().
SharedPreferences parece una fea solución para mí. Es mucho más claro cuando usas el constructor de aplicaciones para tales fines.
Todo lo que necesita es usar su propia clase de Aplicación, no una predeterminada.
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");
}
}
Luego debe registrar esta clase como su clase de aplicación dentro de 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>
Incluso puede presionar el botón Atrás, para que la aplicación vaya al fondo y no malgaste los recursos de su procesador, solo el recurso de memoria, y luego puede volver a ejecutarlo y el constructor aún no se activará ya que la aplicación aún no se completó.
Puede borrar la memoria en el Administrador de tareas, por lo que todas las aplicaciones se cerrarán y luego reiniciará su aplicación para asegurarse de que su código de inicialización vuelva a activarse.
Use SharedPreference para esto-
Si no está reiniciando su actividad de inicio una vez que su aplicación esté activa, en ese caso, en ese caso, la usará.
Úselo en una pantalla de bienvenida si lo está implementando en la aplicación.
Si no está utilizando ninguna pantalla de presentación, entonces necesita crear una actividad sin visualización de vistas y en su llamada en creación puede iniciar la actualización y comenzar su actividad principal.
puede usar el valor de contador o booleano para esto.
Aquí está el documento de SharedPreference:
http://developer.android.com/reference/android/content/SharedPreferences.html
parece que deberías hacer algo como esto
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.
}
Puede hacer esto cada vez, para verificar si la aplicación se ha actualizado, por lo que solo se ejecuta una vez para la actualización de la aplicación
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();
}
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();
}
}