/** * Synchronizes the UART configurations between handheld and wearables. * Call this when configuration has been created or altered. * @return pending result */ public PendingResult<DataApi.DataItemResult> onConfigurationAddedOrEdited(final long id, final UartConfiguration configuration) { if (mGoogleApiClient == null || !mGoogleApiClient.isConnected()) return null; final PutDataMapRequest mapRequest = PutDataMapRequest.create(Constants.UART.CONFIGURATIONS + "/" + id); final DataMap map = mapRequest.getDataMap(); map.putString(Constants.UART.Configuration.NAME, configuration.getName()); final ArrayList<DataMap> commands = new ArrayList<>(UartConfiguration.COMMANDS_COUNT); for (Command command : configuration.getCommands()) { if (command != null && command.isActive()) { final DataMap item = new DataMap(); item.putInt(Constants.UART.Configuration.Command.ICON_ID, command.getIconIndex()); item.putString(Constants.UART.Configuration.Command.MESSAGE, command.getCommand()); item.putInt(Constants.UART.Configuration.Command.EOL, command.getEolIndex()); commands.add(item); } } map.putDataMapArrayList(Constants.UART.Configuration.COMMANDS, commands); final PutDataRequest request = mapRequest.asPutDataRequest(); return Wearable.DataApi.putDataItem(mGoogleApiClient, request); }
public void displayLocationSettingsRequest(final Activity activity) { GoogleApiClient googleApiClient = new GoogleApiClient.Builder(activity) .addApi(LocationServices.API).build(); googleApiClient.connect(); LocationRequest locationRequest = LocationRequest.create(); locationRequest.setPriority(mAccuracy); locationRequest.setInterval(mInterval); locationRequest.setFastestInterval(mInterval / 2); LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest); builder.setAlwaysShow(false); final PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build()); result.setResultCallback(new LocationResultCallback(activity)); }
public void refreshPlacesData(){ Uri uri = PlacesContract.PlaceEntry.CONTENT_URI; Cursor dataCursor = getContentResolver().query(uri, null, null, null,null,null); if (dataCursor==null||dataCursor.getCount()==0) return; List<String> placeIds = new ArrayList<String>(); while (dataCursor.moveToNext()){ placeIds.add(dataCursor.getString(dataCursor.getColumnIndex(PlacesContract.PlaceEntry.COLUMN_PLACE_ID))); } PendingResult<PlaceBuffer> placeBufferPendingResult = Places.GeoDataApi.getPlaceById(mClient, placeIds.toArray(new String[placeIds.size()])); placeBufferPendingResult.setResultCallback(new ResultCallback<PlaceBuffer>() { @Override public void onResult(@NonNull PlaceBuffer places) { mAdapter.swapPlaces(places); mGeofencing.updateGeofencesList(places); if (mIsEnabled) mGeofencing.registerAllGeofences(); } }); }
private void updateWearWeather(int weather_id, double high_temp, double low_temp){ PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(WEATHER_PATH).setUrgent(); putDataMapRequest.getDataMap().putInt(WEATHER_ID, weather_id); Log.d(LOG_TAG, "value of weather put : "+weather_id); putDataMapRequest.getDataMap().putDouble(HIGH_TEMP, high_temp); putDataMapRequest.getDataMap().putDouble(LOW_TEMP, low_temp); PutDataRequest putDataRequest = putDataMapRequest.asPutDataRequest().setUrgent(); PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(mWearClient, putDataRequest); pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>() { @Override public void onResult(@NonNull DataApi.DataItemResult dataItemResult) { if (dataItemResult.getStatus().isSuccess()) { Log.d(LOG_TAG, "Data item set: " + dataItemResult.getDataItem().getUri()); } else { Log.d(LOG_TAG, "Error in sending data to watch"); } } }); }
private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) { if (mGoogleApiClient.isConnected()) { PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi .getAutocompletePredictions(mGoogleApiClient, constraint.toString(), mBounds, mPlaceFilter); AutocompletePredictionBuffer autocompletePredictions = results .await(60, TimeUnit.SECONDS); final Status status = autocompletePredictions.getStatus(); if (!status.isSuccess()) { Toast.makeText(getContext(), "Error contacting API: " + status.toString(), Toast.LENGTH_SHORT).show(); autocompletePredictions.release(); return null; } return DataBufferUtils.freezeAndClose(autocompletePredictions); } return null; }
public Observable<PlacePrediction> getAutocompleteResults(final GoogleApiClient mGoogleApiClient, final String query, final LatLngBounds bounds) { return Observable.create(new Observable.OnSubscribe<PlacePrediction>() { @Override public void call(Subscriber<? super PlacePrediction> subscriber) { PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, query, bounds, null); AutocompletePredictionBuffer autocompletePredictions = results .await(60, TimeUnit.SECONDS); final Status status = autocompletePredictions.getStatus(); if (!status.isSuccess()) { autocompletePredictions.release(); subscriber.onError(null); } else { for (AutocompletePrediction autocompletePrediction : autocompletePredictions) { subscriber.onNext( new PlacePrediction( autocompletePrediction.getPlaceId(), autocompletePrediction.getDescription() )); } autocompletePredictions.release(); subscriber.onCompleted(); } } }); }
@Override public FREObject call( FREContext context, FREObject[] args ) { super.call( context, args ); AIR.log( "GameServices::revealAchievement" ); String achievementId = FREObjectUtils.getString( args[0] ); boolean immediate = FREObjectUtils.getBoolean( args[1] ); GameServicesHelper helper = GameServicesHelper.getInstance(); if( helper.isAuthenticated() ) { if( immediate ) { PendingResult<Achievements.UpdateAchievementResult> result = Games.Achievements.revealImmediate( helper.getClient(), achievementId ); result.setResultCallback( this, 10, TimeUnit.SECONDS ); return null; } Games.Achievements.reveal( helper.getClient(), achievementId ); AIR.log( "Successfully revealed achievement: " + achievementId ); AIR.dispatchEvent( GameServicesEvent.ACHIEVEMENT_UPDATE_SUCCESS ); } else { helper.dispatchAchievementUpdateError(); } return null; }
private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) { if (mGoogleApiClient.isConnected()) { PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, constraint.toString(), mBounds, mPlaceFilter); AutocompletePredictionBuffer autocompletePredictions = results.await(60, TimeUnit.SECONDS); final Status status = autocompletePredictions.getStatus(); if (!status.isSuccess()) { Toast.makeText(getContext(), "Error contacting API: " + status.toString(), Toast.LENGTH_SHORT).show(); autocompletePredictions.release(); return null; } return DataBufferUtils.freezeAndClose(autocompletePredictions); } return null; }
@Override public PendingResult<DeleteSnapshotResult> delete(GoogleApiClient googleApiClient, final SnapshotMetadata snapshotMetadata) { if (!isAlreadyOpen(snapshotMetadata.getUniqueName()) && !isAlreadyClosing(snapshotMetadata.getUniqueName())) { setIsClosing(snapshotMetadata.getUniqueName()); try { return new CoordinatedPendingResult<>( Games.Snapshots.delete(googleApiClient, snapshotMetadata), new ResultListener() { @Override public void onResult(Result result) { // deleted files are closed. setClosed(snapshotMetadata.getUniqueName()); } }); } catch (RuntimeException e) { setClosed(snapshotMetadata.getUniqueName()); throw e; } } else { throw new IllegalStateException(snapshotMetadata.getUniqueName() + " is either open or is busy"); } }
private void callPlaceDetectionApi() throws SecurityException { PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi .getCurrentPlace(mGoogleApiClient, null); result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() { @Override public void onResult(PlaceLikelihoodBuffer likelyPlaces) { for (PlaceLikelihood placeLikelihood : likelyPlaces) { Log.i(LOG_TAG, String.format("Place '%s' with " + "likelihood: %g", placeLikelihood.getPlace().getName(), placeLikelihood.getLikelihood())); } likelyPlaces.release(); } }); }
@SuppressWarnings({"MissingPermission"}) public void startLocationUpdates(GoogleApiClient googleApiClient) { // particular case:hace un requestLocationSettings y casi al mismo tiempo stop(), // ,se recibe settingsResult:SUCCESS y luego hace startLocationUpdates y como // no está conectado da error if (!googleApiClient.isConnected()) { return; } PendingResult<Status> result = LocationServices.FusedLocationApi.requestLocationUpdates( googleApiClient, mLocationRequest, this); result.setResultCallback(new ResultCallback<Status>() { @Override public void onResult(@NonNull Status status) { if (!status.isSuccess()) { Utils.logD(LOG_TAG, String.format("requestLocationUpdates returned an error:code:%s ," + "message: %s", status.getStatusCode(), status.getStatusMessage())); getActivity().finish(); } } }, 2, TimeUnit.SECONDS); }
@SuppressLint("LongLogTag") private void findAllWearDevices() { Log.d(TAG, "findAllWearDevices()"); PendingResult<NodeApi.GetConnectedNodesResult> pendingResult = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient); pendingResult.setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() { @Override public void onResult(@NonNull NodeApi.GetConnectedNodesResult getConnectedNodesResult) { if (getConnectedNodesResult.getStatus().isSuccess()) { mAllConnectedNodes = getConnectedNodesResult.getNodes(); verifyNodeAndUpdateUI(); Log.e("Connected Nodes", "->"+mAllConnectedNodes.toString()); findWearDevicesWithApp(); } else { Log.d(TAG, "Failed NodeApi: " + getConnectedNodesResult.getStatus()); } } }); }
@Override public void onConnected(Bundle bundle) { //inicializa list view adapter=new ArrayAdapter<Location>(this, android.R.layout.simple_list_item_1, data); setListAdapter(adapter); //define requisicao para obter localizacao //objeto define quantos updates serao necessarios //deadline para desistir se nao conseguir obter location //intervalo //otimizacao de energia, caso aplicavel locationRequest = new LocationRequest() .setNumUpdates(5) .setExpirationDuration(60000) .setInterval(1000) .setPriority(LocationRequest.PRIORITY_LOW_POWER); LocationSettingsRequest.Builder b = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest); PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(playServices, b.build()); result.setResultCallback(this); }
private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) { if (mGoogleApiClient.isConnected()) { PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi .getAutocompletePredictions(mGoogleApiClient, constraint.toString(), mBounds, mPlaceFilter); AutocompletePredictionBuffer autocompletePredictions = results .await(60, TimeUnit.SECONDS); final Status status = autocompletePredictions.getStatus(); if (!status.isSuccess()) { if (callback != null) callback.onSuggestFail(status); autocompletePredictions.release(); return null; } return DataBufferUtils.freezeAndClose(autocompletePredictions); } return null; }
private void callPlaceDetectionApi() throws SecurityException { PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi .getCurrentPlace(mGoogleApiClient, null); result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() { @Override public void onResult(PlaceLikelihoodBuffer likelyPlaces) { for (PlaceLikelihood placeLikelihood : likelyPlaces) { Log.i(LOG_TAG, String.format("Place '%s' with " + "likelihood: %g", placeLikelihood.getPlace().getName(), placeLikelihood.getLikelihood())); display.setText(placeLikelihood.getPlace().getAddress().toString()); messageSending(placeLikelihood.getPlace().getAddress().toString()); break; } likelyPlaces.release(); } }); }
private void checkIfPhoneHasApp() { Log.d(TAG, "checkIfPhoneHasApp()"); PendingResult<CapabilityApi.GetCapabilityResult> pendingResult = Wearable.CapabilityApi.getCapability( mGoogleApiClient, CAPABILITY_PHONE_APP, CapabilityApi.FILTER_ALL); pendingResult.setResultCallback(new ResultCallback<CapabilityApi.GetCapabilityResult>() { @Override public void onResult(@NonNull CapabilityApi.GetCapabilityResult getCapabilityResult) { Log.d(TAG, "onResult(): " + getCapabilityResult); if (getCapabilityResult.getStatus().isSuccess()) { CapabilityInfo capabilityInfo = getCapabilityResult.getCapability(); mAndroidPhoneNodeWithApp = pickBestNodeId(capabilityInfo.getNodes()); verifyNodeAndUpdateUI(); } else { Log.d(TAG, "Failed CapabilityApi: " + getCapabilityResult.getStatus()); } } }); }
void getCurrentPlace() throws SecurityException { PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi.getCurrentPlace(placeApiClient, null); result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() { @Override public void onResult(PlaceLikelihoodBuffer likelyPlaces) { for (int i = 0; i < likelyPlaces.getCount() && i < 5; i++) { PlaceEntry place = new PlaceEntry(); if (likelyPlaces.get(i).getLikelihood() == 0) continue; place.setName(likelyPlaces.get(i).getPlace().getName().toString()); place.setLatLon(likelyPlaces.get(i).getPlace().getLatLng()); myDataset.add(place); mAdapter.notifyItemInserted(myDataset.size() - 1); } getMapA(); likelyPlaces.release(); } }); }
@Override protected void onConnected() { PendingResult<Status> pendingResult = null; String actionStr = null; if (mAction == SUBSCRIBE) { pendingResult = Nearby.Messages.subscribe( getGoogleApiClient(), createNearbySubscribeIntent(), createSubscribeOptions()); actionStr = "background subscribe"; } else { pendingResult = Nearby.Messages.unsubscribe( getGoogleApiClient(), createNearbySubscribeIntent()); actionStr = "background unsubscribe"; } pendingResult.setResultCallback(new SimpleResultCallback(actionStr) { @Override public void onResult(final Status status) { super.onResult(status); disconnect(); if (mCallback != null) { mCallback.run(); } } }); }
@Override public FREObject call( FREContext context, FREObject[] args ) { super.call( context, args ); AIR.log( "GameServices::unlockAchievement" ); String achievementId = FREObjectUtils.getString( args[0] ); boolean immediate = FREObjectUtils.getBoolean( args[1] ); GameServicesHelper helper = GameServicesHelper.getInstance(); if( helper.isAuthenticated() ) { if( immediate ) { PendingResult<Achievements.UpdateAchievementResult> result = Games.Achievements.unlockImmediate( helper.getClient(), achievementId ); result.setResultCallback( this, 10, TimeUnit.SECONDS ); return null; } Games.Achievements.unlock( helper.getClient(), achievementId ); AIR.log( "Successfully unlocked achievement: " + achievementId ); AIR.dispatchEvent( GameServicesEvent.ACHIEVEMENT_UPDATE_SUCCESS ); } else { helper.dispatchAchievementUpdateError(); } return null; }
private void configureLocationConnection() { LocationRequest locationRequest = createLocationRequest(); LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest); PendingResult<LocationSettingsResult> locationSettingsResultPendingResult = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build()); locationSettingsResultPendingResult .setResultCallback(new ResultCallback<LocationSettingsResult>() { @Override public void onResult(LocationSettingsResult result) { if (LocationSettingsStatusCodes.SUCCESS != result.getStatus().getStatusCode()) { Intent localIntent = new Intent(Constants.GOOGLE_API).putExtra(Constants.GOOGLE_API_LOCATION_RESULT, result.getStatus()); LocalBroadcastManager.getInstance(ParcoursService.this).sendBroadcast(localIntent); } } }); // noinspection MissingPermission : permissions dans le manifest LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this); }
/** * This method read the UART configurations from the DataApi and populates the adapter with them. */ private void populateConfigurations() { if (mGoogleApiClient.isConnected()) { final PendingResult<DataItemBuffer> results = Wearable.DataApi.getDataItems(mGoogleApiClient, Uri.parse("wear:" + Constants.UART.CONFIGURATIONS), DataApi.FILTER_PREFIX); results.setResultCallback(new ResultCallback<DataItemBuffer>() { @Override public void onResult(final DataItemBuffer dataItems) { final List<UartConfiguration> configurations = new ArrayList<>(dataItems.getCount()); for (int i = 0; i < dataItems.getCount(); ++i) { final DataItem item = dataItems.get(i); final long id = ContentUris.parseId(item.getUri()); final DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap(); final UartConfiguration configuration = new UartConfiguration(dataMap, id); configurations.add(configuration); } mAdapter.setConfigurations(configurations); dataItems.release(); } }); } }
/** * GoogleApiClient interfaces */ @Override public void onConnected(@Nullable Bundle bundle) { final LocationRequest locationRequest = LocationRequest.create() .setPriority(LocationRequest.PRIORITY_LOW_POWER); final LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest) .setNeedBle(true); final PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build()); result.setResultCallback(new ResultCallback<LocationSettingsResult>() { @Override public void onResult(@NonNull LocationSettingsResult locationSettingsResult) { final Status status = locationSettingsResult.getStatus(); if (status.getStatusCode() == LocationSettingsStatusCodes.RESOLUTION_REQUIRED) { try { status.startResolutionForResult(getCurrentActivity(), NEAR_LOCATION_SETTINGS_CODE); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); } } } }); }
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { AnalyticsManager.getInstance().trackSearch(); final AutocompletePrediction item = mAdapter.getItem(position); final String placeId = item.getPlaceId(); final CharSequence primaryText = item.getPrimaryText(null); PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi .getPlaceById(mGoogleApiClient, placeId); placeResult.setResultCallback(mUpdatePlaceDetailsCallback); }
protected final <T extends Result> void setupLocationPendingResult(PendingResult<T> pendingResult, ResultCallback<T> resultCallback) { if (timeoutTime != null && timeoutUnit != null) { pendingResult.setResultCallback(resultCallback, timeoutTime, timeoutUnit); } else { pendingResult.setResultCallback(resultCallback); } }
/** * Blocking wait for the given file to be closed. Returns immediately if the * file is not open. * * @param filename - the file name in question. */ public PendingResult<Result> waitForClosed(String filename) { CountDownLatch l; synchronized (this) { l = opened.get(filename); } return new CountDownPendingResult(l); }
@Override public PendingResult<OpenSnapshotResult> resolveConflict(GoogleApiClient googleApiClient, String conflictId, String snapshotId, SnapshotMetadataChange snapshotMetadataChange, SnapshotContents snapshotContents) { // Since the unique name of the snapshot is unknown, this resolution method cannot be safely // used. Please use another method of resolution. throw new IllegalStateException("resolving conflicts with ids is not supported."); }
@Override public PendingResult<OpenSnapshotResult> open(GoogleApiClient googleApiClient, final String filename, boolean createIfNotFound, int conflictPolicy) { // check if the file is already open if (!isAlreadyOpen(filename)) { setIsOpening(filename); try { return new CoordinatedPendingResult<>( Games.Snapshots.open(googleApiClient, filename, createIfNotFound, conflictPolicy), new ResultListener() { @Override public void onResult(Result result) { // if open failed, set the file to closed, otherwise, keep it open. if (!result.getStatus().isSuccess()) { Log.d(TAG, "Open was not a success: " + result.getStatus() + " for filename " + filename); setClosed(filename); } else { Log.d(TAG, "Open successful: " + filename); } } }); } catch (RuntimeException e) { setClosed(filename); throw e; } } else { throw new IllegalStateException(filename + " is already open"); } }
@Override public PendingResult<OpenSnapshotResult> resolveConflict(GoogleApiClient googleApiClient, String conflictId, final Snapshot snapshot) { if (!isAlreadyOpen(snapshot.getMetadata().getUniqueName()) && !isAlreadyClosing(snapshot.getMetadata().getUniqueName())) { setIsOpening(snapshot.getMetadata().getUniqueName()); try { return new CoordinatedPendingResult<>( Games.Snapshots.resolveConflict(googleApiClient, conflictId, snapshot), new ResultListener() { @Override public void onResult(Result result) { if (!result.getStatus().isSuccess()) { setClosed(snapshot.getMetadata().getUniqueName()); } } }); } catch (RuntimeException e) { setClosed(snapshot.getMetadata().getUniqueName()); throw e; } } else { throw new IllegalStateException(snapshot.getMetadata().getUniqueName() + " is already open or is busy"); } }
@Override public PendingResult<OpenSnapshotResult> open(GoogleApiClient googleApiClient, final SnapshotMetadata snapshotMetadata, int conflictPolicy) { // check if the file is already open if (!isAlreadyOpen(snapshotMetadata.getUniqueName())) { setIsOpening(snapshotMetadata.getUniqueName()); try { return new CoordinatedPendingResult<>(Games.Snapshots.open( googleApiClient, snapshotMetadata, conflictPolicy), new ResultListener() { @Override public void onResult(Result result) { // if open failed, set the file to closed, otherwise, keep it open. if (!result.getStatus().isSuccess()) { Log.d(TAG, "Open was not a success: " + result.getStatus() + " for filename " + snapshotMetadata.getUniqueName()); setClosed(snapshotMetadata.getUniqueName()); } else { Log.d(TAG, "Open was successful: " + snapshotMetadata.getUniqueName()); } } }); } catch (RuntimeException e) { setClosed(snapshotMetadata.getUniqueName()); throw e; } } else { throw new IllegalStateException(snapshotMetadata.getUniqueName() + " is already open"); } }
/** * Method to call API for each user input * @param constraint User input character string * @return ArrayList containing suggestion results */ private ArrayList<PlaceAutoComplete> getAutoComplete(CharSequence constraint){ if(mGoogleApiClient.isConnected()){ //Making a query and fetching result in a pendingResult PendingResult<AutocompletePredictionBuffer> results= Places.GeoDataApi .getAutocompletePredictions(mGoogleApiClient,constraint.toString(),mBounds,mPlaceFilter); //Block and wait for 60s for a result AutocompletePredictionBuffer autocompletePredictions=results.await(60, TimeUnit.SECONDS); final Status status=autocompletePredictions.getStatus(); // Confirm that the query completed successfully, otherwise return null if(!status.isSuccess()){ Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString()); autocompletePredictions.release(); return null; } Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount() + " predictions."); // Copy the results into our own data structure, because we can't hold onto the buffer. // AutocompletePrediction objects encapsulate the API response (place ID and description). Iterator<AutocompletePrediction> iterator=autocompletePredictions.iterator(); ArrayList resultList=new ArrayList<>(autocompletePredictions.getCount()); while(iterator.hasNext()){ AutocompletePrediction prediction=iterator.next(); resultList.add(new PlaceAutoComplete(prediction.getPlaceId(),prediction.getPrimaryText(null),prediction.getSecondaryText(null))); } autocompletePredictions.release(); return resultList; }else{ Log.e(TAG,"GoogleApiClient Not Connected"); return null; } }