2015-07-09 16 views
9

here è il codice fornito dalla guida ufficiale, mentre questo è uno snippet che causa problemi.Android: come risolvere la mancata connessione API di Google da un servizio?

@Override 
public void onConnectionFailed(ConnectionResult result) { 
    if (mResolvingError) { 
     // Already attempting to resolve an error. 
     return; 
    } else if (result.hasResolution()) { 
     try { 
      mResolvingError = true; 
      result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR); 
     } catch (IntentSender.SendIntentException e) { 
      // There was an error with the resolution intent. Try again. 
      mGoogleApiClient.connect(); 
     } 
    } else { 
     // Show dialog using GooglePlayServicesUtil.getErrorDialog() 
     mResolvingError = true; 
     GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, REQUEST_RESOLVE_ERROR) 
       .setOnDismissListener(new DialogInterface.OnDismissListener() { 
        @Override 
        public void onDismiss(DialogInterface dialog) { 
         mResolvingError = false; 
        } 
       }); 
    } 
} 

Se lo uso in un servizio, quando si legge la variabile this passato come argomento a queste funzioni, si aspettano un tipo di attività. Come devo fare? È un servizio.

Per lo stesso motivo non riesco a ottenere il risultato dell'attività

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
if (requestCode == REQUEST_RESOLVE_ERROR) { 
    mResolvingError = false; 
    if (resultCode == RESULT_OK) { 
     // Make sure the app is not already connected or attempting to connect 
     if (!mGoogleApiClient.isConnecting() && 
       !mGoogleApiClient.isConnected()) { 
      mGoogleApiClient.connect(); 
     } 
    } 
} 
} 
+0

quindi il tuo problema è ottenere un riferimento a un'attività? nella vita del servizio le attività sono anche vive? – Elltz

+0

Che tipo di servizio: avviato, vincolato, intento? –

+0

avviato mentre l'attività potrebbe essere in qualsiasi stato – user3290180

risposta

6

Questa risposta presuppone che il servizio è un servizio "ha iniziato". Se si tratta di un servizio vincolato o di un servizio intent, indicarlo in un commento e aggiornerò la descrizione e il codice inclusi qui.

La soluzione che suggerisco è di implementare l'attività mostrata di seguito per gestire l'interfaccia utente della risoluzione. Sostituire il metodo onConnectionFailed() nel vostro servizio con questo codice per mano dal trattamento risoluzione al ResolverActivity:

@Override 
public void onConnectionFailed(ConnectionResult result) { 
    Intent i = new Intent(this, ResolverActivity.class); 
    i.putExtra(ResolverActivity.CONNECT_RESULT_KEY, result); 
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    startActivity(i); 
} 

Aggiungere l'attività indicato di seguito per la vostra applicazione. Quando la richiesta di connessione nel servizio non riesce, il risultato della connessione, che è un Parcelable, viene passato all'attività. L'attività gestisce l'interfaccia utente della risoluzione e al termine restituisce lo stato al servizio come ulteriore extra. Dovrai modificare il codice nel tuo servizio onStartCommand() per esaminare gli extra nell'intento di determinare se è stato chiamato per avviare il servizio per la prima volta o per ricevere lo stato di risoluzione dallo ResolverActivity.

Un miglioramento di questo approccio sarebbe quello di inviare una notifica con un PendingIntent per ResolverActivity invece di avviare immediatamente l'attività. Ciò darebbe all'utente la possibilità di posticipare la risoluzione dell'errore di connessione.

public class ResolverActivity extends AppCompatActivity { 
    public static final String TAG = "ResolverActivity"; 

    public static final String CONNECT_RESULT_KEY = "connectResult"; 

    public static final String CONN_STATUS_KEY = "connectionStatus"; 
    public static final int CONN_SUCCESS = 1; 
    public static final int CONN_FAILED = 2; 
    public static final int CONN_CANCELLED = 3; 

    // Request code to use when launching the resolution activity 
    private static final int REQUEST_RESOLVE_ERROR = 1111; 

    private static final String ERROR_CODE_KEY = "errorCode"; 
    private static final String DIALOG_FRAG_TAG = "errorDialog"; 

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

     Log.i(TAG, "onCreate()"); 

     // No content needed. 
     //setContentView(R.layout.activity_main); 

     Intent i = getIntent(); 

     ConnectionResult result = i.getParcelableExtra(CONNECT_RESULT_KEY); 

     if (result.hasResolution()) { 
      try { 
       Log.i(TAG, "Starting error resolution..."); 
       result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR); 
      } catch (IntentSender.SendIntentException e) { 
       // There was an error with the resolution intent. 
       sendStatusToService(CONN_FAILED); 
       finish(); 
      } 
     } else { 
      // Show dialog using GooglePlayServicesUtil.getErrorDialog() 
      ErrorDialogFragment.newInstance(result.getErrorCode()) 
        .show(getSupportFragmentManager(), DIALOG_FRAG_TAG); 
     } 
    } 

    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent result) { 

     if (requestCode == REQUEST_RESOLVE_ERROR) { 
      if (resultCode == RESULT_OK) { 
       Log.i(TAG, "onActivityResult(): Connection problem resolved"); 
       sendStatusToService(CONN_SUCCESS); 
      } else { 
       sendStatusToService(CONN_CANCELLED); 
       Log.w(TAG, "onActivityResult(): Resolution cancelled"); 
      } 
      // Nothing more to do in this activity 
      finish(); 
     } 
    } 

    private void sendStatusToService(int status) { 
     Intent i = new Intent(this, MyGoogleApiService.class); 
     i.putExtra(CONN_STATUS_KEY, status); 
     startService(i); 
    } 

    // Fragment to display an error dialog 
    public static class ErrorDialogFragment extends DialogFragment { 

     public static ErrorDialogFragment newInstance(int errorCode) { 
      ErrorDialogFragment f = new ErrorDialogFragment(); 
      // Pass the error that should be displayed 
      Bundle args = new Bundle(); 
      args.putInt(ERROR_CODE_KEY, errorCode); 
      f.setArguments(args); 
      return f; 
     } 

     @Override 
     @NonNull 
     public Dialog onCreateDialog(Bundle savedInstanceState) { 
      // Get the error code and retrieve the appropriate dialog 
      int errorCode = getArguments().getInt(ERROR_CODE_KEY); 
      return GooglePlayServicesUtil.getErrorDialog(
        errorCode, getActivity(), REQUEST_RESOLVE_ERROR); 
     } 

     @Override 
     public void onDismiss(DialogInterface dialog) { 
      Log.i(TAG, "Dialog dismissed"); 
     } 
    } 
} 
+0

Funziona ma ho aggiunto mResolving boolean come dice la guida per evitare ripetizioni di errori mentre si risolvono i precedenti. – user3290180

+0

anche restituire FAILED nella finestra di dialogo respingere – user3290180

+0

onActivityResult restituire sempre il codice di richiesta errato nel mio caso puoi aiutare a questo proposito – ingsaurabh