You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:14:56