Запуск службы на платформе Android

Я запускаю сервис, используя метод startService (намерение намерения) . Когда я вызываю эту функцию, он достигает функции onCreate, но не может вызвать onStartCommand . Вот мой код –

@Override public void onReceive(Context context, Intent intent) { // Send a text notification to the screen. Log.e("mudit", "Action: " + intent.getAction()); try { ConnectivityManager connManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = connManager.getActiveNetworkInfo(); Log.e("mudit", "getType: " + info.getType()); Log.e("mudit", "isConnected: " + info.isConnected()); if (info.isConnected()) { Intent newinIntent = new Intent(context, service.class); context.startService(newinIntent); } } catch (Exception e) { e.printStackTrace(); Intent newinIntent = new Intent(context, service.class); context.stopService(newinIntent); } } 

Код услуги –

 package com.android.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.widget.Toast; public class service extends Service { @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { super.onCreate(); Toast.makeText(this, "Service created...", Toast.LENGTH_LONG).show(); } @Override public void onDestroy() { super.onDestroy(); Toast.makeText(this, "Service destroyed ...", Toast.LENGTH_LONG).show(); } public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "onStartCommand...", Toast.LENGTH_LONG).show(); return 1; } } 

Manifest.xml –

 <receiver class=".AReceiver" android:name=".AReceiver"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver> <service class=".service" android:name=".service" android:enabled="true" android:icon="@drawable/icon"> </service> 

LarsVogel решает эту проблему (и многие другие, подобные ей) на этом превосходном посту .

Так я адаптировал его код для создания приемника подключения, который контролирует, когда пользователь подключается к сети WIFI, чтобы загружать данные об использовании:

В файле манифеста поместите приемник и объявите сервис прямо перед конечным тегом для вашего </ application>:

  <receiver android:name=".ConnMonitor" android:enabled="true"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver> <service android:name=".BatchUploadGpsData" ></service> </application> 

Создайте класс вещательного приемника в отдельном файле ConnMonitor.java (пожалуйста, раскомментируйте вызовы журнала, чтобы иметь возможность правильно отслеживать поток)

 import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.util.Log; public class ConnMonitor extends BroadcastReceiver { private String TAG = "TGtracker"; @Override public void onReceive(Context context, Intent intent) { //String typeName = ""; String state = ""; int type = -1; ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE ); NetworkInfo test = (NetworkInfo) connectivityManager.getActiveNetworkInfo(); //Log.v(TAG,"there has been a CONNECTION CHANGE -> "+intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO)); try { //typeName = test.getTypeName().toString(); type = test.getType(); state = test.getState().toString(); //Log.i(TAG,"type -> '"+typeName +"' state -> '"+state+"'" ); } catch (Exception e) { //typeName = "null"; type = -1; state = "DISCONNECTED"; //Log.i(TAG,"type -> error1 "+e.getMessage()+ " cause = "+e.getCause() ); } if ( (type == 1) && (state == "CONNECTED") ) { //Log.i(TAG, "I am soooo friggin uploadin on this beautiful WIFI connection "); Intent batchUploadDataService = new Intent(context, BatchUploadGpsData.class); context.startService(batchUploadDataService); } else { //Log.e(TAG,"NO FOUND MATCH type -> '"+typeName +"' state -> '"+state+"'" ); } } } 

И, наконец, создать службу BatchUploadGpsData.java следующим образом:

 import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class BatchUploadGpsData extends Service { final String TAG = "TGtracker"; @Override public void onCreate() { Log.e(TAG, "here i am, rockin like a hurricane. onCreate service"); // this service tries to upload and terminates itself whether it is successful or not // but it only effectively DOES anything while it is created // (therefore, you can call 1 million times if uploading isnt done, nothing happens) // if you comment this next line, you will be able to see that it executes onCreate only the first it is called // the reason i do this is that the broadcast receiver is called at least twice every time you have a new change of connectivity state with successful connection to wifi this.stopSelf(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //Log.i(TAG, "Received start id " + startId + ": " + intent); Log.e(TAG, "call me redundant BABY! onStartCommand service"); // this service is NOT supposed to execute anything when it is called // because it may be called inumerous times in repetition // all of its action is in the onCreate - so as to force it to happen ONLY once return 1; } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } } 

Это не псевдокод, это реальный код, протестированный и запущенный на Android 2.2 и выше.

Способ протестировать эту услугу – отключить и перезапустить службы WIFI на вашем Android-устройстве (выключение Wi-Fi-маршрутизатора также поможет вам). НО этот код не проверяет, действительно ли вы подключены к сети. Для этого я рекомендую вам сделать запрос httpclient и проверить результат вызова. Выходят за рамки этого обсуждения.

ПРИМЕЧАНИЕ. Поскольку службы работают в том же потоке, что и пользовательский интерфейс, я настоятельно рекомендую вам реализовать загрузку в отдельном потоке или асинтете, в зависимости от ваших конкретных потребностей. Вы также можете запустить весь сервис в отдельном потоке, но это еще раз не та область обсуждения, несмотря на стандартную практику в этих случаях.

  1. Unbound Service: он работает в фоновом режиме на неопределенный срок, даже начав работу с завершением службы.
  2. Связанная служба: она будет работать до времени жизни.

Активность может запускаться через startService() и она остановится через stopService() . Если активность хочет взаимодействовать с сервисом, она может использовать bindService() .

onCreate() после того, как onStartCommand вызывается с данными о намерениях, предоставляемыми этим действием.

Источник

Сначала вы должны добавить @Override перед onStartCommand(..) затем убедитесь, что цель для проекта Android выше 2.0 .

Я считаю, что вы не можете получить доступ к компонентам пользовательского интерфейса, таким как Dialog или даже Toast в службе.

попробуй это.

 public int onStartCommand(Intent intent, int flags, int startId) { /* Toast.makeText(this, "onStartCommand...", Toast.LENGTH_LONG).show(); return 1; */ Log.i("YourService", "Yes this works."); } 

Прежде всего, назовите свой класс кем-то другим, это моя рекомендация избегать путаницы по линии. Во-вторых, это пример моего явного вызова службы, которая у меня есть. Я использую полные имена путей при вызове служб и т. Д., Поскольку они не находятся в том же пакете, что и мое приложение.

 <service android:name="com.public.service.UploaderService" android:icon="@drawable/vgbio"></service> 

Вот суть моего класса обслуживания,

 package com.public.service; .... public class UploaderService extends Service{ .... } 

В третьих, убедитесь, что вы используете @Override для onStartCommand ().