【发布时间】:2019-03-08 18:57:00
【问题描述】:
正在开发一个应该通过广播生成随机字符的应用。我需要广播自定义服务生成的随机字符,以便注册拦截广播的主要活动可以获取随机数并将它们显示在 EditText 上。此处显示布局:app layout
开始按钮会触发随机字符生成服务。 EditText 将显示实时生成的随机数(无需按下任何按钮)。停止按钮将停止服务。 EditText 不会显示任何数字。我创建了一个服务(RandomCharacterService)并将其注册到我的清单中。运行应用程序后,我的应用程序崩溃。我确定这是因为我没有在清单中注册我的广播,但我不明白该怎么做。也许我在主要活动中处理广播的方式有问题。在开始按钮的按钮单击方法中,我尝试执行 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
【问题讨论】:
-
您应该包含您遇到的崩溃的调用堆栈。
-
注明,包括在内!
-
1.您不会在活动中初始化
myService,因此它总是会抛出 NPE。 2.您有一个竞争条件,您在一个按钮按下时使用serviceIntent,但在另一个按钮中对其进行初始化。目前,无法保证按特定顺序按下按钮。 -
哦,我明白了。那么我将如何初始化 myService?
标签: java android random broadcastreceiver