question

hneilk avatar image
hneilk asked

Exception generated on app first use

When I first open my game with GameCircle using WhisperSync and Leaderboards, I get the following exception in the log: E/GC_NetworkCallFactory(22301): Exception encountered while executing request: com.amazon.ags.AGSClientException: Network request requires authentication E/GC_NetworkCallFactory(22301): com.amazon.ags.AGSClientException: Network request requires authentication. E/GC_NetworkCallFactory(22301): at com.amazon.ags.html5.comm.HttpNetworkClient.addADPTokenHeaders(HttpNetworkClient.java:177) E/GC_NetworkCallFactory(22301): at com.amazon.ags.html5.comm.HttpNetworkClient.addAuthenticationHeaders(HttpNetworkClient.java:153) The game then loads WhisperSync data from local storage. If I hit the Back button and launch the game again, it reads the WhisperSync data correctly from the cloud. I'm initializing in onResume() as recommended, and it doesn't matter whether I obtain the GameDataMap immediately after initialization or in the AmazonGamesCallback. If I change the game data on a different device, I once again have to launch the game, hit the Back button, then launch again to get the latest from the cloud. Any ideas?
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Sujoy@Amazon avatar image
Sujoy@Amazon answered
Hi Hneilkelly, I am unable to understand when do you get AGSClientException in app start-up. Is it during the GameCircle initialization? I tested with SyncableString and data syncing is working as expected between a Kindle Fire and a Samsung device. public class MyActivity extends Activity { private static final String TAG = "MyActivity"; //reference to the agsClient AmazonGamesClient agsClient; AmazonGamesCallback callback = new AmazonGamesCallback() { @Override public void onServiceNotReady(AmazonGamesStatus status) { //unable to use service System.out.println("com.amazon.example.whispersynctest.MyActivity.onServiceNotReady"); } @Override public void onServiceReady(AmazonGamesClient amazonGamesClient) { System.out.println("MyActivity.onServiceReady"); agsClient = amazonGamesClient; enableButtons(); GameDataMap gameDataMap = AmazonGamesClient.getWhispersyncClient().getGameData(); final SyncableString str = gameDataMap.getLatestString("gameText"); if (str.isSet() && str.getValue() != null && str.getValue().length() > 0){ System.out.println("str = " + str.getValue()); final TextView textView = ((TextView)findViewById(R.id.local_text)); textView.post(new Runnable() { public void run() { textView.setText(str.getValue()); } }); } AmazonGamesClient.getWhispersyncClient().setWhispersyncEventListener(new WhispersyncEventListener() { public void onNewCloudData() { // refresh visible game data System.out.println("MyActivity.onNewCloudData"); GameDataMap gameDataMap = AmazonGamesClient.getWhispersyncClient().getGameData(); final SyncableString str = gameDataMap.getLatestString("gameText"); if (str.isSet() && str.getValue() != null && str.getValue().length() > 0){ System.out.println("str = " + str.getValue()); final TextView textViewLocal = ((TextView)findViewById(R.id.local_text)); final TextView textViewCloud = ((TextView)findViewById(R.id.cloud_text)); textViewLocal.post(new Runnable() { public void run() { textViewLocal.setText(str.getValue()); } }); textViewCloud.post(new Runnable() { public void run() { textViewCloud.setText(str.getValue()); } }); } } // The following three methods are mainly useful for debugging purposes and don't have to be overridden public void onDataUploadedToCloud() { System.out.println("MyActivity.onDataUploadedToCloud"); } }); } }; private void enableButtons() { findViewById(R.id.submitData).setEnabled(true); findViewById(R.id.sync).setEnabled(true); findViewById(R.id.login).setEnabled(true); } EnumSet myGameFeatures = EnumSet.of(AmazonGamesFeature.Leaderboards, AmazonGamesFeature.Whispersync); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); System.out.println("MyActivity.onResume"); AmazonGamesClient.initialize(this, callback, myGameFeatures); } public void submitData(View view) { GameDataMap gameDataMap = AmazonGamesClient.getWhispersyncClient().getGameData(); SyncableString gameText = gameDataMap.getLatestString("gameText"); String strToSync = Build.MODEL + " : " + ((EditText)findViewById(R.id.text_to_sync)).getText().toString(); System.out.println("strToSync = " + strToSync); gameText.set(strToSync); ((TextView)findViewById(R.id.local_text)).setText(strToSync); AmazonGamesClient.getWhispersyncClient().flush(); } public void sync(View view) { AmazonGamesClient.getWhispersyncClient().synchronize(); } public void login(View view) { AmazonGamesClient.getInstance().showSignInPage(); } }
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

hneilk avatar image
hneilk answered
Thanks for your help Sujoy. Your code helped point me in the right direction to solve my sync problem. Here's what I found - hopefully it will help others. 1. I was setting my game variables in onResume() after calling AmazonGamesClient.initialize. The docs state that game data is valid immediately after this call, but that's not the case if it's been changed on another device. Implementing the WhispersyncEventListener method onNewCloudData() inside the AmazonGamesCallback method onServiceReady method is required to update game variables, although I don't think the docs make this clear. At least it wasn't to me. 2. I also needed to add AmazonGamesClient.shutdown() to my onStop() method to force a new initialize each time the game is started. Without this it seems the callbacks aren't triggered and the cloud data isn't checked.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.