使用广播在 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 出现。
正在开发一个应该通过广播生成随机字符的应用程序。我需要广播由我的自定义服务生成的随机字符,以便注册拦截广播的主 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 出现。