5

나는 똑같은 문제에 직면/해결했다면 pls가 도움이된다는 사실을 발견했다.백그라운드 서비스에서 WiFi를 통해 인터넷에 접속할 수 없다.

사용자가 wakeful broadcast receiver에서 intent service의 도움으로 수동으로 끄기로 전환하지 않는 한 5 분마다 데이터를 서버로 보냅니다. 게다가 와이파이 잠금 장치를 사용하기 전에 잠금 장치를 사용하지 않고 시도했습니다.

정상적인 데이터 네트워크 (2G/3G/4G)에서 데이터를 전송하는 장치에서는 정상적으로 작동하지만 정상적으로 연결된 경우 와이파이 네트워크는 어떻게 든 null으로 getActiveNetworkInfo()을 가져옵니다 (웹 URL을 직접 누르더라도 hostname not found error이 나타납니다) 이것은 확실히 HTC One (v.4.4.2 설치)에서 발생합니다. 다른 장치는 제대로 작동합니다.

  • 우리는 이전 공식 연결성 관리자가 네트워크가 사용 가능하지 않더라도 너무 많은 참/거짓 조건을 반환하는 데 문제가 있음을 알고 있습니다. 그들이 다시 자르거나 그냥 맞춤형 OEM jing-bang인지 알 수 있습니다.

  • wakeful broadcast receiver >> get wifi locks >> sleep the thread for 3 secs inside the 수신을 시작한 후 수신을 시작한 후 Wi-Fi가 연결을 다시 시작할 때까지 기다립니다. >> 나중에 내 일을해라.

  • 무선 데이터 대신 강제로 모바일 데이터 연결을 사용할 가능성이 있습니다. (startUsingNetworkFeature()를 사용하여) 누구나 같은 솔루션을 가지고 있습니까?

답변

5

희망 너무 늦지 않으므로 너와 똑같은 문제가있다. 내 응용 프로그램은 내부 저장 파일에서 특정 간격 (30m/1h/2h/4h)으로 서버에 데이터를 전송해야했습니다. getActiveNetworkInfo()의 경우 적절한 결과를 얻으려면 wifi를 깨우지 않아야합니다 (5 ~ 15 분 후에 잠자기 wifi가 꺼지기 때문).

/** Receiver for keeping the device awake */ 
public class WakeUpReceiver extends WakefulBroadcastReceiver { 

    // Constant to distinguish request 
    public static final int WAKE_TYPE_UPLOAD = 2; 

    // AlarmManager to provide access to the system alarm services. 
    private static AlarmManager alarm; 
    // Pending intent that is triggered when the alarm fires. 
    private static PendingIntent pIntent; 

    /** BroadcastReceiver onReceive() method */ 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     // Start appropriate service type 
     int wakeType = intent.getExtras().getInt("wakeType"); 
     switch (wakeType) { 
     case WAKE_TYPE_UPLOAD: 
      Intent newUpload = new Intent(context, UploadService.class); 
      startWakefulService(context, newUpload); 
      break; 
     default: 
      break; 
     } 
    } 

    /** Sets alarms */ 
    @SuppressLint("NewApi") 
    public static void setAlarm(Context context, int wakeType, Calendar startTime) { 
     // Set alarm to start at given time 
     alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
     Intent intent = new Intent(context, WakeUpReceiver.class); 
     intent.putExtra("wakeType", wakeType); 
     pIntent = PendingIntent.getBroadcast(context, wakeType, intent, 
       PendingIntent.FLAG_UPDATE_CURRENT); 
     // For android 4.4+ the method is different 
     if (android.os.Build.VERSION.SDK_INT >= 
       android.os.Build.VERSION_CODES.KITKAT) { 
      alarm.setExact(AlarmManager.RTC_WAKEUP, 
        startTime.getTimeInMillis() + 5000, pIntent); 
     } else { 
      alarm.set(AlarmManager.RTC_WAKEUP, 
        startTime.getTimeInMillis() + 5000, pIntent); 
     } 
     // The + 5000 is for adding symbolic 5 seconds to alarm start 
    } 
} 

는 참고 public static void setAlarm(Context, int, Calendar) 기능은, 내가 사용 : 내가 전화를 해제 할 필요가있을 때, 나는 호출되는 WakefulBroadcastReceiver

첫째, 그것은 나에게 문제를 많이했다, 그러나 여기 내 솔루션이 작동하는 방법 알람을 설정하는 기능 (기본 애플리케이션 참조).

: 알람이 설정 한 후 전화가 다시 서비스를 실행 재부팅 그래서 만약

/** Service for uploading data to server */ 
public class UploadService extends Service { 

    private static final String serverURI = "http://your.server.com/file_on_server.php"; 

    private Looper mServiceLooper; 
    private ServiceHandler mServiceHandler; 

    WifiLock wfl; 

    private Intent currentIntent; 

    private SharedPreferences sharedPrefs; 
    private int updateInterval; 
    private boolean continueService; 

    /** Service onCreate() method */ 
    @Override 
    public void onCreate() { 
     super.onCreate(); 

     // Initialize wifi lock 
     wfl = null; 

     // Initialize current Intent 
     currentIntent = null; 

     // Create separate HandlerThread 
     HandlerThread thread = new HandlerThread("SystemService", 
       Process.THREAD_PRIORITY_BACKGROUND); 
     thread.start(); 
     // Get the HandlerThread's Looper and use it for our Handler 
     mServiceLooper = thread.getLooper(); 
     mServiceHandler = new ServiceHandler(mServiceLooper); 

     // Get shared variables values if set 
     sharedPrefs = getSharedPreferences("serviceVars", MODE_PRIVATE); 
     updateInterval = sharedPrefs.getInt("sendInterval", 60); // in your case 5 
     continueService = sharedPrefs.getBoolean("bgServiceState", false); 
    } 

    /** Service onStartCommand() method */ 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     // If continuing, set new alarm 
     if (continueService) { 
      Calendar nextStart = Calendar.getInstance(); 
      nextStart.set(Calendar.SECOND, 0); 
      // Set alarm to fire after the interval time 
      nextStart.add(Calendar.MINUTE, updateInterval); 
      WakeUpReceiver.setAlarm(this, WakeUpReceiver.WAKE_TYPE_UPLOAD, 
        nextStart); 
     } 

     // Get current Intent and save it 
     currentIntent = intent; 

     // Acquire a wifi lock to ensure the upload process works 
     WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); 
     wfl = wm.createWifiLock(WifiManager.WIFI_MODE_FULL, "WifiLock"); 
     if (!wfl.isHeld()) { 
      wfl.acquire(); 
     } 

     // For each start request, send a message to start a job and give 
     // start ID so we know which request we're stopping when we finish 
     Message msg = mServiceHandler.obtainMessage(); 
     msg.arg1 = startId; 
     mServiceHandler.sendMessage(msg); 
     // If service gets killed, it will restart 
     return START_STICKY; 
    } 

    /** Handler that receives messages from the thread */ 
    private final class ServiceHandler extends Handler { 
     public ServiceHandler(Looper looper) { 
      super(looper); 
     } 

     /** Executes all service operations */ 
     @Override 
     public void handleMessage(Message msg) { 
      // First wait for 5 seconds 
      synchronized (this) { 
       try { 
        wait(5 * 1000); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
      // Start checking if internet is enabled 
      boolean hasInternet = false; 
      long endTime = System.currentTimeMillis() + 55 * 1000; 
      // Check every second (max 55) if connected 
      while (System.currentTimeMillis() < endTime) { 
       if (hasInternet(UploadService.this)) { 
        hasInternet = true; 
        break; 
       } 
       synchronized (this) { 
        try { 
         wait(1000); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
      // Connected to internet or 60 (5 + 55) seconds passed 
      if (hasInternet) { 
       // Connect to server 
       connectToServer(serverURI, fileName); 
      } else { 
       // Can't connect, send message or something 
      } 

      // Stop service 
      stopSelf(msg.arg1); 
     } 
    } 

    /** Checks if phone is connected to Internet */ 
    private boolean hasInternet(Context context) { 
     ConnectivityManager cm = (ConnectivityManager) context 
       .getSystemService(Context.CONNECTIVITY_SERVICE); 
     NetworkInfo ni = null; 
     if (cm != null) { 
      ni = cm.getActiveNetworkInfo(); 
     } 
     return ni != null && ni.getState() == NetworkInfo.State.CONNECTED; 
    } 

    /** Service onDestroy() method */ 
    @Override 
    public void onDestroy() { 
     // Release wifi lock 
     if (wfl != null) { 
      if (wfl.isHeld()) { 
       wfl.release(); 
      } 
     } 

     // Release wake lock provided by BroadcastReceiver. 
     WakeUpReceiver.completeWakefulIntent(currentIntent); 

     super.onDestroy(); 
    } 

    /** Performs server communication */ 
    private void connectToServer(String serverUri, String dataFileName) { 
     // this function does my network stuff 
    } 

    /** Service onBind() method - Not used */ 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 
} 

내가 또한, BOOTBroadcastReceiver 있습니다

다음으로, 서비스 자체는 Service, IntentService 아니다

:
/** Receiver for (re)starting alarms on device reboot operations */ 
public class BootReceiver extends BroadcastReceiver { 
    WakeUpReceiver alarm = new WakeUpReceiver(); 

    /** BroadcastReceiver onReceive() method */ 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { 
      WakeUpReceiver.setAlarm(context, WakeUpReceiver.WAKE_TYPE_UPLOAD, 
        Calendar.getInstance()); 
     } 
    } 
} 

마지막은 아니지만 적어도 주 Activity에, 나는 시작 수신기하여 서비스를 시작합니다 나는 서비스를 중지 할 때

// Start upload service now 
Calendar timeNow = Calendar.getInstance(); 
WakeUpReceiver.setAlarm(this, WakeUpReceiver.WAKE_TYPE_UPLOAD, timeNow); 

// Enable BootReceiver to (re)start alarm on device restart 
getPackageManager().setComponentEnabledSetting(
     new ComponentName(this, BootReceiver.class), 
     PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
     PackageManager.DONT_KILL_APP); 

는, 나는 너무 BOOT 수신기를 중지

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 
<uses-permission android:name="android.permission.WAKE_LOCK" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 
<uses-permission android:name="android.permission.INTERNET" /> 

<receiver 
    android:name=".BootReceiver" 
    android:enabled="false" > 
    <intent-filter> 
     <action android:name="android.intent.action.BOOT_COMPLETED" /> 
    </intent-filter> 
</receiver> 
<receiver android:name=".WakeUpReceiver" /> 

<service 
    android:name=".UploadService" 
    android:enabled="true" 
    android:label="ServerUpload" 
    android:launchMode="singleInstance" /> 

을 나는 생각 :

// Disable BootReceiver to (re)start alarm on device restart 
getPackageManager().setComponentEnabledSetting(
     new ComponentName(this, BootReceiver.class), 
     PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
     PackageManager.DONT_KILL_APP); 

또한, 명시 할 적절한 권한과 구성 요소를 추가하는 것을 잊지 마세요 이 모든 것을 다 커버했기 때문에 누군가가 문제를 해결할 수 있다면 기쁠 것입니다.

관련 문제