Android跨应用通信:MainActivity变量在Service的onHandleIntent中为null的原因
Hey there! Let's break down why your res variable is null in ServiceV and how to fix that crash when communicating between App1 and App2.
Why is res null?
The core issue here is that MainActivity and IntentService are separate Android components with independent lifecycles. When you try to access a MainActivity variable directly from ServiceV, you're either referencing an outdated/destroyed instance of the Activity, or you never properly passed the instance to the Service. Android doesn't guarantee that your Activity will stay alive while the Service runs, so relying on direct references leads to null pointers.
Recommended Solutions
1. Pass Data Directly via Intent (Best Practice)
Instead of trying to access the Activity's variable from the Service, send the required data (res.getOtp()) as an extra in the Intent that starts ServiceV or triggers the cross-app broadcast. This is the standard Android way to communicate between components.
In App1's MainActivity:
// When preparing the Intent to send to ServiceV or App2 Intent intent = new Intent(this, ServiceV.class); // Pass the OTP value directly (assuming getOtp() returns a String) intent.putExtra("EXTRA_OTP", res.getOtp()); startService(intent); // Or sendBroadcast(intent) if communicating with App2
In App1's ServiceV onHandleIntent():
@Override protected void onHandleIntent(Intent intent) { if (intent != null) { // Retrieve the OTP from the Intent extras String otp = intent.getStringExtra("EXTRA_OTP"); if (otp != null) { // Use the OTP here to communicate with App2 // ... your existing logic ... } else { // Handle case where OTP wasn't passed } } }
2. Use a Custom Application Class for Shared Data
If res is an object you need to access across multiple components (not just this one Service), store it in a custom Application subclass. This keeps the object alive for the entire app lifecycle.
Step 1: Create a custom Application class
public class MyApp extends Application { private YourResClass res; public YourResClass getRes() { return res; } public void setRes(YourResClass res) { this.res = res; } }
Step 2: Register it in AndroidManifest.xml
<application android:name=".MyApp" <!-- rest of your application config --> >
Step 3: Set the value in MainActivity
// When you initialize 'res' in MainActivity ((MyApp) getApplication()).setRes(res);
Step 4: Retrieve it in ServiceV
@Override protected void onHandleIntent(Intent intent) { YourResClass res = ((MyApp) getApplicationContext()).getRes(); if (res != null) { String otp = res.getOtp(); // Proceed with your logic } else { // Handle null case (e.g., res wasn't initialized yet) } }
⚠️ Note: Make sure YourResClass doesn't hold a reference to MainActivity, otherwise you risk memory leaks.
3. Avoid Direct Activity References (Anti-Pattern)
Never hold a strong reference to an Activity in a Service. If you absolutely must interact with the Activity (not recommended for this use case), use a WeakReference to avoid memory leaks—but this still doesn't guarantee the Activity is alive when the Service runs. Stick to the first two solutions instead.
Final Tip
For cross-app communication, always pass the exact data you need via Intent extras instead of relying on shared objects. This makes your code more robust and aligns with Android's component design principles.
内容的提问来源于stack exchange,提问作者arnoldssss

