2012-08-12 3 views
6

인터넷에 동기화해야하는 Android 앱이 있지만 잠자기 상태가되면 인터넷에 접속할 수 없습니다. 그것은 사용자가 15 분 후에 데이터를 끌 때 "배터리 모드"를 사용할 때만 발생합니다. 테스트 애플리케이션을 작성하고 데이터를 켜기는했지만 여전히 서버에 연결됩니다.잠자기시 Android에서 인터넷 켜기

내가 뭘하려 :

  • 내가 수동으로 해제 데이터를 설정 한 후 앱을 켭하고 그것이 내가 또한 가동 잠금을 시도했지만 도움이되지 않았다
  • 작동합니다.
  • 경보는 전화가 모토로라 ATRIX 안드로이드 2.3.3에서 테스트 시간

위해 절전 모드로 전환하는 경우에도, 예상대로 작동합니다. 나는 와이파이에 의지 할 수 없다. 실생활에서는 매주 동기화됩니다. 어떻게하면 가능합니까?

알람 관리기 :

alarm_manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE); 
Intent intent = new Intent(this, AlarmReceiver.class); 
PendingIntent pending = PendingIntent.getBroadcast(this, 0, intent, 
         PendingIntent.FLAG_UPDATE_CURRENT); 
alarm_manager.setRepeating(AlarmManager.RTC_WAKEUP, 
         System.currentTimeMillis(), 15000, pending); 

AlarmReceiver :

public class AlarmReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     Log.d("MYTAG", "RECEIVED getMobileDataEnabled: " + getMobileDataEnabled(context)); 
     if (!isOnline(context)) { 
      Log.d("MYTAG", "NO INET"); 
      if (turnOnInet(context)) { 
       Log.d("MYTAG", "INET IS ON"); 
      } 
     } 

     HttpClient httpclient = new DefaultHttpClient(); 
     HttpPost httppost = new HttpPost("http://xxx.xxx.xxx.xxx/ping/pong/moto/"); 
      try { 
       List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); 
       nameValuePairs.add(new BasicNameValuePair("short_code", "ROFL")); 
       httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
       httpclient.execute(httppost); 
       Log.d("MYTAG", "POST FINISHED"); 
      } 
      catch (Exception e) { 
       Log.e("MYTAG", "MYTAG", e); 
      } 
    } 

    public boolean isOnline(Context context) { 
     ConnectivityManager cm = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); 
     NetworkInfo netInfo = cm.getActiveNetworkInfo(); 
     if (netInfo != null){ 
      Log.d("MYTAG", "isAvailable: "+netInfo.isAvailable()); 
     } 
     if (netInfo != null && netInfo.isConnectedOrConnecting()) { 
      return true; 
     } 
     return false; 
    } 

    public boolean turnOnInet(Context context) { 
     ConnectivityManager mgr = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); 
     if (mgr == null) { 
      Log.d("MYTAG", "ConnectivityManager == NULL"); 
      return false; 
     } 
     try { 
      Method setMobileDataEnabledMethod = mgr.getClass().getDeclaredMethod("setMobileDataEnabled", boolean.class); 
      if (null == setMobileDataEnabledMethod) { 
       Log.d("MYTAG", "setMobileDataEnabledMethod == null"); 
       return false; 
      }  
      setMobileDataEnabledMethod.invoke(mgr, true); 
     } 
     catch(Exception e) { 
      Log.e("MYTAG", "MYTAG", e); 
      return false; 
     } 
     return true; 
    } 


    private boolean getMobileDataEnabled(Context context) { 
     ConnectivityManager mgr = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); 
     if (mgr == null) { 
      Log.d("MYTAG", "getMobileDataEnabled ConnectivityManager == null"); 
      return false; 
     } 
     try { 
      Method method = mgr.getClass().getMethod("getMobileDataEnabled"); 
      return (Boolean) method.invoke(mgr); 
     } catch (Exception e) { 
      Log.e("MYTAG", "MYTAG", e); 
      return false; 
     } 
    } 
} 

의 AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> 
+4

사용자의 배터리를 지우지 마십시오. – SLaks

+0

"실제 생활"에서는 매주 – programmersbook

+0

번에 RTC_WAKEUP 대신 RTC 플래그를 사용해 보셨습니까? 웨이크 업이 강제되지 않기 때문에 프레임 워크가 네트워크에서 전환 될 수 있습니다. 일주일에 한 번 동기화를 사용하고 있기 때문에 WAKEUP 플래그가 필요하지 않습니다. – nandeesh

답변

5

나는 sugges을 거라고 조금 접근 방식을 바꾸는 것은 전혀 나쁘지 않습니다. 사용자가 항상 결정할 기회를 제공하지 않는다는 유일한 문제와 함께 항상 동기화되는지 확인하는 것이 좋습니다. , 내 데이터를 끄기로 결정했다. 나는 아무에게도 그것을 켜지 않기를 바란다. 몇 가지 이유가있을 수 있으며, 그 중 하나만 있으면 충분하지만 해외에서 나가서 국제 데이터 플랜이 없다고 말하면 우연히 또는 기본값으로 데이터 로밍이 활성화됩니다. 일부 특정 앱이 내 데이터를 켜고 민감한 금액을 보냈다면 꽤 화가 났을 것입니다.

접근과 직선 솔루션보다 적절한뿐만 아니라 사용자가 응용 프로그램을 열거 나 어떤 쉬운 조건에 따라 일부 와이파이 연결 (ConnectivityManager is your friend)에 대한 액세스 (마지막 시간이있을 때마다 수시로 하드/전체 동기화를 할 것 일주일 이상 동기화, 오래된 저장된 데이터, 불일치 등)를 기록하고 나머지 경우에는 부드러운 동기화 (백그라운드에서 데이터 업데이트)를 수행하십시오.

주기적으로 동기화한다는 것은 사용자가 앱을 사용하지 않을 경우 사용자 데이터를 낭비한다는 의미입니다. 궁극적으로 이것은 앱을 매번 시스템에 의해 종료 될 수있는 완벽한 후보로 만듭니다.

희망이 있습니다. 귀하의 발전과 함께 우리를 업데이 트하십시오.

관련 읽기 : Optimizing downloads for efficient network access

+0

좋은 지적. 또한 네트워크를 사용하는 최적화 된 응용 프로그램 작성에 대한 기사를 살펴보십시오. 네트워크 전송을 그룹화하고 여러 연결을 처리하는 방법이 있습니다. https://developer.att.com/developer/forward.jsp?passedItemId=7200042 –

15

첫째, 당신은 얻을 필요가 있다는 BroadcastReceiver 중과 IntentServiceHttpPost 코드입니다. 안 함 기본 응용 프로그램 스레드에서 네트워크 입출력을 수행하고 onReceive()이 주 응용 프로그램 스레드에서 호출됩니다. 예를 들어, 너무 오래 걸리면 Android가 인터넷 작업을 통해 코드를 중간에 종료합니다.

두 번째로 IntentService이 주어지면 WakeLock을 사용해야합니다. 그러면 두 가지 문제를 모두 처리하는 my WakefulIntentService을 사용할 수 있습니다. 또는 같은 용도의 WakefulBroadcastReceiver을 사용하십시오.

세 번째로 turnOnInet()getMobileDataEnabled()을 삭제하십시오. 당신은 그 (것)들을 필요로하지 않으며, 신뢰할 수 없으며, 특히 turnOnInet()은 사용자 적대적이다. - 사용자가 모바일 데이터를 켜기를 원한다면, 그들은 켜져있을 것이다.

, 당신은 바로 인터넷에 연결되어 있지 않은 경우 이제 임시 해결 방법, 두 번째에 대한 SystemClock.sleep()으로, 당신의 IntentService()onHandleIntent() (또는 WakefulIntentService 당신의 doWakefulWork()) 당신에, 그 모두를 제공하고 다시 시도 루프에서 몇 번 반복합니다. 조금 후에 인터넷에 액세스하는 것을 발견하면 (예 : 연결 변경 브로드 캐스트를 폴링이 아닌 수신 대기로 변경하면 WakefulIntentService에서 벗어나 자신의 백그라운드 스레드로 일반 Service으로 이동할 수 있습니다. 그리고 WakeLock 관리를위한 상태 머신). 또는 sleep()을 계속 사용하십시오. 몇 초 동안이 배경 스레드를 묶어두면 세상의 종말이 아닐 수도 있습니다. 적절한 시간이 지난 후에도 연결이 끊어지지 않으면 Android 4.0 이상에서 사용자 중심의 대역폭 관리를 포함하여 연결되지 않을 수도있는 여러 가지 이유가 있으므로 계속 무기한 사용하지 마십시오.

+0

저는 몇 주 동안 고생했습니다. 'WakefulIntentService'를 제대로 사용하지 않는 이유는 수면에 여러 번 시도해도 깊은 잠에서 깨어 났을 때 인터넷에 백그라운드 서비스를 제공하지 않는 이유입니다. 나는 알람 관리자와 함께 서비스를 예약하고 있으며, 실제로 서비스가 시작될 때마다 서비스를 시작하는 브로드 캐스트 일정을 잡아야한다는 것을 알고 있지만, 장치가 인터넷에 연결되어 있지는 않습니다 (Google에 pinging) . 나는 정말 실망 스럽다. –

+1

@CordRehn : 도즈 모드. 또는 장치에 모바일 데이터가없는 경우 Wi-Fi 연결을 설정하는 데 시간이 걸립니다. – CommonsWare

+0

시간을내어 주셔서 감사합니다. 이제 Doze 모드를 연구하겠습니다. 나는 10 초의 타임 아웃과 3 초의 간격으로 성공적으로 ping google로 3 분을 보내고 관대했다. 나는 그 해결책이 단지 "기다려라"고 생각하지 않는다. –

1

정확한 대답은 아니지만이 방법은 배터리 수명을 완전히 망칠 것입니다. 수면의 모든 포인트는 배터리 전원을 절약하는 것입니다.이 앱은 기능이 얼마나 유용 하든지 상관없이 고객에게 짜증나게 할뿐입니다.

내가 권하고 싶은 것은 앱이 사용되지 않는 동안 절대적으로 인터넷에 연결해야한다는 것입니다. 전화가 들릴 때 트리거를 설정하십시오. 앱이 완전히 필요하지 않은 경우 앱을 열 때마다 인터넷에 다시 연결하는 것이 가장 좋습니다.

관련 문제