Android 如何在每次应用程序启动时只执行一次?

Android 如何在每次应用程序启动时只执行一次?,android,android-3.0-honeycomb,auto-update,Android,Android 3.0 Honeycomb,Auto Update,我想在应用程序中实现一个更新检查器,我显然只需要在启动应用程序时显示一次。如果我在onCreate()或onStart()方法中进行调用,则每次创建活动时都会显示该调用,这不是可行的解决方案 所以我的问题是:是否有一种方法可以做一些事情,比如检查更新,每次应用程序启动/启动一次? 如果有点难理解,我很抱歉,我很难解释我自己在这一点上的意思。是的,你可以使用android的SharedPreference概念。只需创建一个布尔标志并将其保存在SharedPrefernce中,然后在onCreate

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

所以我的问题是:是否有一种方法可以做一些事情,比如检查更新,每次应用程序启动/启动一次?


如果有点难理解,我很抱歉,我很难解释我自己在这一点上的意思。

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

我使用与另一个答案中所述相同的方法执行此操作。我只是在第一个活动中有一个全局变量,它与清单中的版本号相匹配。每次升级时,我都会增加它,当检查看到更大的数字时,它会执行一次性代码

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


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

看起来您可能需要执行类似操作

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

您每次都可以执行此操作,以检查应用程序是否已升级,因此它仅为应用程序升级运行一次-

  • 如果你的应用程序激活后没有重新启动启动程序活动,那么就使用它

  • 如果要在应用程序中实现,请在启动屏幕中使用此选项

  • 如果您没有使用任何初始屏幕,那么您需要创建一个没有视图集的活动,在它的oncreate调用中,您可以执行启动更新并启动主活动

  • 您可以为此使用计数器值或布尔值

    以下是SharedReference文档:


    共享参考对我来说似乎是一个丑陋的解决方案。当您将应用程序构造函数用于此类目的时,它会更加简洁

    您只需要使用自己的应用程序类,而不是默认的应用程序类

    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>
    

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

    我使用的另一个替代方法是保留一个片段实例,在该实例中,可以做更多的事情,特别是当您需要访问主活动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();
            }
        }
    }
    }
    

    保留片段的想法来自这里:。除了配置更改之外,我还发现了它的其他用途。

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

    我的解决方案是在MainActivity类中创建一个简单的“firstRun”布尔值集,然后运行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
    }
    
    SharedReferences prefs=PreferenceManager.GetDefaultSharedReferences(此选项);
    if(!prefs.getBoolean(“onlyonce”,false)){
    
    //这在@Vitalii的网站上继续

    在设置了应用程序类之后,如果需要访问活动,我们可以“一次”使用恰当命名的android库

    在应用程序类的
    onCreate
    方法中

    一次。初始化(此)
    
    在Activity/Fragment类的
    onCreate
    /
    onViewCreated
    方法中

    val helloTag=“你好”
    if(!one.beenDone(one.THIS\u APP\u SESSION,helloTag)){
    //做一些只需要做一次的事情
    Once.markDone(helloTag)//标记完成
    }
    
    唯一的问题是,当您退出应用程序时,SharedReference没有被清除。幸运的是,我的应用程序包含一个启动屏幕,每次启动应用程序时都可以用它重置SharedReference。不知道为什么我以前没有想到这一点-感谢您朝着正确的方向推动:-)所以这不是一个每次应用程序升级需要时间,但每次启动需要一次?是的,你是绝对正确的。你可以做的另一件事是,每当你开始你的活动,在那里你已经为更新检查器编写了代码,你可以使用intent.setFlag(FLAG_Activity_REORDER_TO_FRONT)以便onCreate()不会再被调用。如果你需要一次应用程序升级,请检查我的答案。我基本上只是在启动屏幕上使用带有布尔值的Intent extras来判断它是否正在启动(如果从启动屏幕启动,则为true,如果从其他任何内容启动,则为false)。它工作得很好。+1这是真正的解决方案,SharedReferences会让一切变得复杂,让事情变得混乱!这也不是真正的解决方案。当您从应用程序管理器执行“清除数据”时,构造函数将再次执行。代码应仅在重新安装应用程序或新安装时运行,而不是在执行清除数据操作时运行:'(@Rauf抱歉,现在无法测试,但无法“清除数据”关闭应用程序?清除数据和卸载之间几乎没有区别。清除数据会使应用程序恢复到刚安装时的状态。即,它只是删除了与之相关的所有数据。但我需要捕获一个新的installation@Rauf这个主题是关于应用程序启动,而不是应用程序安装。因为我认为所有的解决方案都有S当您
    @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();
        }
    
        ...
    }
    
    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
    }
    
     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();
      }
    }