2016-03-30 60 views
-1

我試圖將Google任務與我的應用程序同步。爲此我創建了一個名爲GTaskSyncer的類,我創建了獲取任務細節的方法。在服務對象上獲得空指針異常

我想從UI調用這些方法。現在爲了測試,我創建了一個擴展AsyncTask的類,我在這裏調用了方法doInbackground

這是我在主要活動中調用的。

現在我在服務對象GTaskSyncer上得到空指針異常。

主要活動

public class MainActivity extends AppCompatActivity { 
    GoogleAccountCredential mCredential; 
    private TextView mOutputText; 
    ProgressDialog mProgress; 

    static final int REQUEST_ACCOUNT_PICKER = 1000; 
    static final int REQUEST_AUTHORIZATION = 1001; 
    static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002; 
    private static final String PREF_ACCOUNT_NAME = "accountName"; 
    private static final String[] SCOPES = { TasksScopes.TASKS }; 
    public com.google.api.services.tasks.Tasks mService = null; 
    /** 
    * Create the main activity. 
    * @param savedInstanceState previously saved instance data. 
    */ 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     LinearLayout activityLayout = new LinearLayout(this); 
     LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
       LinearLayout.LayoutParams.MATCH_PARENT, 
       LinearLayout.LayoutParams.MATCH_PARENT); 
     activityLayout.setLayoutParams(lp); 
     activityLayout.setOrientation(LinearLayout.VERTICAL); 
     activityLayout.setPadding(16, 16, 16, 16); 

     ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT); 

     mOutputText = new TextView(this); 
     mOutputText.setLayoutParams(tlp); 
     mOutputText.setPadding(16, 16, 16, 16); 
     mOutputText.setVerticalScrollBarEnabled(true); 
     mOutputText.setMovementMethod(new ScrollingMovementMethod()); 
     activityLayout.addView(mOutputText); 

     mProgress = new ProgressDialog(this); 
     mProgress.setMessage("Calling Google Tasks API ..."); 

     Button sync = new Button(this); 

     sync.setText("Sync"); 

     setContentView(activityLayout); 

     // Initialize credentials and service object. 
     SharedPreferences settings = getPreferences(Context.MODE_PRIVATE); 
     mCredential = GoogleAccountCredential.usingOAuth2(
       getApplicationContext(), Arrays.asList(SCOPES)) 
       .setBackOff(new ExponentialBackOff()) 
       .setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null)); 

     HttpTransport transport = AndroidHttp.newCompatibleTransport(); 
     JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); 
     mService = new com.google.api.services.tasks.Tasks.Builder(
       transport, jsonFactory, mCredential) 
       .setApplicationName("Google Tasks API Android Quickstart") 
       .build(); 
    } 


    /** 
    * Called whenever this activity is pushed to the foreground, such as after 
    * a call to onCreate(). 
    */ 
    @Override 
    protected void onResume() { 
     super.onResume(); 
     if (isGooglePlayServicesAvailable()) { 
      refreshResults(); 
     } else { 
      mOutputText.setText("Google Play Services required: " + 
        "after installing, close and relaunch this app."); 
     } 
    } 

    /** 
    * Called when an activity launched here (specifically, AccountPicker 
    * and authorization) exits, giving you the requestCode you started it with, 
    * the resultCode it returned, and any additional data from it. 
    * @param requestCode code indicating which activity result is incoming. 
    * @param resultCode code indicating the result of the incoming 
    *  activity result. 
    * @param data Intent (containing result data) returned by incoming 
    *  activity result. 
    */ 
    @Override 
    protected void onActivityResult(
      int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 
     switch(requestCode) { 
      case REQUEST_GOOGLE_PLAY_SERVICES: 
       if (resultCode != RESULT_OK) { 
        isGooglePlayServicesAvailable(); 
       } 
       break; 
      case REQUEST_ACCOUNT_PICKER: 
       if (resultCode == RESULT_OK && data != null && 
         data.getExtras() != null) { 
        String accountName = 
          data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); 
        if (accountName != null) { 
         mCredential.setSelectedAccountName(accountName); 
         SharedPreferences settings = 
           getPreferences(Context.MODE_PRIVATE); 
         SharedPreferences.Editor editor = settings.edit(); 
         editor.putString(PREF_ACCOUNT_NAME, accountName); 
         editor.apply(); 
        } 
       } else if (resultCode == RESULT_CANCELED) { 
        mOutputText.setText("Account unspecified."); 
       } 
       break; 
      case REQUEST_AUTHORIZATION: 
       if (resultCode != RESULT_OK) { 
        chooseAccount(); 
       } 
       break; 
     } 

     super.onActivityResult(requestCode, resultCode, data); 
    } 

    /** 
    * Attempt to get a set of data from the Google Tasks API to display. If the 
    * email address isn't known yet, then call chooseAccount() method so the 
    * user can pick an account. 
    */ 
    private void refreshResults() { 
     if (mCredential.getSelectedAccountName() == null) { 
      chooseAccount(); 
     } else { 
      if (isDeviceOnline()) { 
       new TestAsyncTask(mCredential).execute(); 
      } else { 
       mOutputText.setText("No network connection available."); 
      } 
     } 
    } 
    /** 
    * Starts an activity in Google Play Services so the user can pick an 
    * account. 
    */ 
    private void chooseAccount() { 
     startActivityForResult(
       mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); 
    } 

    /** 
    * Checks whether the device currently has a network connection. 
    * @return true if the device has a network connection, false otherwise. 
    */ 
    private boolean isDeviceOnline() { 
     ConnectivityManager connMgr = 
       (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 
     NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); 
     return (networkInfo != null && networkInfo.isConnected()); 
    } 

    /** 
    * Check that Google Play services APK is installed and up to date. Will 
    * launch an error dialog for the user to update Google Play Services if 
    * possible. 
    * @return true if Google Play Services is available and up to 
    *  date on this device; false otherwise. 
    */ 
    private boolean isGooglePlayServicesAvailable() { 
     final int connectionStatusCode = 
       GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); 
     if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) { 
      showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode); 
      return false; 
     } else if (connectionStatusCode != ConnectionResult.SUCCESS) { 
      return false; 
     } 
     return true; 
    } 

    /** 
    * Display an error dialog showing that Google Play Services is missing 
    * or out of date. 
    * @param connectionStatusCode code describing the presence (or lack of) 
    *  Google Play Services on this device. 
    */ 
    void showGooglePlayServicesAvailabilityErrorDialog(
      final int connectionStatusCode) { 
     Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
       connectionStatusCode, 
       MainActivity.this, 
       REQUEST_GOOGLE_PLAY_SERVICES); 
     dialog.show(); 
    } 

} 

TestAsyncTask

public class TestAsyncTask extends AsyncTask<Void, Void, List<TaskList>>{ 

    private com.google.api.services.tasks.Tasks mService = null; 
    private Exception mLastError = null; 
    private MainActivity activity; 
    private com.google.api.services.tasks.Tasks client = null; 

    public TestAsyncTask(GoogleAccountCredential credential) { 
     HttpTransport transport = AndroidHttp.newCompatibleTransport(); 
     JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); 
     mService = new com.google.api.services.tasks.Tasks.Builder(
       transport, jsonFactory, credential) 
       .setApplicationName("Google Tasks API Android Quickstart") 
       .build(); 

    } 
    protected List<TaskList> doInBackground(Void... params) { 

     GTaskSyncer gTaskSyncer = new GTaskSyncer(activity); 

     List<TaskList> result = new ArrayList<>(); 

     try { 

      result = gTaskSyncer.getAllTaskList(); 

     } catch (IOException e) { 

      Toast.makeText(activity,"IO Exception",Toast.LENGTH_SHORT).show(); 
     } 
     return result; 
    } 
} 

GTaskSyncer

public class GTaskSyncer 
{ 

    final MainActivity activity; 
    final com.google.api.services.tasks.Tasks mService; 


    GTaskSyncer(MainActivity activity) { 
     this.activity = activity; 
     mService = activity.mService; 
    } 

    public List<TaskList> getAllTaskList() throws IOException 
    { 
     List<TaskList> result = new ArrayList<TaskList>(); 

     TaskLists taskLists = mService.tasklists().list().execute(); 

     for (TaskList taskList : taskLists.getItems()) { 

       result.add(taskList); 
     } 

     return result; 

    } 


    public TaskList createList() throws IOException 
    { 

     TaskList taskList = new TaskList(); 

     taskList = activity.mService.tasklists().insert(taskList).execute(); 

     return taskList; 
    } 

    public Task createTask(String listId) throws IOException 
    { 

     Task task = new Task(); 

     task = activity.mService.tasks().insert(listId, task).execute(); 

     return task; 
    } 

    public Task getTask(String listId,String taskId) throws IOException 
    { 

     Task task = activity.mService.tasks().get(listId, taskId).execute(); 

     return task; 
    } 

    public List<Task> getTaskList(String listId) throws IOException 
    { 
     List<Task> result = new ArrayList<Task>(); 

     List<Task> tasks = mService.tasks().list(listId).execute().getItems(); 

     if (tasks != null) { 

      for (Task task : tasks) { 

       result.add(task); 
      } 
     } else { 

      Toast.makeText(activity,"No tasks.",Toast.LENGTH_SHORT).show(); 
     } 

     return result; 
    } 

} 

請幫助..

+0

請出示您的日誌輸出。跟蹤這個問題可能會有用。 –

+1

可能重複[什麼是空指針異常,以及如何解決它?](http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do -i-fix-it) – beresfordt

回答

1

你還沒有初始化這個private MainActivity activity;而且您正在使用它來創建的GTaskSyncer

GTaskSyncer gTaskSyncer = new GTaskSyncer(activity); 

因此,這裏正在傳遞的實例:

GTaskSyncer(MainActivity activity) { 
    this.activity = activity; // null 
    mService = activity.mService; // exception 
} 

最後,你正在使用它在很多地方,這是造成exception

taskList = activity.mService.tasklists().insert(taskList).execute(); 

試圖改變構造:

public TestAsyncTask(GoogleAccountCredential credential, MainActivity activity) { 
    HttpTransport transport = AndroidHttp.newCompatibleTransport(); 
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); 
    mService = new com.google.api.services.tasks.Tasks.Builder(
      transport, jsonFactory, credential) 
      .setApplicationName("Google Tasks API Android Quickstart") 
      .build(); 
    this.activity = activity; 
} 

,並調用它是這樣的:

new TestAsyncTask(mCredential, MainActivity.this).execute(); 
+0

謝謝..它解決了null異常。但我沒有得到任何任務列表。你能幫忙嗎? – user5881997

+0

@ user5881997,如果它解決了空指針異常,你可以請[接受和upvote](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)我的答案。 –

+0

你可以更新代碼來獲取任務列表嗎? –

0

其更好地改變你的構造

GTaskSyncer(MainActivity activity,com.google.api.services.tasks.Tasks mService) { 
     this.activity = activity; 
     this.mService = mService; 
}