我正在尝试启动服务,但出现错误。 我不知道如何解决这个特定的问题。 我正在上课的班级:
package com.example.test;
public class Purchase extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_purchase);
final Intent i = new Intent(this,MyHostApduService.class);
Livedate<User> user = *something*;
user.observe(Purchase.this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
i.putExtra("user name", user.getUserName());
i.putExtra("credit card", user.getCreditCard());
i.putExtra("context", Purchase.class);
i.putExtra("mail", user.getMail());
}
});
Toast.makeText(Purchase.this, "YOU CAN ONLY MAKE A PURCHASE AFTER GETTING CLOSE TO THE OTHER DEVICE", Toast.LENGTH_SHORT).show();
this.startService(i);
}
}
服务:
public int onStartCommand(Intent intent, int flags, int startId) {
creditCard = intent.getExtras().getString("credit card");
return START_STICKY;
}
错误:
java.lang.RuntimeException: Unable to start service com.example.test.MyHostApduService@fe81f37 with Intent { cmp=com.example.test/.MyHostApduService }:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
答案 0 :(得分:0)
问题::在“购买”活动中,启动MyHostApduService服务时,您没有在意图上加任何额外的内容,这就是为什么总会出现NullPointerException的原因。
解决方案::从您的代码中,我想您想先启动服务,每当用户在活动中发生更改时,便希望将用户送至服务中心进行处理。
步骤1:更改User类以实现Parcelable接口。
public class User implements Parcelable {
private String userName;
private String creditCard;
private String mail;
public User() {
}
protected User(Parcel in) {
userName = in.readString();
creditCard = in.readString();
mail = in.readString();
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getCreditCard() {
return creditCard;
}
public void setCreditCard(String creditCard) {
this.creditCard = creditCard;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(userName);
dest.writeString(creditCard);
dest.writeString(mail);
}
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
步骤2:更改活动中的代码
user.observe(Purchase.this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
i.putExtra("user", user);
Purchase.this.startService(i);
}
});
步骤3:更改服务中的代码。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
user = intent.getParcelableExtra("user");
if (user == null) {
// The first time this service is started, user is not change yet.
} else {
// The next time this service is started, user is changed.
Log.i("TAG", user.getCreditCard() + "");
}
return START_STICKY;
}
答案 1 :(得分:0)
您要传递给服务的意图没有属性“信用卡”。这是因为您启动服务时的意图是空的(没有其他功能)。仅在LiveData发生更改时才执行代码i.putExtra("credit card", user.getCreditCard());
。当活动首次开始时,没有任何东西触发LiveData的onChanged。
答案 2 :(得分:0)
我建议在这里阅读有关事件循环的内容,如果您搜索“ android事件循环”,那么这里有一些不错的文章。
有效地是,您的方法“ onCreate”和“ onChanged”都是回调。 “ onCreate”将在“ onChanged”开始之前完全执行。这意味着您在不带任何参数的情况下启动服务会得到空指针异常。通常,如果可以避免,您不想跨多个回调使用对象。
解决此问题的一种可能方法是在收到新数据时启动服务。但是请注意,如果可以对用户数据进行多次更改,会发生什么情况。
package com.example.test;
public class Purchase extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_purchase);
Livedate<User> user = *something*;
user.observe(Purchase.this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
final Intent i = new Intent(this,MyHostApduService.class);
i.putExtra("user name", user.getUserName());
i.putExtra("credit card", user.getCreditCard());
i.putExtra("context", Purchase.class);
i.putExtra("mail", user.getMail());
Purchase.this.startService(i);
Toast...
}
});
}
}