使用广播在 Android Studio 中生成随机字符

Generate Random Characters in Android Studio using Broadcast

正在开发一个应该通过广播生成随机字符的应用程序。我需要广播由我的自定义服务生成的随机字符,以便注册拦截广播的主 activity 可以获得随机数并将它们显示在 EditText 上。布局如下所示:app layout

开始按钮将触发随机字符生成器服务。 EditText 将显示实时生成的随机数(无需按下任何按钮)。停止按钮将停止服务。 EditText 不会显示任何数字。我创建了一个服务 (RandomCharacterService) 并将其注册到我的清单中。在 运行 该应用程序上,我的应用程序崩溃了。我确定这是因为我没有在我的清单中注册我的广播,但我不知道该怎么做。也许我在主 activity 中处理广播的方式有问题。在开始按钮的按钮单击方法中,我尝试执行 for 循环,但这也导致应用程序崩溃。

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.cs7455rehmarazzaklab8">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".RandomCharacterService"></service>

    </application>

MainActivityjava:

    package com.example.cs7455rehmarazzaklab8;

    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.content.BroadcastReceiver;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.graphics.Color;
    import android.graphics.drawable.ColorDrawable;
    import android.support.constraint.ConstraintLayout;
    import android.support.v4.content.LocalBroadcastManager;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.Window;
    import android.widget.Button;
    import android.widget.Toast;
    import java.util.Random;

    public class MainActivity extends AppCompatActivity
    {
        private Button btnStart, btnStop;
        private EditText myTV;

        private Intent serviceIntent;
        private RandomCharacterService myService;
        private ServiceConnection myServiceConnection;
        private boolean isServiceOn; //checks if the service is on

        private int myRandomCharacter;
        char MyRandomCharacter = (char)myRandomCharacter;
        private boolean isRandomGeneratorOn;

        private final int MIN = 65;
        char m = (char)MIN;
        private final int MAX = 26;
        char x = (char)MAX;
        private final String TAG = "Random Char Service: ";

        private final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        private Context mContext;
        private Random mRandom = new Random();

        // Initialize a new BroadcastReceiver instance
        private BroadcastReceiver mRandomCharReceiver = new BroadcastReceiver() 
    {
            @Override
            public void onReceive(Context context, Intent intent) {
            // Get the received random number
            myRandomCharacter = intent.getIntExtra("RandomCharacter",-1);

            // Display a notification that the broadcast received
            Toast.makeText(context,"Received : " + myRandomCharacter,Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        requestWindowFeature(Window.FEATURE_ACTION_BAR);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Get the application context
        mContext = getApplicationContext();

        btnStart = (Button) findViewById(R.id.StartButton);
        btnStop = (Button) findViewById(R.id.StopButton);


        myTV = (EditText)findViewById(R.id.RandomCharText);

        // Register the local broadcast
        LocalBroadcastManager.getInstance(mContext).registerReceiver(mRandomCharReceiver, new IntentFilter("BROADCAST_RANDOM_CHARACTER"));

        // Change the action bar color
        getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#FFFF00BF")));

        // Set a click listener for start button
        btnStart.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                isServiceOn = true;

                serviceIntent = new Intent(getApplicationContext(), RandomCharacterService.class);
                startService(serviceIntent);
                setRandomNumber();
                // Generate a random char
                myRandomCharacter = new Random().nextInt(x)+m;

                // Initialize a new intent instance
                Intent intent = new Intent("BROADCAST_RANDOM_CHARACTER");
                // Put the random character to intent to broadcast it
                intent.putExtra("RandomCharacter",myRandomCharacter);

                // Send the broadcast
                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);

                // Update the TextView with random character
                myTV.setText(" " + myRandomCharacter );
            }
        });

        btnStop.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                isServiceOn = false;

                stopService(serviceIntent);
            }
        });
    }
    private void setRandomNumber()
    {
        myTV.setText("Random Character: " + (char)myService.getRandomCharacter());
        String alphabet = myTV.getText().toString();

    }

}

RandomCharacterService.java:

    package com.example.cs7455rehmarazzaklab8;

    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.support.annotation.IntDef;
    import android.support.annotation.Nullable;
    import android.util.Log;

    import java.util.Random;


    public class RandomCharacterService extends Service
    {
        private int myRandomCharacter;
        char MyRandomCharacter = (char)myRandomCharacter;
        private boolean isRandomGeneratorOn;

        private final int MIN = 65;
        char m = (char)MIN;
        private final int MAX = 26;
        char x = (char)MAX;
        private final String TAG = "Random Char Service: ";

        private final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        class RandomCharacterServiceBinder extends Binder{
            public RandomCharacterService getService()
            {
                return RandomCharacterService.this;
            }
        }

    private IBinder myBinder = new RandomCharacterServiceBinder();

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.i(TAG, "In OnStartCommand Thread ID is "+Thread.currentThread().getId());
        isRandomGeneratorOn = true;

        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                startRandomGenerator();
            }
        }
        ).start();

        return START_STICKY;
    }

    private void startRandomGenerator()
    {
        while(isRandomGeneratorOn)
        {
            char alphabet = 'A';
            for (int i = 65; i < 90; i++)
            {
                try
                {
                    Thread.sleep(1000);
                    if(isRandomGeneratorOn)
                    {
                        alphabet++;
                        myRandomCharacter = new Random().nextInt(x)+m;
                        Log.i(TAG, "Thread ID is "+Thread.currentThread().getId() + ", Random character is "+(char)myRandomCharacter);
                    }
                }
                catch(InterruptedException e)
                {
                    Log.i(TAG, "Thread Interrupted.");
                }

            }

        }

    }

    private void stopRandomGenerator()
    {
        isRandomGeneratorOn = false;
    }

    public int getRandomCharacter()
    {
        return myRandomCharacter;
    }

    public boolean isRandomGeneratorOn() {
        return isRandomGeneratorOn;
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        stopRandomGenerator();
        Log.i(TAG, "Service Destroyed.");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent)
    {
        Log.i(TAG, "In onBind ...");
        return myBinder;
    }
}

调用堆栈:callstack from running the app

尝试按下停止按钮时调用堆栈:crash from attempting to press stop button

由于您使用的是绑定服务(使用Ibinder)。您必须通过调用 bindService 而不是 startService 来启动服务。但在此之前,您需要初始化 ServiceConnection 变量并更好地使用 isServiceOn 布尔值,如下例所示。

private ServiceConnection myServiceConnection = new ServiceConnection() {
    @Override
    // IBinder interface is through which we receive the service object for communication.
    public void onServiceConnected(ComponentName name, IBinder binder) {
        RandomCharacterServiceBinder myBinder = (RandomCharacterServiceBinder) binder;
        isServiceOn = true;
        myService = myBinder.getService();
        Toast.makeText(context,"Service connected", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        isServiceOn = false;
        myService = null;
    }
};

调用onServiceConnected后,您将获得您的服务对象。您的服务很可能会在您执行点击之前被初始化。但只是为了确保您可以在其中 TOAST 一些消息。

并且您应该在 Activity 的 onCreate 方法中启动服务,这样服务将有一些时间来创建。因此,将下面的代码从您单击侦听器移至 onCreate 方法。

serviceIntent = new Intent(getApplicationContext(), RandomCharacterService.class);
// startService(serviceIntent); <-- remove this line, call bindService
bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);

并等待服务连接 Toast 出现。