2010-05-05 13 views
46

मैं एक वेब सेवा चला रहा हूं जो उपयोगकर्ताओं को एक बड़े ऐप के हिस्से के रूप में अपनी यात्राएं (Google की MyTracks की तरह) रिकॉर्ड करने की अनुमति देता है। बात यह है कि जब कोई उपयोगकर्ता यात्रा शुरू करता है या इसे समाप्त करता है तो सर्वर को कॉर्ड और अन्य आइटम सहित डेटा पास करना आसान होता है। एक नौसिखिया होने के नाते, मुझे यकीन नहीं है कि एक पृष्ठभूमि सेवा कैसे स्थापित की जाए जो प्रत्येक (प्री-निर्धारित) अवधि (मिनट 3 मिनट, अधिकतम 1 घंटा) में स्थान अपडेट भेजता है जब तक कि उपयोगकर्ता यात्रा के अंत तक नहीं पहुंच जाता, या जब तक समय बीतने की पूर्व निर्धारित राशि।एंड्रॉइड: सर्वर पर समय-समय पर स्थान भेजने के लिए कैसे करें

एक बार फोन से यात्रा शुरू हो जाने के बाद, सर्वर अपडेट के बीच अंतराल के रूप में उपयोग करने के लिए मतदान अवधि के साथ जवाब देता है। यह हिस्सा काम करता है, जिसमें मैं फोन पर प्रतिक्रिया प्रदर्शित कर सकता हूं, और मेरा सर्वर उपयोगकर्ता की कार्रवाई को पंजीकृत करता है। इसी तरह, यात्रा निकट यात्रा अनुरोध पर सर्वर-साइड बंद है।

हालांकि, जब मैंने StartLocationUpdates (स्ट्रिंग प्रदाता, लंबे मिनट, फ्लोट मिनीडिस्टेंस, लोकेशन लिस्टर श्रोता) का उपयोग करते हुए स्टार्टट्रैक गतिविधि के अंदर से आवधिक ट्रैकिंग विधि शुरू करने का प्रयास किया, जहां मिनीटाइम सर्वर से मतदान अवधि है, तो यह अभी काम नहीं करता है , और मुझे कोई त्रुटि नहीं मिल रही है। तो इसका मतलब है कि मैं इस बिंदु पर अनजान हूं, पहले कभी एंड्रॉइड का इस्तेमाल नहीं किया था।

मैंने हैंडलर, लंबित इरादों और समान चीजों को करने के लिए अन्य चीजों के साथ पृष्ठभूमि सेवाओं का उपयोग करने पर यहां कई पोस्ट देखी हैं, लेकिन मुझे वास्तव में यह समझ में नहीं आता कि यह कैसे करना है। मैं चाहता हूं कि उपयोगकर्ता अपडेट पर चल रहे हों, जबकि फोन पर अन्य सामान करना चाहें, इसलिए यदि आप मुझे ट्यूटोरियल पर इंगित कर सकते हैं जो दिखाता है कि वास्तव में पृष्ठभूमि सेवाओं को कैसे लिखना है (शायद ये अलग वर्ग के रूप में चलते हैं?) या अन्य तरीकों के बारे में ऐसा करना, यह बहुत अच्छा होगा।

धन्यवाद!

उत्तर

15

आपको एक अलग वर्ग बनाने की आवश्यकता है जो Service वर्ग का उप-वर्ग है।

Service Documentation

आपका प्राथमिक आवेदन startService और stopService फोन पृष्ठभूमि प्रक्रिया शुरू कर सकते हैं करना चाहिए। थेरेस भी संदर्भ कक्षा में कुछ अन्य उपयोगी कॉल सेवा का प्रबंधन करने के:

Context Documentation

+0

धन्यवाद एक लाख। मैं सेवा बनाने, इसे शुरू करने और रोकने में सक्षम हूं। अब मुझे यह सुनिश्चित करना है कि सिस्टम इसे मार नहीं सकता है, और इसे आवश्यकतानुसार कहा जाता है। – Mark

+2

ध्यान रखें कि ओएस आपकी सेवा को समय-समय पर बंद कर देगा (और पुनरारंभ) क्योंकि यह उपयुक्त दिखता है: http://developer.android.com/reference/android/app/Service.html#Process लाइफसाइकिल – jscharf

+0

jscharf, मैं यह कैसे सुनिश्चित करूं सेवा को समय-समय पर कॉल करने की गारंटी दी जाती है, और तब तक तब तक चलती है जब तक कि उपयोगकर्ता कॉल को रोकने के लिए कोई विशेष कार्रवाई नहीं करता? मैं अलार्म का उपयोग करने और दस्तावेज़ों का उपयोग करने के तरीके पर जा रहा हूं ... – Mark

71

मैं हाल ही में इनमें से किसी एक में लिखा था और फैसला किया कि यह एक अच्छा विचार है एक पृष्ठभूमि सेवा चल रहा है छोड़ने के लिए नहीं है। यह शायद ऑपरेटिंग सिस्टम द्वारा बंद हो जाएगा, या यह हो सकता है। मैंने जो किया वह बूट उद्देश्य के लिए फ़िल्टर का उपयोग करता था और फिर अलार्म मैनेजर का उपयोग करके अलार्म सेट करता था ताकि मेरा ऐप नियमित अंतराल पर पुनरारंभ किया जा सके, और फिर उसने डेटा भेजा। आप एंड्रॉइड दस्तावेज में सेवाओं और अलार्म मैनेजर पर अच्छी जानकारी पा सकते हैं।

सबसे पहले मैंने एक प्रसारण रिसीवर बनाया जो इंटरनेट कनेक्शन खोले जाने पर बस मेरी सेवा शुरू करता है (मुझे केवल तभी दिलचस्पी है जब कोई कनेक्शन हो - आप बूट ईवेंट के लिए भी फ़िल्टर करना चाहेंगे)। लांच रिसीवर अल्पकालिक होना चाहिए, तो बस अपनी सेवा प्रारंभ:

public class LaunchReceiver extends BroadcastReceiver { 

    public static final String ACTION_PULSE_SERVER_ALARM = 
      "com.proofbydesign.homeboy.ACTION_PULSE_SERVER_ALARM"; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     AppGlobal.logDebug("OnReceive for " + intent.getAction()); 
     AppGlobal.logDebug(intent.getExtras().toString()); 
     Intent serviceIntent = new Intent(AppGlobal.getContext(), 
       MonitorService.class); 
     AppGlobal.getContext().startService(serviceIntent); 
    } 
} 

प्रकट मेरे पास में:

<receiver 
    android:name="LaunchReceiver" 
    android:label="@string/app_name" > 
    <intent-filter> 
     <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> 
    </intent-filter> 
    <intent-filter> 
     <action android:name="com.proofbydesign.homeboy.ACTION_PULSE_SERVER_ALARM" /> 
    </intent-filter> 
</receiver> 

सूचना कैसे मैं अपने ही अलार्म है, जो के लिए एक फिल्टर है क्या की अनुमति देता है मुझे सेवा बंद करने के लिए और इसे अपना काम पूरा करने के बाद इसे फिर से शुरू कर दिया है।

मेरा मॉनीटर सेवा के शीर्ष लगता है:

public class MonitorService extends Service { 

    private LoggerLoadTask mTask; 
    private String mPulseUrl; 
    private HomeBoySettings settings; 
    private DataFile dataFile; 
    private AlarmManager alarms; 
    private PendingIntent alarmIntent; 
    private ConnectivityManager cnnxManager; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     cnnxManager = (ConnectivityManager) 
       getSystemService(Context.CONNECTIVITY_SERVICE); 
     alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
     Intent intentOnAlarm = new Intent(
       LaunchReceiver.ACTION_PULSE_SERVER_ALARM); 
     alarmIntent = PendingIntent.getBroadcast(this, 0, intentOnAlarm, 0); 
    } 

    @Override 
    public void onStart(Intent intent, int startId) { 
     super.onStart(intent, startId); 
     // reload our data 
     if (mPulseUrl == null) { 
      mPulseUrl = getString(R.string.urlPulse); 
     } 
     AppGlobal.logDebug("Monitor service OnStart."); 
     executeLogger(); 
    } 

executeLogger एक asyncTask शुरू होता है, जो कि शायद मुझे जरूरत से ज्यादा सतर्क किया जा रहा है (यह केवल मेरे तीसरे Android एप्लिकेशन) था। asyncTask जीपीएस डेटा पकड़ लेता है, इंटरनेट को भेज देता है और अंत में अगले अलार्म सेट:

private void executeLogger() { 
    if (mTask != null 
     && mTask.getStatus() != LoggerLoadTask.Status.FINISHED) { 
     return; 
    } 
    mTask = (LoggerLoadTask) new LoggerLoadTask().execute(); 
} 

private class LoggerLoadTask extends AsyncTask<Void, Void, Void> { 

    // TODO: create two base service urls, one for debugging and one for live. 
    @Override 
    protected Void doInBackground(Void... arg0) { 
     try { 
      // if we have no data connection, no point in proceeding. 
      NetworkInfo ni = cnnxManager.getActiveNetworkInfo(); 
      if (ni == null || !ni.isAvailable() || !ni.isConnected()) { 
       AppGlobal 
         .logWarning("No usable network. Skipping pulse action."); 
       return null; 
      } 
      ///grab and log data 
     } catch (Exception e) { 
      AppGlobal.logError(
        "Unknown error in background pulse task. Error: '%s'.", 
        e, e.getMessage()); 
     } finally { 
      // always set the next wakeup alarm. 
      int interval; 
      if (settings == null 
       || settings.getPulseIntervalSeconds() == -1) { 
       interval = Integer 
         .parseInt(getString(R.string.pulseIntervalSeconds)); 
      } else { 
       interval = settings.getPulseIntervalSeconds(); 
      } 
      long timeToAlarm = SystemClock.elapsedRealtime() + interval 
       * 1000; 
      alarms.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToAlarm, 
        alarmIntent); 
     } 
     return null; 
    } 
} 

मुझे लगता है कि मैं stopSelf() कॉल नहीं कर रहा हूँ अलार्म सेट करने के बाद नोटिस, तो मेरी सेवा जब तक कुछ नहीं कर चारों ओर बैठेंगे ओप sys द्वारा बंद करो। चूंकि मैं इस ऐप का एकमात्र उपयोगकर्ता हूं, इससे कोई फर्क नहीं पड़ता, लेकिन सार्वजनिक ऐप के लिए, विचार यह है कि आप अगले अंतराल के लिए अलार्म सेट करते हैं, फिर बंद करने के लिए खुद को रोकें।

अद्यतन 'alarms.setRepeating()' का उपयोग करने के बारे में @juozas से टिप्पणी देखें।

+0

रॉब, धन्यवाद। अब मैं दस्तावेज खोज रहा हूं कि इरादे फ़िल्टर का उपयोग कैसे करें और समय-समय पर इसे चलाने के बजाए सेवा को समय-समय पर कॉल करने के लिए अलार्म सेट कैसे करें। – Mark

+0

मार्क, मैंने अपना कोड पोस्ट किया - उम्मीद है कि यह मदद करता है। –

+0

धन्यवाद फिर से रॉब। – Mark

2

मैं रोब केंट के साथ सहमत हैं, और अतिरिक्त में मैं beter हो सकता है आपके BroadcastReceiver में WakefulBroadcastReceiver प्रदान करता है और यह स्थिर विधि startWakefulService(android.content.Context context,android.content.Intent intent) है का उपयोग करें, क्योंकि यह garanted आपकी सेवा ओएस द्वारा बंद नहीं होगा करने के लिए लगता है।

public class YourReceiver extends WakefulBroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 

     Intent service = new Intent(context, YourService.class); 
     startWakefulService(context, service); 
    } 
} 

Official documentation

संबंधित मुद्दे