Как сохранить прослушивание websockets в качестве фоновой службы?

У меня есть служба для обработки моих событий websocket, однако он перестает слушать, когда пользовательский интерфейс закрыт — однако, я все еще могу выдавать сообщения (например. данные о местоположении.) Как сохранить websockets работает в фоновом режиме, чтобы он будет прослушивать события при загрузке или при закрытии основного потока пользовательского интерфейса?

public class HomeActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {
    public static final String TAG = HomeActivity.class.getSimpleName();
    public static final String PREFS_NAME = "MyPrefsFile";
    String userName = "init";
    String token = "init";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        WifiInfo wInfo = wifiManager.getConnectionInfo();
        String macAddress = wInfo.getMacAddress();
        TextView textView = (TextView) findViewById(R.id.txtMac);
        textView.setText(macAddress);

        startService(new Intent(getBaseContext(), wsService.class));

        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        userName = settings.getString("username","does not exist");
        token = settings.getString("token","does not exist");
        textView = (TextView) findViewById(R.id.txtEmail);
        textView.setText(userName);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setTitle("Beacon");

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }


    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.home, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        } else if (id == R.id.nav_logout) {
            Log.i(TAG, "<<<<---- LOGOUT ---->>> ");
            Intent i = new Intent(getApplicationContext(), HomeActivity.class);
            startActivity(i);
        }


        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

Это сервис, запускаемый из действия выше:

public class wsService extends Service implements OnPreparedListener {
    public static final String PREFS_NAME = "MyPrefsFile";
    double longitude = 0;
    double latitude = 0;
    long time = 0;
    float speed = 0;
    float accuracy = 0;
    float bearing = 0;
    boolean sound_stopped = true;
    String userName = "init";
    String token = "init";
    public static final String TAG = wsService.class.getSimpleName();
    private LocationRequest mLocationRequest;
    MediaPlayer mp;

    /** indicates how to behave if the service is killed */
    int mStartMode;

    /** interface for clients that bind */
    IBinder mBinder;

    /** indicates whether onRebind should be used */
    boolean mAllowRebind;
    private Socket mSocket;
    {
        try {
            mSocket = IO.socket("http://192.168.0.2:5000");
        } catch (URISyntaxException e) {}

    }

    /** Called when the service is being created. */
    @Override
    public void onCreate() {
        Log.d(TAG, "-- Starting wsService --");
        new LongOperation().execute("test");
        mp = MediaPlayer.create(this, R.raw.led);
        String locationProvider = LocationManager.NETWORK_PROVIDER;
        mLocationRequest = LocationRequest.create() // Create the LocationRequest object
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(10 * 1000)        // 10 seconds, in milliseconds
                .setFastestInterval(1 * 1000); // 1 second, in milliseconds
        // Acquire a reference to the system Location Manager
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);
    }

    private class LongOperation extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            Log.d(TAG, "-- Starting BACKGROUND wsService --");
            mSocket.connect();
            mSocket.on("to_mobile", onCommand);
            return "Executed";
        }

        @Override
        protected void onPostExecute(String result) {

        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }

    //Listening new message event to receive message
    private Emitter.Listener onCommand = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            JSONObject data = (JSONObject)args[0];
            String command = null;
            try {
                command = data.getString("command");
            } catch (JSONException e) {
                e.printStackTrace();
            }

            Log.i(TAG, "<<<<---- RECEIVING COMMAND ----->>> " + command);
            if (command.equals("ping_audio_start")) {
                start_sound();
            }
            if (command.equals("ping_audio_stop")) {
                stop_sound();
            }
            if (command.equals("ping_gps")) {
                Log.i(TAG, "<<<<---- RESPONDING GPS REQUEST ----->>> ");
                mSocket.emit("from_mobile", gps_string);
            }

        }
    };

    String gps_string = "HELLO FROM DROID";
    private void handleNewLocation(Location location) {
        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        WifiInfo wInfo = wifiManager.getConnectionInfo();
        String macAddress = wInfo.getMacAddress();
        longitude = location.getLongitude();
        latitude = location.getLatitude();
        time = location.getTime();
        speed = location.getSpeed();
        accuracy = location.getAccuracy();
        bearing = location.getBearing();
        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        userName = settings.getString("username","does not exist");
        token = settings.getString("token","does not exist");
        gps_string = "{ "mac":"" + macAddress
                + "", "userName":"" + userName
                + "", "token":"" + token
                + "", "time":"" + time
                + "", "longitude":"" + longitude
                + "", "latitude":"" + latitude
                + "", "speed":"" + speed
                + "", "accuracy":"" + accuracy
                + "", "bearing":"" + bearing
                + ""}";
        mSocket.emit("from_mobile", gps_string);
        Log.i(TAG, "<<<<---- SENDING GPS DATA ---->>> ");
    }

    // Define a listener that responds to location updates
    LocationListener locationListener = new LocationListener() {
        public void onLocationChanged(Location location) {
            handleNewLocation(location);
        }
        public void onStatusChanged(String provider, int status, Bundle extras) {}

        public void onProviderEnabled(String provider) {}

        public void onProviderDisabled(String provider) {}
    };

    public void start_sound() {
        Log.i(TAG, "<<<<---- START PING ----->>>");
        mp.release();
        mp = MediaPlayer.create(this, R.raw.led);
        mp.setLooping(true);
        mp.start();
        mp.setVolume(1, 1);
        sound_stopped = false;

    }
    public void stop_sound() {
        Log.i(TAG, "<<<<---- STOP PING ----->>> ");
        mp.stop();
        sound_stopped = true;
    }

    public void onPrepared(MediaPlayer player) {
        player.start();
    }
        /** The service is starting, due to a call to startService() */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return mStartMode;
    }

    /** A client is binding to the service with bindService() */
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /** Called when all clients have unbound with unbindService() */
    @Override
    public boolean onUnbind(Intent intent) {
        return mAllowRebind;
    }

    /** Called when a client is binding to the service with bindService()*/
    @Override
    public void onRebind(Intent intent) {

    }

    /** Called when The service is no longer used and is being destroyed */
    @Override
    public void onDestroy() {

    }
}

1 ответ

  1. IntentService работает только до тех пор, пока это необходимо для обработки намерения. i.e если для обработки не осталось никаких намерений, служба автоматически закрывается.

    Попробуйте обычный сервис.