Arraylist 在构造函数内部正确分配,但在 Android Studio 服务外部时为 null
Arraylist being assigned correctly inside a constructor but is null when it is outside in a Android Studio Service
我似乎无法弄清楚为什么每当我尝试将从 MainActivity
收到的数组列表分配给服务的后台服务 SensorService
的 public 数组列表时构造函数。
这是我的构造函数
public SensorService(ArrayList<String> contactListNumber) {
contactNumbers=contactListNumber;
Log.d(TAG, "Inside Constructor");
Log.d(TAG, "SensorService: Phone Numbers = "+contactListNumber);
Log.d(TAG, "SensorService: Input Arraylist Size = "+contactListNumber.size());
Log.d(TAG, "SensorService: Assigned Arraylist Size = "+contactNumbers.size());
setPhoneNumberArray(contactListNumber);
}
我什至尝试调用一个方法,但它仍然给我正确分配 contactNumbers
的相同结果,但是当我尝试在 onCreate 中调用它时,我得到一个 NullPointerException。
这是我创建服务的 MainActivity
Intent
SensorService sensorService = new SensorService(Contact_Number);
Intent intent = new Intent(this, sensorService.getClass());
if(!isMyServiceRunning(sensorService.getClass())){
startService(intent);
//intent.putExtra("ContactNumberList", Contact_Number);
Toast.makeText(this, "Starting Service", Toast.LENGTH_SHORT).show();
}
这是我的完整 SensorService
。
public class SensorService extends Service {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShakeDetector mShakeDetector;
public ArrayList<String> contactNumbers;
public SensorService() {
}
public SensorService(ArrayList<String> contactListNumber) {
contactNumbers=contactListNumber;
Log.d(TAG, "Inside Constructor");
Log.d(TAG, "SensorService: Phone Numbers = "+contactListNumber);
Log.d(TAG, "SensorService: Input Arraylist Size = "+contactListNumber.size());
Log.d(TAG, "SensorService: Assigned Arraylist Size = "+contactNumbers.size());
setPhoneNumberArray(contactListNumber);
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onCreate() {
//contactNumbers=MainActivity.Contact_Numbers;
super.onCreate();
// start the foreground service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
// ShakeDetector initialization
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mShakeDetector = new ShakeDetector();
Log.d(TAG, "SensorService: Assigned Arraylist Size Outside Constructor = "+contactNumbers.size());
mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {
@SuppressLint("MissingPermission")
@Override
public void onShake(int count) {
// check if the user has shacked
// the phone for 3 time in a row
//if (count == 3)
if (count == 1) {
// vibrate the phone
vibrate();
Log.d(TAG, "onShake: Vibrate Activated");
// create FusedLocationProviderClient to get the user location
FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(getApplicationContext());
Log.d("Check: ", "Sending Message");
// use the PRIORITY_BALANCED_POWER_ACCURACY
// so that the service doesn't use unnecessary power via GPS
// it will only use GPS at this very moment
fusedLocationClient.getCurrentLocation(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY, new CancellationToken() {
@Override
public boolean isCancellationRequested() {
return false;
}
@NonNull
@Override
public CancellationToken onCanceledRequested(@NonNull OnTokenCanceledListener onTokenCanceledListener) {
return null;
}
}).addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
// check if location is null
// for both the cases we will
// create different messages
Log.d("Check: ", "MESSAGE SENT");
if (location != null) {
// get the SMSManager
SmsManager smsManager = SmsManager.getDefault();
// get the list of all the contacts in Database
DatabaseHelper db = new DatabaseHelper(SensorService.this);
ArrayList<String> Contact_id, Contact_Name, Contact_Number;
ArrayList<String> phonenumber = new ArrayList<String>();
Log.d(TAG, "onSuccess: contactlistnumber size = "+contactNumbers.size());
String[] phoneNumberList = new String[contactNumbers.size()];
phoneNumberList = contactNumbers.toArray(phoneNumberList);
Log.d(TAG, "onSuccess: Item 1 = "+phoneNumberList[0]);
for(int i = 0; i < phoneNumberList.length ; i++){
Log.d("Number is",(String)phoneNumberList[i]);
}
//phonenumber = (ArrayList<String>)getIntent().getSerializableExtra("ContactNumberList");
// send SMS to each contact
for (String c : phoneNumberList) {
String message = "Hey, I am in DANGER, i need help. Please urgently reach me out. Here are my coordinates.\n " + "http://maps.google.com/?q=" + location.getLatitude() + "," + location.getLongitude();
smsManager.sendTextMessage(c, null, message, null, null);
}
} else {
String message = "I am in DANGER, i need help. Please urgently reach me out.\n" + "GPS was turned off.Couldn't find location. Call your nearest Police Station.";
SmsManager smsManager = SmsManager.getDefault();
DatabaseHelper db = new DatabaseHelper(SensorService.this);
List<ContactInfo> list = (List<ContactInfo>) db.getEveryone();
String[] phoneNumberList = new String[contactNumbers.size()];
phoneNumberList = contactNumbers.toArray(phoneNumberList);
for (String c : phoneNumberList) {
smsManager.sendTextMessage(c, null, message, null, null);
}
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d("Check: ", "OnFailure");
String message = "I am in DANGER, i need help. Please urgently reach me out.\n" + "GPS was turned off.Couldn't find location. Call your nearest Police Station.";
SmsManager smsManager = SmsManager.getDefault();
DatabaseHelper db = new DatabaseHelper(SensorService.this);
List<ContactInfo> list = (List<ContactInfo>) db.getEveryone();
String[] phoneNumberList = new String[contactNumbers.size()];
phoneNumberList = contactNumbers.toArray(phoneNumberList);
for (String c : phoneNumberList){
smsManager.sendTextMessage(c, null, message, null, null);
}
}
});
}
}
});
// register the listener
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
// method to vibrate the phone
public void vibrate() {
final Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
VibrationEffect vibEff;
// Android Q and above have some predefined vibrating patterns
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
vibEff = VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK);
vibrator.cancel();
vibrator.vibrate(vibEff);
} else {
vibrator.vibrate(500);
}
}
// For Build versions higher than Android Oreo, we launch
// a foreground service in a different way. This is due to the newly
// implemented strict notification rules, which require us to identify
// our own notification channel in order to view them correctly.
@RequiresApi(Build.VERSION_CODES.O)
private void startMyOwnForeground() {
String NOTIFICATION_CHANNEL_ID = "example.permanence";
String channelName = "Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_MIN);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setContentTitle("You are protected.")
.setContentText("We are there for you")
// this is important, otherwise the notification will show the way
// you want i.e. it will show some default notification
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
@Override
public void onDestroy() {
// create an Intent to call the Broadcast receiver
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, ReactivateService.class);
this.sendBroadcast(broadcastIntent);
super.onDestroy();
}
public void setPhoneNumberArray(ArrayList numbers) {
contactNumbers=numbers;
//Log.d(TAG, "setPhoneNumberArray: contactnumbers size = "+contactNumbers.size());
}
}
如果有人能告诉我为什么会这样,我将不胜感激。
我发现了我的错误。
对于任何其他试图这样做的人。
我犯了一个非常短视的错误,没有将 Arraylist contactNumbers
声明为静态的。
这是之前的样子。
public ArrayList<String> contactNumbers;
最后的时候我加了static关键字。这样它看起来像
static public ArrayList<String> contactNumbers;
.
其他一切似乎都正常工作。因为我现在可以在服务中获取 contactNumbers
的值。
我似乎无法弄清楚为什么每当我尝试将从 MainActivity
收到的数组列表分配给服务的后台服务 SensorService
的 public 数组列表时构造函数。
这是我的构造函数
public SensorService(ArrayList<String> contactListNumber) {
contactNumbers=contactListNumber;
Log.d(TAG, "Inside Constructor");
Log.d(TAG, "SensorService: Phone Numbers = "+contactListNumber);
Log.d(TAG, "SensorService: Input Arraylist Size = "+contactListNumber.size());
Log.d(TAG, "SensorService: Assigned Arraylist Size = "+contactNumbers.size());
setPhoneNumberArray(contactListNumber);
}
我什至尝试调用一个方法,但它仍然给我正确分配 contactNumbers
的相同结果,但是当我尝试在 onCreate 中调用它时,我得到一个 NullPointerException。
这是我创建服务的 MainActivity
Intent
SensorService sensorService = new SensorService(Contact_Number);
Intent intent = new Intent(this, sensorService.getClass());
if(!isMyServiceRunning(sensorService.getClass())){
startService(intent);
//intent.putExtra("ContactNumberList", Contact_Number);
Toast.makeText(this, "Starting Service", Toast.LENGTH_SHORT).show();
}
这是我的完整 SensorService
。
public class SensorService extends Service {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShakeDetector mShakeDetector;
public ArrayList<String> contactNumbers;
public SensorService() {
}
public SensorService(ArrayList<String> contactListNumber) {
contactNumbers=contactListNumber;
Log.d(TAG, "Inside Constructor");
Log.d(TAG, "SensorService: Phone Numbers = "+contactListNumber);
Log.d(TAG, "SensorService: Input Arraylist Size = "+contactListNumber.size());
Log.d(TAG, "SensorService: Assigned Arraylist Size = "+contactNumbers.size());
setPhoneNumberArray(contactListNumber);
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onCreate() {
//contactNumbers=MainActivity.Contact_Numbers;
super.onCreate();
// start the foreground service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
// ShakeDetector initialization
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mShakeDetector = new ShakeDetector();
Log.d(TAG, "SensorService: Assigned Arraylist Size Outside Constructor = "+contactNumbers.size());
mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {
@SuppressLint("MissingPermission")
@Override
public void onShake(int count) {
// check if the user has shacked
// the phone for 3 time in a row
//if (count == 3)
if (count == 1) {
// vibrate the phone
vibrate();
Log.d(TAG, "onShake: Vibrate Activated");
// create FusedLocationProviderClient to get the user location
FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(getApplicationContext());
Log.d("Check: ", "Sending Message");
// use the PRIORITY_BALANCED_POWER_ACCURACY
// so that the service doesn't use unnecessary power via GPS
// it will only use GPS at this very moment
fusedLocationClient.getCurrentLocation(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY, new CancellationToken() {
@Override
public boolean isCancellationRequested() {
return false;
}
@NonNull
@Override
public CancellationToken onCanceledRequested(@NonNull OnTokenCanceledListener onTokenCanceledListener) {
return null;
}
}).addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
// check if location is null
// for both the cases we will
// create different messages
Log.d("Check: ", "MESSAGE SENT");
if (location != null) {
// get the SMSManager
SmsManager smsManager = SmsManager.getDefault();
// get the list of all the contacts in Database
DatabaseHelper db = new DatabaseHelper(SensorService.this);
ArrayList<String> Contact_id, Contact_Name, Contact_Number;
ArrayList<String> phonenumber = new ArrayList<String>();
Log.d(TAG, "onSuccess: contactlistnumber size = "+contactNumbers.size());
String[] phoneNumberList = new String[contactNumbers.size()];
phoneNumberList = contactNumbers.toArray(phoneNumberList);
Log.d(TAG, "onSuccess: Item 1 = "+phoneNumberList[0]);
for(int i = 0; i < phoneNumberList.length ; i++){
Log.d("Number is",(String)phoneNumberList[i]);
}
//phonenumber = (ArrayList<String>)getIntent().getSerializableExtra("ContactNumberList");
// send SMS to each contact
for (String c : phoneNumberList) {
String message = "Hey, I am in DANGER, i need help. Please urgently reach me out. Here are my coordinates.\n " + "http://maps.google.com/?q=" + location.getLatitude() + "," + location.getLongitude();
smsManager.sendTextMessage(c, null, message, null, null);
}
} else {
String message = "I am in DANGER, i need help. Please urgently reach me out.\n" + "GPS was turned off.Couldn't find location. Call your nearest Police Station.";
SmsManager smsManager = SmsManager.getDefault();
DatabaseHelper db = new DatabaseHelper(SensorService.this);
List<ContactInfo> list = (List<ContactInfo>) db.getEveryone();
String[] phoneNumberList = new String[contactNumbers.size()];
phoneNumberList = contactNumbers.toArray(phoneNumberList);
for (String c : phoneNumberList) {
smsManager.sendTextMessage(c, null, message, null, null);
}
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d("Check: ", "OnFailure");
String message = "I am in DANGER, i need help. Please urgently reach me out.\n" + "GPS was turned off.Couldn't find location. Call your nearest Police Station.";
SmsManager smsManager = SmsManager.getDefault();
DatabaseHelper db = new DatabaseHelper(SensorService.this);
List<ContactInfo> list = (List<ContactInfo>) db.getEveryone();
String[] phoneNumberList = new String[contactNumbers.size()];
phoneNumberList = contactNumbers.toArray(phoneNumberList);
for (String c : phoneNumberList){
smsManager.sendTextMessage(c, null, message, null, null);
}
}
});
}
}
});
// register the listener
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
// method to vibrate the phone
public void vibrate() {
final Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
VibrationEffect vibEff;
// Android Q and above have some predefined vibrating patterns
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
vibEff = VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK);
vibrator.cancel();
vibrator.vibrate(vibEff);
} else {
vibrator.vibrate(500);
}
}
// For Build versions higher than Android Oreo, we launch
// a foreground service in a different way. This is due to the newly
// implemented strict notification rules, which require us to identify
// our own notification channel in order to view them correctly.
@RequiresApi(Build.VERSION_CODES.O)
private void startMyOwnForeground() {
String NOTIFICATION_CHANNEL_ID = "example.permanence";
String channelName = "Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_MIN);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setContentTitle("You are protected.")
.setContentText("We are there for you")
// this is important, otherwise the notification will show the way
// you want i.e. it will show some default notification
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
@Override
public void onDestroy() {
// create an Intent to call the Broadcast receiver
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, ReactivateService.class);
this.sendBroadcast(broadcastIntent);
super.onDestroy();
}
public void setPhoneNumberArray(ArrayList numbers) {
contactNumbers=numbers;
//Log.d(TAG, "setPhoneNumberArray: contactnumbers size = "+contactNumbers.size());
}
}
如果有人能告诉我为什么会这样,我将不胜感激。
我发现了我的错误。
对于任何其他试图这样做的人。
我犯了一个非常短视的错误,没有将 Arraylist contactNumbers
声明为静态的。
这是之前的样子。
public ArrayList<String> contactNumbers;
最后的时候我加了static关键字。这样它看起来像
static public ArrayList<String> contactNumbers;
.
其他一切似乎都正常工作。因为我现在可以在服务中获取 contactNumbers
的值。