Intereting Posts
Невозможно использовать LayoutInflater в пользовательском адаптере Как использовать ScriptIntrinsic3DLUT с .cube-файлом? Android.database.sqlite.SQLiteException: нет такого столбца Упаковка приложений для приложений для Android не соответствует вкусам Отсутствует графический макет для XML-файлов макета Странное поведение с датчиком ориентации Android Android split ActionBar – изменение раскладки значков Библиотека проверки лицензии Android и несколько учетных записей Google Как вручную вводить логин и выход из системы с помощью кнопки без использования <com.facebook.widget.LoginButton />? Как предоставить разрешение на использование adb без укорачивания устройств Пользовательский ArrayAdapter getView не называется – почему нет? Сбой транзакции Binder при возвращении изображения камеры Как преобразовать InputStream в Source? Как отключить горизонтальную прокрутку в веб-браузере Android Могу ли я одновременно открыть как Wi-Fi, так и сотовые сетевые интерфейсы на Android?

Не удалось связаться с Google Datastore с Android-приложением в Android Studio

Я пытаюсь создать приложение Android, которое взаимодействует с Google App Engine для загрузки и сохранения объектов в хранилище google. Я думаю, что у меня есть правильная настройка, но я не знаю, могу ли я загрузить свое приложение, чтобы проверить его, он просто зависает навсегда, а затем дает мне эту ошибку:

SEVERE: Endpoints configuration not updated. The app returned an error when the Google Cloud Endpoints server attempted to communicate with it. 

Однако, если я изменю номер версии, новая версия появится в моей консоли онлайн даже после получения этого сообщения. Я прочитал всю документацию Google в Datastore и не мог понять, что случилось. У меня была эта проблема в течение месяца и я не смог найти решение. Я где-то читал, что если приложение содержит ошибку, оно не будет загружено, поэтому я включу весь мой код. Я также не знаю, что я делаю, даже не уверен, что я нахожусь на правильном пути, почему это не работает, поэтому, если вы заметили что-то глупое, скажите, пожалуйста, мне. Заранее спасибо, вы станете моим героем и моим богом, если сможете исправить это для меня.

Вот моя конечная точка:

 package com.polo.backend.endpoints; /** * Created by sagesmith on 4/16/16. * * Is used to interact with the server */ import com.google.api.server.spi.config.Api; import com.google.api.server.spi.config.ApiMethod; import com.google.api.server.spi.config.ApiNamespace; import com.google.api.server.spi.response.ConflictException; import com.google.api.server.spi.response.NotFoundException; import com.googlecode.objectify.Ref; import com.polo.backend.services.ObjcfyService; import com.polo.backend.entities.Event; import com.polo.backend.entities.User; import java.util.List; import javax.inject.Named; /** * */ @Api( name = "userEndpoint", version = "v1", namespace = @ApiNamespace( ownerDomain = "backend.polo.com", ownerName = "backend.polo.com", packagePath = "" ) ) public class UserEndpoint { /** * Registers the two entities used in this class */ public UserEndpoint(){ ObjcfyService.register(User.class); ObjcfyService.register(Event.class); } @ApiMethod(name = "insertUser") /** * Inserts a new {@code User} into the data store */ public void insertUser(User user) throws ConflictException, NotFoundException{ if(getUser(user.getUsername()) != null){ throw new ConflictException("Object already exists"); } } /** * * @param user * @throws NotFoundException */ @ApiMethod(name = "updateUser") public void updateUser(User user) throws NotFoundException{ if(getUser(user.getUsername()) != null) { ObjcfyService.objectify().save().entity(user).now(); } } /** * * @param username * @throws NotFoundException */ @ApiMethod(name = "removeUser") public void removeUser(@Named("username") String username) throws NotFoundException{ User record = getUser(username); if(record != null){ ObjcfyService.objectify().delete().entity(record).now(); } } /** * * @param username * @return * @throws NotFoundException */ @ApiMethod(name = "getUser") public User getUser(@Named("username") String username) throws NotFoundException{ User user = ObjcfyService.objectify().load().type(User.class).id(username).now(); if(user != null) { List<Ref<User>> friendRefs = user.getFriendRefs(); List<Ref<Event>> repeatingEventRefs = user.getRepeatingEventRefs(); List<Ref<Event>> nonRepeatingEventRefs = user.getNonRepeatingEventRefs(); for (Ref<User> friendRef : friendRefs) { user.addFriend(friendRef.get()); } for (Ref<Event> repeatingEventRef : repeatingEventRefs) { user.addRepeatingEvent(repeatingEventRef.get()); } for (Ref<Event> nonRepeatingEventRef : nonRepeatingEventRefs) { user.addNonRepeatingEvent(nonRepeatingEventRef.get()); } } else{ throw new NotFoundException("User not found"); } return user; } } , за package com.polo.backend.endpoints; /** * Created by sagesmith on 4/16/16. * * Is used to interact with the server */ import com.google.api.server.spi.config.Api; import com.google.api.server.spi.config.ApiMethod; import com.google.api.server.spi.config.ApiNamespace; import com.google.api.server.spi.response.ConflictException; import com.google.api.server.spi.response.NotFoundException; import com.googlecode.objectify.Ref; import com.polo.backend.services.ObjcfyService; import com.polo.backend.entities.Event; import com.polo.backend.entities.User; import java.util.List; import javax.inject.Named; /** * */ @Api( name = "userEndpoint", version = "v1", namespace = @ApiNamespace( ownerDomain = "backend.polo.com", ownerName = "backend.polo.com", packagePath = "" ) ) public class UserEndpoint { /** * Registers the two entities used in this class */ public UserEndpoint(){ ObjcfyService.register(User.class); ObjcfyService.register(Event.class); } @ApiMethod(name = "insertUser") /** * Inserts a new {@code User} into the data store */ public void insertUser(User user) throws ConflictException, NotFoundException{ if(getUser(user.getUsername()) != null){ throw new ConflictException("Object already exists"); } } /** * * @param user * @throws NotFoundException */ @ApiMethod(name = "updateUser") public void updateUser(User user) throws NotFoundException{ if(getUser(user.getUsername()) != null) { ObjcfyService.objectify().save().entity(user).now(); } } /** * * @param username * @throws NotFoundException */ @ApiMethod(name = "removeUser") public void removeUser(@Named("username") String username) throws NotFoundException{ User record = getUser(username); if(record != null){ ObjcfyService.objectify().delete().entity(record).now(); } } /** * * @param username * @return * @throws NotFoundException */ @ApiMethod(name = "getUser") public User getUser(@Named("username") String username) throws NotFoundException{ User user = ObjcfyService.objectify().load().type(User.class).id(username).now(); if(user != null) { List<Ref<User>> friendRefs = user.getFriendRefs(); List<Ref<Event>> repeatingEventRefs = user.getRepeatingEventRefs(); List<Ref<Event>> nonRepeatingEventRefs = user.getNonRepeatingEventRefs(); for (Ref<User> friendRef : friendRefs) { user.addFriend(friendRef.get()); } for (Ref<Event> repeatingEventRef : repeatingEventRefs) { user.addRepeatingEvent(repeatingEventRef.get()); } for (Ref<Event> nonRepeatingEventRef : nonRepeatingEventRefs) { user.addNonRepeatingEvent(nonRepeatingEventRef.get()); } } else{ throw new NotFoundException("User not found"); } return user; } } 

Вот мой пользовательский объект:

 package com.polo.backend.entities; /** * Created by sagesmith on 4/16/16. */ import com.google.api.server.spi.config.AnnotationBoolean; import com.google.api.server.spi.config.ApiResourceProperty; import com.googlecode.objectify.Ref; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Index; import com.googlecode.objectify.annotation.Load; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; @Entity public class User { @Id private String username = null; @Index private String firstName = null; @Index private String lastName = null; @Nullable private String status = null; @Nullable private String location = null; @Load @Nullable private List<Ref<User>> friendRefs = new ArrayList<>(); @Load @Nullable private List<Ref<Event>> nonRepeatingEventRefs = new ArrayList<>(); @Load @Nullable private List<Ref<Event>> repeatingEventRefs = new ArrayList<>(); @Nullable public List<User> friends = new ArrayList<>(); @Nullable public List<Event> nonRepeatingEvents = new ArrayList<>(); @Nullable public List<Event> repeatingEvents = new ArrayList<>(); /** *Returns the first name from the {@code User} * * @return the first name of the {@code User} as a {@code String} */ public String getFirstName(){ return firstName; } /** * Returns the last name from the {@code User} * * @return the last name of the {@code User} as a {@code String} */ public String getLastName(){ return lastName; } /** * Return the username from the user * * @return the username of the user as a String */ public String getUsername(){ return username; } /** * Sets the username of the {@code User} * * @param username Username to set the {@code User}'s username to */ public void setUsername(String username){ this.username = username; } /** * Sets the firstName of the {@code User} * * @param firstName First name to set the {@code User}'s first name to */ public void setFirstName(String firstName){ this.firstName = firstName; } /** * Sets the lastName of the {@code User} * * @param lastName Last name to set the {@code User}'s last name to */ public void setLastName(String lastName){ this.lastName = lastName; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) /** * Adds a friend to the {@code User}'s list of friends * * @param user User to add */ public void addFriendRef(User user){ friendRefs.add(Ref.create(user)); } /** * Returns the {@code User}'s friends * * @return {@code List<Users>} the friends of the {@code User} */ public List<User> getFriends(){ return friends; } /** * Adds a friend to the users {@code List} of friends * * @param user {@code User} to add as a friend */ public void addFriend(User user){ friends.add(user); } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) /** * Returns a {@code List<Ref<User>>} of references to the {@code User}'s friends * * @return {@code List<Ref<User>>} */ public List<Ref<User>> getFriendRefs(){ return friendRefs; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) /** * Returns a {@code List<Ref<Event>>} of references to the {@code User}'s repeating * {@code Event}s * * @return {@code List<Ref<Event>>} */ public List<Ref<Event>> getRepeatingEventRefs(){ return repeatingEventRefs; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) /** * Returns a {@code List<Ref<Event>>} of references to the {@code User}'s non repeating * {@code Event}s * * @return {@code List<Ref<Event>>} */ public List<Ref<Event>> getNonRepeatingEventRefs(){ return nonRepeatingEventRefs; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) /** * Sets the {@code User}'s status to a given {@code String} * * @param status {@code String} to set an {@code Users}'s status to */ public void setStatus(String status){ this.status = status; } /** * Returns the {@code User}'s status as a {@code String} * * @return {@code String} status */ public String getStatus(){ return status; } /** * Returns the {@code User}'s location as a {@code String} * * @return {@code String} location */ public String getLocation(){ return location; } /** * Sets the {@code User}'s location to a given {@code String} * * @param location {@code String} to set an {@code Users}'s location to */ public void setLocation(String location){ this.location = location; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) /** * Adds a repeating {@code Event} to the {@code User}'s schedule * * @param event {@code Event} to add to the {@code User}'s schedule */ public void addRepeatingEvent(Event event){ repeatingEventRefs.add(Ref.create(event)); } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) /** * Adds a non repeating {@code Event} to the user's schedule * * @param event Event to add to the the user's schedule */ public void addNonRepeatingEvent(Event event){ nonRepeatingEventRefs.add(Ref.create(event)); } /** * Returns a {@code List<Event>} of repeating {@code Event}s from the user's schedule * * @return List<Event> repeatingEvents from user's schedule */ public List<Event> getRepeatingEvents(){ return repeatingEvents; } /** * Returns a list of nonRepeatingEvents from the user's schedule * * @return List<Event> repeatingEvents from user's schedule */ public List<Event> getNonRepeatingEvents(){ return nonRepeatingEvents; } } 

И мой объект Event:

 package com.polo.backend.entities; import com.googlecode.objectify.annotation.Entity; /** * Created by sagesmith on 5/3/16. */ @Entity public class Event { private Integer startIndex; private Integer endIndex; private Byte[] color; public Event(Integer startIndex, Integer endIndex, Byte red, Byte green, Byte blue){ this.startIndex = startIndex; this.endIndex = endIndex; color = new Byte[]{red, green, blue}; } } 

И мой ObjectifyService:

 package com.polo.backend.services; /** * Created by sagesmith on 4/16/16. */ import com.googlecode.objectify.Objectify; import com.googlecode.objectify.ObjectifyFactory; import com.googlecode.objectify.ObjectifyService; public class ObjcfyService { public static void register(Class<?> eClass){ ObjectifyService.register(eClass); } public static Objectify objectify(){ return ObjectifyService.ofy(); } public static ObjectifyFactory objectifyFactory(){ return ObjectifyService.factory(); } } 

Вот мой appengine-web.xml, я заменил свое приложение my_id по понятным причинам:

 <?xml version="1.0" encoding="utf-8"?> <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application>my_id</application> <version>1</version> <threadsafe>true</threadsafe> <system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/> </system-properties> 

Вот мой web.xml

 <?xml version="1.0" encoding="utf-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"> <servlet> <servlet-name>SystemServiceServlet</servlet-name> <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class> <init-param> <param-name>services</param-name> <param-value>com.polo.backend.endpoints.UserEndpoint</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>SystemServiceServlet</servlet-name> <url-pattern>/_ah/spi/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> 

Наконец, вот AsyncTask, который я использую для связи с хранилищем данных из моего приложения Android, я снова заменил свой идентификатор приложения my_id:

 package com.polo.client; import android.os.AsyncTask; import android.util.Log; import android.widget.Toast; import com.google.api.client.extensions.android.http.AndroidHttp; import com.google.api.client.extensions.android.json.AndroidJsonFactory; import com.polo.StaticAssets; import com.polo.activity.Home; import com.polo.backend.userEndpoint.UserEndpoint; import com.polo.backend.userEndpoint.model.User; import java.io.IOException; /** * Created by sagesmith on 4/17/16. */ public class UserAsyncTask extends AsyncTask<Void, Void, User>{ private static UserEndpoint userApiService = null; private Home context; private String username; /** * * @param context */ public UserAsyncTask(Home context){ this.context = context; username = StaticAssets.getUserName(context); } /** * * @param params * @return */ @Override protected User doInBackground(Void... params){ if(userApiService == null){ UserEndpoint.Builder builder = new UserEndpoint.Builder( AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null ) .setRootUrl("https://my_id.appspot.com/_ah/api/"); userApiService = builder.build(); } User user = null; try{ user = userApiService.getUser(username).execute(); } catch (IOException e){ Log.e("User not found", e.getMessage()); } return user; } /** * * @param result */ @Override protected void onPostExecute(User result) { if(result!=null) Toast.makeText(context, result.getFirstName(), Toast.LENGTH_LONG).show(); } } 

Это помогает взглянуть на полное сообщение об ошибке, которое советует:

Дополнительную информацию см. В документации по устранению неполадок развертывания: https://developers.google.com/appengine/docs/java/endpoints/test_deploy#troubleshooting_a_deployment_failure.

Документы советуют проверить ваши журналы на « /_ah/spi/BackendService.getApiConfigs » в качестве первого шага. Если я попытаюсь развернуть континент Endpoints на основе образца, я вижу в своих журналах следующее:

 javax.servlet.ServletContext log: unavailable java.lang.reflect.InvocationTargetException at com.google.appengine.runtime.Request.process-b693af604777a85a(Request.java) ... Caused by: java.lang.StackOverflowError ... com.googlecode.objectify.impl.translate.ClassTranslatorFactory.create(ClassTranslatorFactory.java:49) ... 

Эта ошибка возникает только при вызовах ObjectifyService.register(class) , hmm …

В вашем классе User что-то, что вызовет бесконечную рекурсию, когда Objectify попытается зарегистрировать класс и привести к StackOverflowError:

 @Nullable public List<User> friends = new ArrayList<>(); 

Вместо определения самого списка вы можете исправить это, указав список Ref<User> как это было сделано в другом месте класса (возможно, это была опечатка):

 @Nullable public List<Ref<User>> friends = new ArrayList<>(); 

Кроме того, другая проблема вызвана тем, что класс Event отсутствует @Id, который может быть зафиксирован таким образом:

 @Entity public class Event { @Id private Long id; ... 

После внесения этих изменений я могу развернуть приложение Endpoints без каких-либо ошибок.