好像我的小 Android 应用程序正在运行多个实例

2023-12-23

我知道这很蹩脚,但我对 Android 开发完全陌生。我正在编写一个基于传感器的应用程序,每次摇动手机时该应用程序都会更改壁纸。一旦应用程序最小化,它就会在后台运行。

当我第一次运行它时,它工作得非常好。但是当我最小化它并重新打开时,它看起来像是该应用程序的 2 个实例正在运行。就这样继续下去。每次我最小化并打开应用程序时,看起来好像又并行启动了一个实例。

其导致的问题:
1:同一应用程序的多个实例监听“摇动”
2:同一应用程序的多个实例尝试更改壁纸
3:应用程序的最后一个实例所做的壁纸更改很明显

我尝试设置如下:
android:clearTaskOnLaunch="true"
android:launchMode="singleInstance"

什么都不起作用。 请帮忙。

下面是清单文件中我的活动类

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="abhijit.android.sensor"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk
            android:minSdkVersion="14"
            android:targetSdkVersion="19" />
         <uses-permission android:name="android.permission.VIBRATE" />
         <uses-permission android:name="android.permission.SET_WALLPAPER" />

        <application
            android:name="abhijit.android.sensor.GlobalVarible"
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="abhijit.android.sensor.SensorTestActivity" 
                android:label="@string/app_name" 
                android:clearTaskOnLaunch="true"
                android:launchMode="singleInstance" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>

    </manifest>

SensorTestActivity.java

    package abhijit.android.sensor;

    import java.io.IOException;
    import java.util.Date;
    import java.util.Random;

    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.WallpaperManager;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.graphics.Color;
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.os.Bundle;
    import android.os.Vibrator;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;

    public class SensorTestActivity extends Activity implements SensorEventListener {
      private SensorManager sensorManager;
      private boolean color = false;
      private View view;
      TextView text;
      private long lastUpdate;
      Random rnd = new Random(); 
      int colors; 
      private Vibrator vibrate;
      GlobalVarible globalVariable;
      WallpaperManager myWallpaperManager;
      Button b1,b2,b3;
      private static String AppVersion ="WALL-e v0.7 (Beta)";


    /** Called when the activity is first created. */

      @Override
      public void onCreate(Bundle savedInstanceState) {
    //    requestWindowFeature(Window.FEATURE_NO_TITLE);
    //    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sensor_test);
        view = findViewById(R.id.textView);
        text = (TextView) findViewById(R.id.textView);
        view.setBackgroundColor(Color.GREEN);
        b1 = (Button) findViewById(R.id.Enable_button);
        b2 = (Button) findViewById(R.id.Dis_button);
        b3 = (Button) findViewById(R.id.Exit_button);


        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        vibrate = (Vibrator) getSystemService(VIBRATOR_SERVICE);
        myWallpaperManager = WallpaperManager.getInstance(getApplicationContext());
        lastUpdate = new Date().getTime();

        // Calling Application class (see application tag in AndroidManifest.xml)
        globalVariable = (GlobalVarible) getApplicationContext();

        //Set name and email in global/application context
        globalVariable.setCounter(0);
        globalVariable.setWall(1);
        System.out.println("Counter set to :" + globalVariable.getCounter());    

      }

      @Override
      public void onSensorChanged(SensorEvent event) 
      {
        if  ((event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)  & globalVariable.appEnabled) {getAccelerometer(event);}
      }
      private void getAccelerometer(SensorEvent event) {


        float[] values = event.values;
        // Movement
        float x = values[0];
        float y = values[1];
        float z = values[2];


        float accelationSquareRoot = (x * x + y * y + z * z) / (SensorManager.GRAVITY_EARTH * SensorManager.GRAVITY_EARTH);
    //    long actualTime = event.timestamp;

        long actualTime = (new Date()).getTime()  + (event.timestamp - System.nanoTime()) / 1000000L;

        if (accelationSquareRoot >= 3) //
        {
            long timediff = actualTime - lastUpdate;

          if (timediff < 1000) {
              return;
          }

    //      Toast.makeText(this, "Detected device movement & working !!! ", Toast.LENGTH_SHORT).show();
          globalVariable.setCounter(globalVariable.getCounter()+1);

          vibrate.vibrate(300);

          if (color) 
          {
              colors= Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
              view.setBackgroundColor(colors);
          } else {
             view.setBackgroundColor(colors);
          }
          color = !color;

          System.out.println("Counter # " + globalVariable.getCounter());

          if(globalVariable.getCounter()==1)
          {

              globalVariable.setCounter(0);               

              try 
              {
                  switch (globalVariable.getWall()) 
                  {
                            case 1:myWallpaperManager.setResource(R.drawable.wall1);break;              
                            case 2:myWallpaperManager.setResource(R.drawable.wall2);break;
                            case 3:myWallpaperManager.setResource(R.drawable.wall3);break;
                            case 4:myWallpaperManager.setResource(R.drawable.wall4);break;
                            case 5:myWallpaperManager.setResource(R.drawable.wall5);break;
                            case 6:myWallpaperManager.setResource(R.drawable.wall6);break;
                            case 7:myWallpaperManager.setResource(R.drawable.wall7);break;
                            case 8:myWallpaperManager.setResource(R.drawable.wall8);break;
                            case 9:myWallpaperManager.setResource(R.drawable.wall9);break;
                            case 10:myWallpaperManager.setResource(R.drawable.wall10);break;
                            case 11:myWallpaperManager.setResource(R.drawable.wall11);break;
                            case 12:myWallpaperManager.setResource(R.drawable.wall12);break;
                            case 13:myWallpaperManager.setResource(R.drawable.wall13);break;
                            case 14:myWallpaperManager.setResource(R.drawable.wall14);break;
                            case 15:myWallpaperManager.setResource(R.drawable.wall15);break;
                            case 16:myWallpaperManager.setResource(R.drawable.wall16);break;
                            case 17:myWallpaperManager.setResource(R.drawable.wall17);break;
                            case 18:myWallpaperManager.setResource(R.drawable.wall18);break;
                            case 19:myWallpaperManager.setResource(R.drawable.wall19);break;
                            case 20:myWallpaperManager.setResource(R.drawable.wall20);break;
                            case 21:myWallpaperManager.setResource(R.drawable.wall21);break;
                            case 22:myWallpaperManager.setResource(R.drawable.wall22);break;
                            case 23:myWallpaperManager.setResource(R.drawable.wall23);break;
                            case 24:myWallpaperManager.setResource(R.drawable.wall24);break;
                            case 25:myWallpaperManager.setResource(R.drawable.wall25);break;
                            case 26:myWallpaperManager.setResource(R.drawable.wall26);break;
                            case 27:myWallpaperManager.setResource(R.drawable.wall27);break;
                            default:break;
                  }           

                   Toast.makeText(this, "Successfully set as wallpaper to :"+globalVariable.getWall(), Toast.LENGTH_SHORT).show();
                   System.out.println("Counter : Wallerpaper Set to #"+globalVariable.getWall());

                   globalVariable.setWall(globalVariable.getWall()+1); 
                   if(globalVariable.getWall()>27) globalVariable.setWall(1);

                   lastUpdate = actualTime;

                  } catch (IOException e) 
                  {Toast.makeText(this, "Error set as wallpaper :", Toast.LENGTH_SHORT).show();}

          }      
        }
      }

      @Override
      public void onAccuracyChanged(Sensor sensor, int accuracy) {

      }

      @Override
      protected void onResume() {
        super.onResume();
        // register this class as a listener for the orientation and
        // accelerometer sensors
        sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
        Toast.makeText(this, "Sensor detection resumed !!!", Toast.LENGTH_SHORT).show();
      }

      @Override
      protected void onPause() {
        // unregister listener
        super.onPause();
    //    sensorManager.unregisterListener(this);
        Toast.makeText(this, "Sensor detection running in background !!!", Toast.LENGTH_SHORT).show();
    //    System.exit(0);
      }
      public void b1_Onclick(View v)
      {
          System.out.println("new Enabled!!!");
          globalVariable.appEnabled=true;
          sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
          text.setText("Application is [ ENABLED ]");

      }

      public void b2_Onclick(View v)
      {
          System.out.println("new Disbled!!!");
          globalVariable.appEnabled=false;
          sensorManager.unregisterListener(this);
          text.setText("Application is [ DISABLED ]");
      }

      public void b3_Onclick(View v)
      {
          System.out.println("new exit!!!");
          sensorManager.unregisterListener(this);
          this.onPause();
          this.finish();
      }

      public void b4_Onclick(View view)
      {

              AlertDialog.Builder dlgAlert  = new AlertDialog.Builder(this);

              dlgAlert.setMessage(AppVersion + " \n \nCopyright \u00a9 2014, \nAbhijit Mishra");
              dlgAlert.setTitle(AppVersion);
              dlgAlert.setPositiveButton("OK", null);
              dlgAlert.setCancelable(true);
              dlgAlert.create().show();

              dlgAlert.setPositiveButton("Ok", new DialogInterface.OnClickListener(){public void onClick(DialogInterface dialog, int which){}});      
      }


    } 

全局变量.Java

    package abhijit.android.sensor;

    import android.app.Application;

    public class GlobalVarible extends Application{


       public int counter,wall;
       boolean appEnabled=true;


       public int getWall() {
        return wall;
    }

    public void setWall(int wall) {
        this.wall = wall;
    }

    public int getCounter() {
        return counter;
    }

       public void setCounter(int counter) {
           this.counter = counter;
    }




    }

请让我知道下一步应该做什么,以便即使我最小化并恢复应用程序,也只有 1 个线程运行。

问候, 阿比吉特


问题就在这里:

  @Override
  protected void onResume() {
    super.onResume();
    // register this class as a listener for the orientation and
    // accelerometer sensors
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
  }

  @Override
  protected void onPause() {
    // unregister listener
    // sensorManager.unregisterListener(this);
  }

您没有取消注册侦听器,因此它被注册了多次。

我理解您想要做的就是即使活动暂停也能继续聆听,并且您could使用布尔标志仅注册一次。但这可能不是一个好主意。不可见的活动可以由系统随时完成。

对于这些类型的用例Service会更合适(作为奖励,您可以将其设置为从BOOT_COMPLETED,以便您在重新启动设备时无需重新运行应用程序来设置此侦听器)。

所以,简而言之,我建议:

  • 创建服务 http://developer.android.com/reference/android/app/Service.html. In onCreate(),将服务注册为侦听器SensorManager(就像你在这里所做的一样)。
  • 当您的活动运行时,发送Intent启动服务(参见docs http://developer.android.com/guide/components/services.html).
  • (可选)指定 ACTION_BOOT_COMPLETED 的侦听器,以便在设备重新启动时重新启动服务。看这个答案 https://stackoverflow.com/questions/4562734/android-starting-service-at-boot-time.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

好像我的小 Android 应用程序正在运行多个实例 的相关文章

  • Web 视图未在 Android 中加载本地 html 文件

    I am integrating html in android I have created a web view But i am not able load local html page Surprisingly web view
  • 将表值参数与 SQL Server JDBC 结合使用

    任何人都可以提供一些有关如何将表值参数 TVP 与 SQL Server JDBC 一起使用的指导吗 我使用的是微软提供的6 0版本的SQL Server驱动程序 我已经查看了官方文档 https msdn microsoft com en
  • 如何持续更新MPAndroidChart中的Y轴值

    我希望 LineChart 中的轴能够实时调整其最大值和最小值 当新数据的 Y 值增加 正值和负值 时 像 ResetAxisMaxValue 和 ResetAxisMinValue 这样的函数可以很好地工作 但是 一旦信号再次变低 Y 值
  • Firebase ANR - 甚至不使用 firebase

    随着 GMS 的最新更新 引入了新的 ANR 如果您退出应用程序 然后返回 则 ANR 就会初始化 线程跟踪似乎指向 Firebase 但我什至从未开始使用 Firebase 我猜它一定是新的 GMS 包的一部分 06 11 00 34 0
  • Java 8 中函数式接口的使用

    这是来自的后续问题Java 8 中的 双冒号 运算符 https stackoverflow com questions 20001427 double colon operator in java 8其中 Java 允许您使用以下方式引用
  • 以编程方式将 TextView 添加到主屏幕小部件

    我想以编程方式将文本视图控件添加到我的主屏幕小部件 在下面的示例中 我使用 TextView 填充 Linearlayout 但是这里应该如何使用 RemoteView 它只接受 xml 资源布局作为参数 public class MyWi
  • 在 Jetpack Compose 中跨可组合函数重复使用一组预览注释

    在 Jetpack Compose 中迈出第一步 这非常令人惊奇 除了一个恼人的问题 我有一组固定的预览 正常 深色和 RTL Preview name Normal group Screen showBackground true Pre
  • 计算日期之间的天数差异

    在我的代码中 日期之间的差异是错误的 因为它应该是 38 天而不是 8 天 我该如何修复 package random04diferencadata import java text ParseException import java t
  • Cloudfoundry:如何组合两个运行时

    cloundfoundry 有没有办法结合两个运行时环境 我正在将 NodeJS 应用程序部署到 IBM Bluemix 现在 我还希望能够执行独立的 jar 文件 但应用程序失败 APP 0 bin sh 1 java not found
  • JavaDoc 在 Android 项目中不起作用

    我在 Ubuntu 10 04 上使用 Eclipse 3 5 2 进行 Android 开发 我安装了 来自 Ubuntu 存储库的 Sun JDK Eclipse 3 5 2 经典 来自 eclipse org 解压到 opt ecli
  • java.lang.IllegalArgumentException:找不到片段的 id 0x1020002 (android:id/content) 的视图

    我正在尝试从一个片段移动到另一个片段 它在片段事务期间显示以下错误 java lang IllegalArgumentException No view found for id 0x1020002 android id content f
  • Dispatcher-servlet 无法映射到 websocket 请求

    我正在开发一个以Spring为主要框架的Java web应用程序 特别使用Spring core Spring mvc Spring security Spring data Spring websocket 像这样在 Spring 上下文
  • Espresso 和 Proguard 的 Java.lang.NoClassDefFoundError

    我对 Espresso 不太有经验 但我终于成功地运行了它 我有一个应用程序需要通过 Proguard 缩小才能处于 56K 方法之下 该应用程序以 3 秒的动画开始 因此我需要等到该动画结束才能继续 这就是我尝试用该方法做的事情waitF
  • 如何在Java中正确删除数组[重复]

    这个问题在这里已经有答案了 我刚接触 Java 4 天 从我搜索过的教程来看 讲师们花费了大量精力来解释如何分配二维数组 例如 如下所示 Foo fooArray new Foo 2 3 但我还没有找到任何解释如何删除它们的信息 从内存的情
  • JSON 到 hashmap (杰克逊)

    我想将 JSON 转换为 HashMapJackson http jackson codehaus org 这是我的 JSON String json Opleidingen name Bijz trajecten zorg en welz
  • Java的-XX:+UseMembar参数是什么

    我在各种地方 论坛等 看到这个参数 并且常见的答案是它有助于高并发服务器 尽管如此 我还是找不到 sun 的官方文档来解释它的作用 另外 它是Java 6中添加的还是Java 5中存在的 顺便说一句 许多热点虚拟机参数的好地方是这一页 ht
  • Hibernate 和可序列化实体

    有谁知道是否有一个框架能够从实体类中剥离 Hibernate 集合以使它们可序列化 我查看了 BeanLib 但它似乎只进行实体的深层复制 而不允许我为实体类中的集合类型指定实现映射 BeanLib 目前不适用于 Hibernate 3 5
  • 直接使用从密钥库加载的 SecretKey 时,密钥用户未经过身份验证

    我正在尝试使用 Cipher 和在 KeyStore 中加载的 SecretKey 来加密数据 但总是收到此错误 导致 android security KeyStoreException 关键用户未经过身份验证 我尝试自己创建 Secre
  • Android 自定义警报对话框中的 OnClickListener

    我是一个自学成才的初学者 感谢耐心 谢谢 在 Eclipse 中 我使用自己的 xml 文件 custom dialog 创建了一个自定义警报对话框 称为 usernamealert 如果用户尚未输入用户名 即 username lengt
  • 在哪里存储 Java 的 .properties 文件?

    The Java教程 http download oracle com javase tutorial essential environment properties htmlon using Properties 讨论如何使用 Prop

随机推荐