Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 谷歌日历Android API错误:null_Java_Android_Api_Calendar - Fatal编程技术网

Java 谷歌日历Android API错误:null

Java 谷歌日历Android API错误:null,java,android,api,calendar,Java,Android,Api,Calendar,今天,我想在我的Android应用程序中添加一些谷歌日历的东西,所以我基本上就是这么做的 最后,当我进入我的日历场景并点击按钮时,一切似乎都正常,需要获得许可和谷歌账号,但最终都失败了 我真的不知道这是从哪里来的:/ 以下是我的Calendar.java源代码: 包com.cmil3.ar.projetar; 导入com.google.android.gms.common.ConnectionResult; 导入com.google.android.gms.common.GoogleAppAva

今天,我想在我的Android应用程序中添加一些谷歌日历的东西,所以我基本上就是这么做的

最后,当我进入我的日历场景并点击按钮时,一切似乎都正常,需要获得许可和谷歌账号,但最终都失败了

我真的不知道这是从哪里来的:/

以下是我的Calendar.java源代码:

包com.cmil3.ar.projetar; 导入com.google.android.gms.common.ConnectionResult; 导入com.google.android.gms.common.GoogleAppAvailability; 导入com.google.api.client.extensions.android.http.AndroidHttp; 导入com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential; 导入com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException; 导入com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; 导入com.google.api.client.http.HttpTransport; 导入com.google.api.client.json.JsonFactory; 导入com.google.api.client.json.jackson2.JacksonFactory; 导入com.google.api.client.util.ExponentialBackOff; 导入com.google.api.services.calendar.CalendarScopes; 导入com.google.api.client.util.DateTime; 导入com.google.api.services.calendar.model.*; 导入android.Manifest; 导入android.accounts.AccountManager; 导入android.app.Activity; 导入android.app.Dialog; 导入android.app.ProgressDialog; 导入android.content.Context; 导入android.content.Intent; 导入android.content.SharedReferences; 导入android.net.ConnectivityManager; 导入android.net.NetworkInfo; 导入android.os.AsyncTask; 导入android.os.Bundle; 导入android.support.annotation.NonNull; 导入android.text.TextUtils; 导入android.text.method.ScrollingMovementMethod; 导入android.view.view; 导入android.view.ViewGroup; 导入android.widget.Button; 导入android.widget.LinearLayout; 导入android.widget.TextView; 导入java.io.IOException; 导入java.util.ArrayList; 导入java.util.array; 导入java.util.List; 授予的进口pub.devrel.easypermissions.aftermissions; 导入pub.devrel.easypermissions.easypermissions; 公课日历扩展活动 实现EasyPermissions.PermissionCallbacks{ 谷歌会计凭证; 私有文本视图mOutputText; 专用按钮mcalapibutton; 进步; 静态最终整数请求\帐户\选择器=1000; 静态最终int请求_授权=1001; 静态最终整数请求\谷歌\播放\服务=1002; 静态最终整数请求\权限\获取\帐户=1003; 私有静态最终字符串按钮\u TEXT=调用谷歌日历API; 私有静态最终字符串PREF\u ACCOUNT\u NAME=accountName; 私有静态最终字符串[]SCOPES={CalendarScopes.CALENDAR\u READONLY}; /** *创建主活动。 *@param savedInstanceState以前保存的实例数据。 */ @凌驾 受保护的void onCreateBundle savedInstanceState{ super.onCreatesavedInstanceState; LinearLayout activityLayout=新建LinearLayoutthis; LinearLayout.LayoutParams lp=新的LinearLayout.LayoutParams LinearLayout.LayoutParams.MATCH_父级, LinearLayout.LayoutParams.MATCH_父项; activityLayout.setLayoutParamslp; activityLayout.setOrientationLinearLayout.VERTICAL; activityLayout.setPadding16,16,16,16; ViewGroup.LayoutParams tlp=新建ViewGroup.LayoutParams ViewGroup.LayoutParams.WRAP_内容, ViewGroup.LayoutParams.WRAP_内容; mCallApiButton=新按钮此按钮; mcalapibutton.setTextBUTTON_文本; mCallApiButton.SetOnClickListener新建视图.OnClickListener{ @凌驾 公共视图v{ mCallApiButton.setEnabledfalse; moutput.setText; getResultsFromApi; mCallApiButton.setEnabledtrue; } }; activityLayout.addViewmCallApiButton; mOutputText=新文本视图此; moutput.setLayoutParamstlp; moutput ext.setPadding16,16,16,16; moutput.setVerticalScrollBarEnabledtrue; MoutText.setMovementMethodnew ScrollingMovementMethod; moutput.setText 单击\'+按钮\'文本+\'按钮测试API。; activityLayout.AddViewMoutText; mProgress=新的进度; 设置消息调用谷歌日历API。。。; setContentViewactivityLayout; //初始化凭据和服务对象。 mCredential=GoogleAccountCredential.usingAuth2 getApplicationContext,Arrays.asListSCOPES .退避新的指数退避; } /** *在验证所有前提条件都满足后,尝试调用API *满意。先决条件是:安装了Google Play服务 *已选择帐户,设备当前具有联机访问权限。如果有的话 *如果不满足前提条件,应用程序将提示用户 *合适。 */ 私有void getResultsFromApi{ 如果!Google PlayServices可用吗{ 收购谷歌游戏服务; }否则,如果mCredential.getSelectedAccountName==null{ 选择会计科目; }否则,如果!isDeviceOnline{ mOutputText.SETTEXT没有可用的网络连接。; }否则{ 新建MakeRequestTaskmCredential.execute; } } /** *尝试设置与API凭据一起使用的帐户。如果有账户 *以前保存的名称将使用该名称;否则,将创建一个帐户 *选择器对话框将显示给用户。请注意,设置 *与凭据对象一起使用的帐户要求应用程序具有 *GET_ACCOUNTS权限,如果尚未获得此权限,则在此请求此权限 *现在。AfterPermissionGrated注释表明 *只要获得帐户权限,函数就会自动重新运行 *这是理所当然的。 */ @AfterPermissionGranded请求\u权限\u获取\u帐户 私有无效选择帐户{ 如果EasyPermissions.hasPermissions 此,Manifest.permission.GET\u帐户{ 字符串accountName=getPreferencesContext.MODE\u PRIVATE .getStringPREF\u帐户名称,空; 如果accountName!=null{ mCredential.setSelectedAccountNameaccountName; getResultsFromApi; }否则{ //启动一个对话框,用户可以从中选择帐户 startActivityForResult mCredential.newchooseaccountcontent, 请求\帐户\选择器; } }否则{ //通过用户对话框请求GET_ACCOUNTS权限 EasyPermissions.requestPermissions 这 此应用程序需要通过联系人访问您的Google帐户。, 请求\u权限\u获取\u帐户, Manifest.permission.GET_帐户; } } /** *在此处启动活动时调用AccountPicker *然后授权退出,给您启动它的请求代码, *它返回的结果代码,以及其中的任何附加数据。 *@param requestCode表示传入哪个活动结果的代码。 *@param resultCode代码,指示传入 *活动结果。 *@param data Intent包含传入数据返回的结果数据 *活动结果。 */ @凌驾 活动结果上的受保护无效 int请求代码、int结果代码、意图数据{ super.onActivityResultrequestCode、结果代码、数据; 开关请求代码{ 案例请求\谷歌\播放\服务: 如果结果代码!=结果\u正常{ moutput.setText 此应用需要Google Play服务。请安装+ 谷歌在你的设备上播放服务并重新启动此应用程序。; }否则{ getResultsFromApi; } 打破 案例请求\账户\选取者: 如果resultCode==RESULT\u OK&&data!=null&& data.getExtras!=null{ 字符串帐户名= data.getStringExtraAccountManager.KEY\u ACCOUNT\u NAME; 如果accountName!=null{ 共享引用设置= getPreferencesContext.MODE_PRIVATE; SharedReferences.Editor=settings.edit; editor.putStringPREF\u ACCOUNT\u NAME,accountName; editor.apply; mCredential.setSelectedAccountNameaccountName; getResultsFromApi; } } 打破 案例请求和授权: 如果resultCode==RESULT\u正常{ getResultsFromApi; } 打破 } } /** *在API 23及以上版本的运行时响应权限请求。 *@param requestCode传入的请求代码 *requestPermissionsandroid.app.Activity,字符串,int,字符串[] *@param permissions请求的权限。永不为空。 *@param grantresult为相应的权限授予结果 *这是授予的权限或拒绝的权限。永不为空。 */ @凌驾 公共无效onRequestPermissionsResultint requestCode, @非空字符串[]权限, @非Null int[]grantResults{ super.onRequestPermissionsResultrequestCode、权限、grantResults; EasyPermissions.onRequestPermissionsResult 请求代码、权限、GrantResult、此; } /** *使用EasyPermissions授予权限时的回调 *图书馆。 *@param requestCode与请求的请求关联的请求代码 *许可 *@param列出请求的权限列表。永不为空。 */ @凌驾 公共无效OnPermissionsGrantenditRequestCode,列表{ //什么也不做。 } /** *使用EasyPermissions拒绝权限时的回调 *图书馆。 *@param requestCode与请求的请求关联的请求代码 *许可 *@param列出请求的权限列表。永不为空。 */ @凌驾 public void on Permissions拒绝请求代码,列表{ //什么也不做。 } /** *检查设备当前是否有网络连接。 *@如果设备有网络连接,则返回true,否则返回false。 */ 专用布尔值isDeviceOnline{ 连接管理器连接管理器= ConnectionManager getSystemServiceContext.CONNECTIVITY\u服务; NetworkInfo NetworkInfo=connMgr.getActiveNetworkInfo; return networkInfo!=null&&networkInfo.isConnected; } /** *检查Google Play services APK是否已安装且为最新版本。 *@如果Google Play服务可用且最多 *此设备上的日期;否则就错了。 */ 私有布尔值isGooglePlayServicesAvailable{ 谷歌可用性= GoogleApiAvailability.getInstance; 最终int连接状态代码= apiAvailability.isGooglePlayServicesAvailable此; 返回connectionStatusCode==ConnectionResult.SUCCESS; } /** *尝试解析丢失、过期、无效或已禁用的Google *如果可能,通过用户对话框播放服务安装。 */ 谷歌PlayServices私人网站{ 谷歌可用性= GoogleApiAvailability.getInstance; 最终int连接状态代码= apiAvailability.isGooglePlayServicesAvailable此; 如果apiAvailability.isUserResolvableErrorconnectionStatusCode{ showGooglePlayServicesAvailabilityErrorDialogconnectionStatusCode; } } /** *显示一个错误对话框,显示Google Play服务缺失 *或者过时了。 *@param connectionStatusCode描述存在或不存在连接的代码 *此设备上的Google Play服务。 */ void showGooglePlayServicesAvailabilityError对话框 最终int连接状态代码{ GoogleAppAvailability apiAvailability=GoogleAppAvailability.getInstance; Dialog Dialog=apiAvailability.getErrorDialog 日历,这个, 连接状态代码, 请求谷歌播放服务; dialog.show; } /** *处理Google日历API调用的异步任务。 *将API调用放在它们自己的任务中可以确保UI保持响应。 */ 私有类MakeRequestTask扩展了AsyncTask{ private com.google.api.services.calendar.calendar mService=null; 私有异常mLastError=null; MakeRequestTaskGoogleAccountCredential凭证{ HttpTransport-transport=AndroidHttp.newCompatibleTransport; JsonFactory JsonFactory=JacksonFactory.getDefaultInstance; mService=new com.google.api.services.calendar.calendar.Builder 传输、jsonFactory、凭证 .SetApplicationName谷歌日历API Android快速启动 建筑 } /** *后台任务调用谷歌日历API。 *@param params此任务不需要任何参数。 */ @凌驾 受保护列表doInBackgroundVoid…参数{ 试一试{ 返回getDataFromApi; }捕获异常e{ mLastError=e; 对; 返回null; } } /** *从主日历中获取接下来10个事件的列表。 *@return描述返回事件的字符串列表。 *@抛出异常 */ 私有列表getDataFromApi引发IOException{ //列出主日历中接下来的10个事件。 DateTime now=新的DateTimeSystem.currentTimeMillis; List eventStrings=newarraylist; Events=mService.Events.listprimary .setMaxResults10 赛特米诺先生 .setOrderBystartTime .setSingleEventstrue 行政长官 te; 列表项=events.getItems; 对于事件:项目{ DateTime start=event.getStart.getDateTime; 如果start==null{ //全天活动没有开始时间,所以只需使用 //开始日期。 开始=event.getStart.getDate; } eventStrings.add 字符串。格式%s%s,event.getSummary,start; } 返回事件字符串; } @凌驾 受保护的void onPreExecute{ moutput.setText; mProgress.show; } @凌驾 PostExecuteList输出上受保护的void{ mProgress.hide; 如果output==null | | output.size==0{ moutput.settext未返回任何结果。; }否则{ output.add0,使用Google日历API检索的数据:; mouttext.settextextutils.join\n,输出; } } @凌驾 一经取消保护无效{ mProgress.hide; 如果mLastError!=null{ 如果Google PlayServicesAvailabilityIoException的mLastError实例{ showGooglePlayServicesAvailabilityErrorDialog GooglePlayServicesAvailabilityIOException mLastError .getConnectionStatusCode; }否则,如果mLastError实例为UserRecoverableAuthIOException{ startActivityForResult UserRecoverableAuthIOException mLastError.getIntent, 日历。请求授权; }否则{ MoutText.SetText发生以下错误:\n +mLastError.getMessage; } }否则{ mouttext.setTextRequest已取消。; } } } }
好的,我自己解决了这个问题。我刚刚在Google Developer API控制台中输入了一个错误的SHA1密钥。
为了通过Android Studio获取我的SHA1密钥,我遵循了这一步骤。

代码太多了。至少有两个答案,它们首先都需要您做更多的工作:1使用调试器缩小代码中出现问题的位置。2.这样做的时候,你很可能会发现错误,如果没有,其他人介入并发现错误会更容易管理。是的,你完全正确,我会尽快这样做。我只是尝试这样做,因为这与教程的代码大致相同。