旧Android版本中registerReceiver与WifiManager相关报错求助
Hi there, let's walk through troubleshooting that registerReceiver error you're facing with your old Android SMS/WiFi service. Based on your setup, here are the most likely causes and fixes tailored to your scenario:
1. Context Lifecycle Mismatch
Your IncomingSms class is a BroadcastReceiver, and the Context passed to onReceive() is a temporary, restricted instance (ReceiverRestrictedContext). If you’re using this short-lived context to register a dynamic receiver, the system will throw errors once the BroadcastReceiver finishes executing and the context is recycled.
Fix: Always use the application context for long-lived operations like registering receivers. Replace any references to recContext with:
Context appContext = context.getApplicationContext();
2. Permission & Manifest Issues
Old Android systems enforce strict permissions for WiFi operations and broadcast registration. Make sure your AndroidManifest.xml includes all required permissions:
<!-- Basic WiFi access permissions --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- For Android 6.0+, WiFi scans require location permissions --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- If targeting older versions, add this for broadcast access --> <uses-permission android:name="android.permission.RECEIVE_SMS" />
Also, ensure you’ve declared your BroadcastReceiver in the manifest:
<receiver android:name=".IncomingSms"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver>
3. BroadcastReceiver Limitations
BroadcastReceivers are designed for short, immediate tasks (max 10 seconds execution time). Registering another dynamic receiver inside onReceive() is risky—your parent receiver may be destroyed before the new one can function, leading to registration failures or memory leaks.
Fix: Move your WiFi scanning logic to a Foreground Service instead. Services have stable lifecycles and are better suited for ongoing operations like WiFi monitoring:
- When your
IncomingSmsdetects the trigger SMS, start a foreground service. - Handle WiFi scanning, registration of the WiFi result receiver, and sending the response SMS from within the service.
- Example service skeleton:
public class WifiScanService extends Service { private WifiManager wifiManager; private BroadcastReceiver wifiScanReceiver; @Override public void onCreate() { super.onCreate(); // Start foreground to avoid being killed (critical for old Android) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel("wifi_scan", "WiFi Scan Service", NotificationManager.IMPORTANCE_LOW); getSystemService(NotificationManager.class).createNotificationChannel(channel); Notification notification = new Notification.Builder(this, "wifi_scan") .setContentTitle("Scanning WiFi") .setSmallIcon(R.drawable.ic_wifi) .build(); startForeground(1, notification); } // Initialize WiFi manager and scan receiver wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); wifiScanReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) { List<ScanResult> results = wifiManager.getScanResults(); // Call your SendLoc logic here to send WiFi info via SMS sendWifiResultsAsSms(results); // Cleanup: unregister receiver and stop service unregisterReceiver(this); stopSelf(); } } }; registerReceiver(wifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); wifiManager.startScan(); } private void sendWifiResultsAsSms(List<ScanResult> results) { // Implement your SMS sending logic here (replace your SendLoc method) } @Override public void onDestroy() { super.onDestroy(); // Ensure receiver is unregistered to prevent leaks if (wifiScanReceiver != null) { try { unregisterReceiver(wifiScanReceiver); } catch (IllegalArgumentException e) { // Ignore if already unregistered } } } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
4. Unhandled Registration/Unregistration
If you do register a receiver dynamically (even in a service), always pair it with a corresponding unregisterReceiver() call in the component’s onDestroy() method. Failing to do so will cause memory leaks and system errors.
Final Check
For very old Android versions (pre-3.1), ensure your app has been launched at least once—system broadcasts won’t be delivered to apps that have never been opened.
内容的提问来源于stack exchange,提问作者Franktonosan Nadal

