Android开发报错:getApplicationContext()空对象引用求助
Android Firebase推送通知:getApplicationContext()空对象引用问题修复
问题描述
我是Android开发新手,因找不到解决方案来发帖求助。我想通过管理员APP给所有用户发送Firebase推送通知,实现后出现了getApplicationContext()空对象引用错误,错误出现在Push_Notification_All和MySingleton类中,相关代码如下:
Push_Notification_All类代码
public class Push_Notification_All extends AppCompatActivity { private final String FCM_API = "https://fcm.googleapis.com/fcm/send"; String NOTIFICATION_MESSAGE; String NOTIFICATION_TITLE; final String TAG = "NOTIFICATION TAG"; String TOPIC; private final String contentType = "application/json"; final Context context = this; EditText edtMessage; EditText edtTitle; Dialog loading; ProgressBar progressBar; private final String serverKey = "key=ABBBAdfgfgzyw:APA91bFfdgdfgAFGveSeXnCNpglbKvpbd9-zu538Z1kA-QdMA41gRb2bgSXcu-2jlk1vhnY8ajXor-PYglN5H68ECTNqHeabfACfD8amSFRIghvGXsmIgEi6Ykw6Jlv2ihhdghfhhgBPr"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_push__notification__all); edtTitle = (EditText) findViewById(R.id.edtTitle); edtMessage = (EditText) findViewById(R.id.edtMessage); loading = new Dialog(context); loading.setContentView(R.layout.loading); progressBar = (ProgressBar) loading.findViewById(R.id.spn_1); ((Button) findViewById(R.id.btnSend)).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (!AppStatus.getInstance(Push_Notification_All.this).isOnline()) { Toast.makeText(Push_Notification_All.this, "Internet is not Available", Toast.LENGTH_SHORT).show(); return; } Push_Notification_All.this.loading.show(); Push_Notification_All.this.loading.setCancelable(false); Push_Notification_All.this.progressBar.setIndeterminateDrawable(new Circle()); Push_Notification_All push_Notification_All = Push_Notification_All.this; push_Notification_All.TOPIC = "/topics/userABC"; push_Notification_All.NOTIFICATION_TITLE = push_Notification_All.edtTitle.getText().toString(); Push_Notification_All push_Notification_All2 = Push_Notification_All.this; push_Notification_All2.NOTIFICATION_MESSAGE = push_Notification_All2.edtMessage.getText().toString(); JSONObject jSONObject = new JSONObject(); JSONObject jSONObject2 = new JSONObject(); try { jSONObject2.put("title", Push_Notification_All.this.NOTIFICATION_TITLE); jSONObject2.put("message", Push_Notification_All.this.NOTIFICATION_MESSAGE); jSONObject.put("to", Push_Notification_All.this.TOPIC); jSONObject.put("data", jSONObject2); } catch (JSONException e) { Push_Notification_All.this.loading.dismiss(); Log.e(TAG, "onCreate: " + e.getMessage()); } Push_Notification_All.this.sendNotification(jSONObject); } }); } public void sendNotification(JSONObject jSONObject) { MySingleton.getInstance(Push_Notification_All.this).addToRequestQueue(new JsonObjectRequest(FCM_API, jSONObject, new Response.Listener<JSONObject>() { public void onResponse(JSONObject jSONObject) { Log.i(TAG, "onResponse: " + jSONObject.toString()); Push_Notification_All.this.edtTitle.setText(""); Push_Notification_All.this.edtMessage.setText(""); Push_Notification_All.this.loading.dismiss(); } }, new Response.ErrorListener() { public void onErrorResponse(VolleyError volleyError) { Push_Notification_All.this.loading.dismiss(); Toast.makeText(Push_Notification_All.this, "Request error", Toast.LENGTH_LONG).show(); Log.i(TAG, "onErrorResponse: Didn't work"); } }) { public Map<String, String> getHeaders() throws AuthFailureError { HashMap hashMap = new HashMap(); hashMap.put("Authorization", serverKey); hashMap.put("Content-Type", contentType); return hashMap; } }); } }
MySingleton类代码
public class MySingleton { private static MySingleton instance; private Context ctx; private RequestQueue requestQueue = getRequestQueue(); private MySingleton(Context context) { ctx = context; } public static synchronized MySingleton getInstance(Context context) { MySingleton mySingleton; synchronized (MySingleton.class) { if (instance == null) { instance = new MySingleton(context); } mySingleton = instance; } return mySingleton; } public RequestQueue getRequestQueue() { if (requestQueue == null) { requestQueue = Volley.newRequestQueue(ctx.getApplicationContext()); } return requestQueue; } public <T> void addToRequestQueue(Request<T> request) { getRequestQueue().add(request); } }
问题原因与修复方案
核心原因
MySingleton中在成员变量声明阶段直接调用getRequestQueue()初始化requestQueue,此时构造方法还未执行,ctx变量尚未被赋值,调用ctx.getApplicationContext()自然会抛出空对象引用异常。
修复步骤
1. 修正MySingleton类的初始化逻辑
将requestQueue的初始化延迟到getRequestQueue()方法中,同时改为持有应用上下文以避免Activity上下文泄漏:
public class MySingleton { private static MySingleton instance; private Context ctx; private RequestQueue requestQueue; // 仅声明,不在此处初始化 private MySingleton(Context context) { // 直接持有应用上下文,避免Activity销毁时引发内存泄漏 ctx = context.getApplicationContext(); } public static synchronized MySingleton getInstance(Context context) { if (instance == null) { instance = new MySingleton(context); } return instance; } public RequestQueue getRequestQueue() { if (requestQueue == null) { // 此时ctx已被构造方法初始化,可安全调用 requestQueue = Volley.newRequestQueue(ctx); } return requestQueue; } public <T> void addToRequestQueue(Request<T> request) { getRequestQueue().add(request); } }
2. 优化Push_Notification_All类的上下文使用
- 移除多余的
final Context context = this;,直接使用Activity本身的上下文 - 初始化Dialog时传入
Push_Notification_All.this:
// 替换原loading初始化代码 loading = new Dialog(Push_Notification_All.this);
额外提示
- 不建议在客户端直接调用FCM API并存储Server Key,存在被反编译泄露的安全风险,推荐使用Firebase Admin SDK在服务端实现推送逻辑
- 确保项目已正确添加Volley依赖,否则会引发其他运行时异常
内容的提问来源于stack exchange,提问作者Azmat Ali
相关产品推荐
相关产品推荐

