2013-05-03 7 views
0

사용자 위치를 수시로 (예 : 20 초마다) 추적하고 매분마다 해당 위치를 웹 서비스에 전송하는 앱을 개발 중입니다. 이를 위해 필자는 각 작업이 AlarmManagers/BroadcastReceivers가 시작한 안드로이드 서비스 인 제작자 소비자 구조를 만들었습니다. 또한이 애플리케이션은 Phonegap 및 JQuery Mobile으로 개발 된 UI를 사용하여 보조 작업을 수행하고 일부 데이터 (예 : 사용자 이름)를 서비스에 전송합니다. 이 문제는 네트워크 통신을 담당하는 서비스가 getInputStream() 메소드에 걸려서 Android Not Responding 대화 상자를 throw 할 때 발생합니다. 오랜 작업은 UI 스레드로 수행되어서는 안된다는 것을 알고 있지만, 내 접근 방식, 단서를 고려할 때이 문제를 해결하는 방법을 모르겠습니다.Android가 응답하지 않음

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
      package="com.android.fcl" 
      android:versionCode="1" 
       android:versionName="1.0" > 

<uses-sdk 
    android:minSdkVersion="8" 
    android:targetSdkVersion="17" /> 

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 
<uses-permission android:name="android.permission.BATTERY_STATS" /> 
<uses-permission android:name="android.permission.CAMERA" /> 
<uses-permission android:name="android.permission.FLASHLIGHT" /> 
<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
<uses-permission android:name="android.permission.VIBRATE" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
<uses-permission android:name="android.permission.WAKE_LOCK" /> 

<application 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme" 
    android:configChanges="orientation|keyboardHidden" 
    android:allowBackup="false"> 
    <activity 
     android:name="com.android.fcl.MainActivity" 
     android:label="@string/app_name" 
     android:screenOrientation="portrait"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 
      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
    <service 
     android:name="com.android.fcl.GPSLoggerService" 
     android:label="@string/gps_logger_service"> 
    </service> 
    <service 
     android:name="com.android.fcl.GPSHttpService" 
     android:label="@string/gps_http_service"> 
    </service> 
    <receiver android:name="com.android.fcl.GPSLoggerReceiver" /> 
    <receiver android:name="com.android.fcl.GPSHttpReceiver" /> 
</application> 

</manifest> 

자바 스크립트 : 아래

내 응용 프로그램 매니페스트 일부 코드

function goToPage() { 
    window.ServiceControl.startService(); 
    $.mobile.changePage('address.html', {transition: 'flip'}); 
    $.mobile.hidePageLoadingMsg(); 
} 

활동 :

public class MainActivity extends DroidGap { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     super.init(); 

     if (android.os.Build.VERSION.SDK_INT > 9) { 
      StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
      StrictMode.setThreadPolicy(policy); 
     } 

     ServiceControl service = ServiceControl.getInstance(); 
     service.setActivity(this); 
     service.setView(appView); 
     appView.addJavascriptInterface(service, "ServiceControl"); 

     ServiceStorage serviceStorage = ServiceStorage.getInstance(); 
     serviceStorage.createDatabase(this); 
     super.loadUrl("file:///android_asset/www/login.html"); 
    }  
} 

ServiceControl.java :

public class ServiceControl { 

    private AlarmManager gpsAlarmManager; 
    private PendingIntent gpsPendingIntent; 
    private AlarmManager httpAlarmManager; 
    private PendingIntent httpPendingIntent; 

    public void startService() { 
     if (this.activity != null) { 
      Intent gpsIntent = new Intent(this.activity, GPSLoggerReceiver.class); 
      Intent httpIntent = new Intent(this.activity, GPSHttpReceiver.class); 
      if (this.gpsAlarmManager == null) { 
       gpsAlarmManager = (AlarmManager) activity.getSystemService(Service.ALARM_SERVICE); 
       gpsPendingIntent = PendingIntent.getBroadcast(activity, 0, gpsIntent, 0); 
       gpsAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), GPS_MIN_TIME, gpsPendingIntent); 
      } 
      if (this.httpAlarmManager == null) { 
       httpAlarmManager = (AlarmManager) activity.getSystemService(Service.ALARM_SERVICE); 
       httpPendingIntent = PendingIntent.getBroadcast(activity, 0, httpIntent, 0); 
       httpAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), HTTP_MIN_TIME, httpPendingIntent); 
      } 
    } 
} 

브로드 캐스트 리시버 :

public class GPSHttpReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     Intent service = new Intent(context, GPSHttpService.class); 
     context.startService(service); 
    } 
} 

서비스 : 작업이 상대적으로 독립적 보인다

public class GPSHttpService extends Service { 

    private PowerManager pm = null; 
    private PowerManager.WakeLock wl = null; 

    private HttpURLConnection httpConnection = null; 

    private synchronized void setWakeLock() { 
     ServiceControl serviceControl = ServiceControl.getInstance(); 
     DroidGap activity = serviceControl.getActivity(); 
     pm = (PowerManager) activity.getSystemService(Context.POWER_SERVICE); 
     wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 
     wl.acquire(); 
    } 

    private String sendPostMessage(String message) { 
     byte [] buffer = null; 
     String response = null; 
    URL url = null; 
     DataOutputStream outputStream = null; 
     InputStreamReader inputStream = null; 

     buffer = message.getBytes(); 
     try { 
      url = new URL(URI); 
      httpConnection = (HttpURLConnection) url.openConnection(); 
      httpConnection.setDoOutput(true); 
      httpConnection.setDoInput(true); 
      httpConnection.setInstanceFollowRedirects(false); 
      httpConnection.setRequestMethod(FCLString.POST_REQUEST_METHOD); 
      httpConnection.setRequestProperty(FCLString.CONTENT_TYPE_PROPERTY, FCLString.CONTENT_TYPE_APP_JSON); 
      httpConnection.setRequestProperty(FCLString.CHARSET_PROPERTY, FCLString.UTF8_FORMAT); 
      httpConnection.setConnectTimeout(CONN_TIMEOUT); 
      httpConnection.setRequestProperty(FCLString.CONTENT_LENGTH_PROPERTY, String.valueOf(buffer.length)); 
      httpConnection.setUseCaches(false); 
      outputStream = new DataOutputStream(httpConnection.getOutputStream()); 
      outputStream.write(buffer); 
      outputStream.flush(); 
      outputStream.close(); 
      inputStream = new InputStreamReader(httpConnection.getInputStream()); 
      response = GPSMessage.readResponseStream(inputStream); 
     } catch (MalformedURLException e) { 
      Log.d(TAG, FCLString.MALFORMED_URL); 
     } catch (IOException e) { 
      Log.d(TAG, FCLString.IO_EXCEPTION); 
      Log.d(TAG, e.getMessage()); 
     } finally { 
      if (httpConnection != null) { 
       httpConnection.disconnect(); 
      } 
     } 
     return response; 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     ServiceStorage serviceStorage = ServiceStorage.getInstance(); 
     JSONObject json= null; 
     String message = null; 
     String response = null; 
     boolean status = false; 

     super.onStartCommand(intent, flags, startId); 
    setWakeLock(); 
     json = serviceStorage.getRecords(); 
     if ((json != null) && (json.length() > 0)) { 
      message = GPSMessage.prepareMessage(json); 
      if (message != null) { 
       if (hasInternetConnection()) { 
        response = sendPostMessage(message); 
        status = GPSMessage.evaluateResponse(response); 
        if (status) { 
         serviceStorage.removeRecords(json); 
        } 
       } 
      } 
     } 
     this.stopSelf(); 
     return Service.START_NOT_STICKY; 
    } 
} 

답변

0

당신은 IntentService를 사용하는 대신에 단지 일반 Service 고려할 수 있습니다. 그러면 별도의 스레드에서 작업을 처리하게됩니다. 안드로이드 서비스에 reference doc에서

+0

감사합니다. @kabuko. –

3

:

주 그들의 호스팅 프로세스의 주요 스레드에서 실행되는 다른 응용 프로그램 객체 등의 서비스. 즉, 서비스가 인 경우 (예 : MP3 재생) 또는 CPU 집약적 인 작업 (예 : MP3 재생) 또는 차단 (네트워킹과 같은 ) 작업 인 경우 에 해당 스레드를 생성해야합니다. 자세한 내용은 Processes and Threads에서 확인할 수 있습니다. IntentService 클래스는 수행 할 작업이 인 자체 스레드가있는 표준 구현 서비스로 사용할 수 있습니다.

+0

감사합니다 @ 산타, 나는 변화를 만들었고 이제 앱이 잘 작동하는 것처럼 보입니다! –