如何在每个应用程序启动时执行一次某些操作?

时间:2011-09-09 11:17:57

标签: android android-3.0-honeycomb auto-update

我想在应用程序中实现更新检查程序,显然我只需要在启动应用程序时显示一次。如果我使用onCreate()onStart()方法进行调用,则每次创建活动时都会显示该调用,这不是一个可行的解决方案。

所以我的问题是:每个应用程序启动/启动时,有没有办法做一些事情,例如检查更新?

我很抱歉,如果有点难以理解,我在解释这个问题时遇到了困难。

10 个答案:

答案 0 :(得分:50)

SharedPreferences对我来说似乎是一个难看的解决方案。当您将应用程序构造函数用于此类目的时,它会更加整洁。

您只需要使用自己的Application类,而不是默认类。

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"); 
    }
}

然后,您应该将此类注册为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>

您甚至可以按“返回”按钮,以便应用程序转到后台,并且不会浪费您的处理器资源,只会浪费内存资源,然后您可以再次启动它,并且构建器仍然没有激活,因为应用程序尚未完成。

您可以在任务管理器中清除内存,以便关闭所有应用程序,然后重新启动应用程序以确保初始化代码再次激活。

答案 1 :(得分:4)

看起来你可能不得不做这样的事情

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.
   }

您每次都可以执行此操作,以检查应用是否已升级,因此仅针对应用升级运行一次

答案 2 :(得分:4)

共享首选项方法很混乱,应用程序类无法访问活动。

我使用的另一个替代方案是拥有一个保留的片段实例,并且在该实例中,可以完成更多的工作,尤其是当您需要访问主活动UI时。

对于这个例子,我在保留的片段中使用了asynctask。我的AsyncTask具有对父活动的回调。它保证每个应用程序只运行一次,因为片段永远不会被销毁 - 当同一个活动被销毁 - 重新创建时重新创建。它是一个保留的片段。

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();
        }
    }
}
}

然后,在您希望此启动任务片段运行一次的主(或父)活动中。

@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();
    }

    ...
}

保留片段的想法来自:http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html。除了配置更改之外,我只是想出了它的其他用途。

答案 3 :(得分:2)

是的,你可以使用Android的SharedPrefernce概念。只需创建一个布尔标志并将其保存在SharedPrefernce中,并在onCreate()方法中检查其值。

答案 4 :(得分:0)

我这样做的方式与其他答案中描述的方式相同。我在第一个活动中只有一个全局变量,它与清单中的版本号相匹配。我为每次升级都增加它,当检查看到更高的数字时,它会执行一次性代码。

如果成功,它会将新号码写入共享首选项,因此在下次升级之前不会再次执行此操作。

当您从共享首选项中检索版本时,请确保将默认值指定为-1,以便在再次运行代码时出错,而不是运行代码而不是正确更新应用程序。

答案 5 :(得分:0)

使用SharedPreference -

  1. 如果您的应用处于有效状态时未再次重新启动启动器活动,那么在这种情况下您可以使用它。

  2. 如果您要在应用中实现此功能,请在启动画面中使用此功能。

  3. 如果您没有使用任何启动画面,那么您需要创建一个没有设置视图的活动,并且在它的oncreate调用上,您可以开始更新并开始您的主要活动。

  4. 你可以使用计数器值或布尔值。

    这是SharedPreference doc:

    http://developer.android.com/reference/android/content/SharedPreferences.html

答案 6 :(得分:0)

      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();


                    }

答案 7 :(得分:0)

我刚刚解决了这个问题,我在整个应用程序的执行过程中多次重新打开了我的主要活动。虽然构造函数对于某些事情来说是一种有效的方法,但它不允许您访问当前的Application上下文来编写其他东西

我的解决方案是创建一个简单的&#39; firstRun&#39; boolean在我的MainActivity类中设置为true,从那里我运行if语句的内容然后将其设置为true。例如:

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
}

答案 8 :(得分:0)

 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();
  }
}

答案 9 :(得分:0)

这在@Vitalii的answer上继续进行。

设置Application类后,如果需要访问Activity,我们可以使用恰当命名的android库“ Once” https://github.com/jonfinerty/Once

在Application类的onCreate方法中

Once.initialise(this)

在“活动/片段”类的onCreate / onViewCreated方法中。

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
}