I have a "saved game chooser" activity for users to open saved games. I start the activity for result and return a string that represents the saved game to the parent activity.
The code I've been using is no more complex than this:
if(savedGameId != null) {
Intent result = new Intent();
result.putExtra("saved_game_key", savedGameId);
setResult(Activity.RESULT_OK, result);
finish();
}
In onActivityResult:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode) {
case SAVED_GAME_ACTIVITY:
if(resultCode == Activity.RESULT_OK) {
if(data.hasExtra("saved_game_key") {
String savedGameId = data.getExtra("saved_game_key");
...
} else {
// couldn't load game
}
}
break;
}
}
This has worked for me on all my test devices and emulators 100% of the time. However, I periodically get a crash report for a NPE for the data.hasExtra("saved_game_key") call.
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Intent.hasExtra(java.lang.String)' on a null object reference
at com.xxxx.yyyy.MainActivity.onActivityResult(MainActivity.java)
at android.app.Activity.dispatchActivityResult(Activity.java:6508)
...
The android versions and devices I've received this report so far:
Android 6.0 - MI MAX (hydrogen)
Android 6.0 - Lenovo K5 Note (A7020a48)
Android 6.0 - Moto G(4) (athene)
Android 5.1 - Galaxy Note 10.1 (lt033g)
Android 4.0.3 - 4.0.4 - Xperia tipo dual (ST21a2)
I have not been able to reproduce this issue myself. I'm going to try to get ahold of one of the above devices and see if I can get any more info.
In the meantime, I've searched google/stackoverflow and have not found anything that resembles this specific situation.
My Question
Is there something, some edge case that I've overlooked that could cause the returned data intent to be null in certain situations?
Like I said, I've never been able to reproduce this issue myself and the code looks correct based on other examples that I've seen for returning data from intents. If you need more information please leave me a comment.
Related
I have prepared a simple test project for this question at GitHub.
I am trying to create an Android app, which would scan a QR code from a computer screen and then use the data (MAC address and PIN or hash) for easy pairing (bonding) with a Bluetooth device.
Similar to the popular InstaWifi app - but for Classic Bluetooth.
For testing purposes I don't do any barcode scanning yet, but just display a list of devices:
After user touches one of the devices, pairing is tried in MainActivity.java:
private void startBluetoothPairing(BluetoothDevice device) {
Intent pairingIntent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
pairingIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
BluetoothDevice.PAIRING_VARIANT_PIN);
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, 1234);
//device.setPin(new byte[]{1,2,3,4}); <- DOES NOT CHANGE ANYTHING
//device.setPairingConfirmation(false);
startActivityForResult(pairingIntent, REQUEST_BT_SETTINGS);
}
Unfortunately, the popup still asks for PIN:
Because I have actually specified a PIN in my source code, I was actually expecting another, simpler system dialog to be shown (this one is shown when doing NFC OOB pairing):
From searching for solutions, I know that there is a setPin() method, but it is not applicable here (or is it?) - because I am trying to pair the whole smartphone to the Bluetooth device and not just the app...
My question: How to make Android OS to show the simple Cancel/Pair dialog?
Searching for Bluetooth pairing request string at GitHub has not shown any hints...
UPDATE: On unrealsoul007's suggestion (thanks) I have update the source code in MainActivity.java and now the simple Cancel/Pair dialog is displayed:
private void startBluetoothPairing(BluetoothDevice device) {
Intent pairingIntent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
pairingIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION);
pairingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(pairingIntent, REQUEST_BT_PAIRING);
}
However I am not sure how to complete the pairing process - because onActivityResult is called with resultCode=0 even before the dialog is closed:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// this is called before user clicks Cancel or Pair in the dialog
if (requestCode == REQUEST_BT_PAIRING) {
if (resultCode == Activity.RESULT_OK) { // 0 != -1
Log.d("XXX", "Let#s pair!!!!"); // NOT CALLED
}
return;
}
}
You are being prompted for entering the pin because that is what you are requesting in your pairingIntent.
Instead of using
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
BluetoothDevice.PAIRING_VARIANT_PIN);
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, 1234);
Use
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PASSKEY_CONFIRMATION);
As mentioned here,
The user will be prompted to confirm the passkey displayed on the
screen or an app will confirm the passkey for the user.
I am developing a game for Android using Google Play Game Services, using Xamarin. I am doing my testing using a Genymotion Android Emulator. I have run into an issue that appears to be a bug in either Google Play or Xamarin's implementation.
If I sign out of a Google account, calls to the IGoogleApiClient.IsConnected() continue to return true (even though I have clearly just signed out). If I then attempt to use that API object, I will get exceptions like:
java.lang.SecurityException: Not signed in when calling API
For example, the follow code results in the above exception if executed after signing out:
public void StartNewMatch()
{
if (!mGoogleApiClient.IsConnected)
{
return;
}
Intent intent = GamesClass.TurnBasedMultiplayer.GetSelectOpponentsIntent(mGoogleApiClient, 1, 1, true);
StartActivityForResult(intent, RC_SELECT_PLAYERS);
}
I am signing out in the Google Play Games Inbox (match picker); as shown in the images below.
Anyone run into this before? Am I missing something? Got any work-arounds?
Note: This only occurs if signing out through Google's UI. If I manually sign the user out, with something like mGoogleApiClient.Disconnect(), the issue does not occur; mGoogleApiClient.IsConnected() now returns false (as expected).
In order to keep signed-in state synced up you MUST implement onActivityResult properly.
This should look something as follows:
NOTE: this is java code, I am not sure how this will look exactly using Xamarin, but hopefully you should be able to figure it out :)
#Override
protected void onActivityResult(int requestCode, int responseCode, Intent data) {
// check for "inconsistent state"
if ( responseCode == GamesActivityResultCodes.RESULT_RECONNECT_REQUIRED && requestCode == <your_request_code_here> ) {
// force a disconnect to sync up state, ensuring that mClient reports "not connected"
mGoogleApiClient.disconnect();
}
}
NOTE: just make sure to replace in the code with the request code you used. You may need to check for multiple request codes too.
If you are using gameHelper classes from BaseGameUtils library(it is easier to use), you may modify the above code to this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
gameHelper.onActivityResult(requestCode, resultCode, data);
if (resultCode == GamesActivityResultCodes.RESULT_RECONNECT_REQUIRED){
// force a disconnect to sync up state, ensuring that mClient reports "not connected"
gameHelper.getApiClient().disconnect();
}
}
I want to have a virtual android pad that has no phone service so that the following code of mine will work:
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + getPhoneNumber()));
if (intent.resolveActivity(getPackageManager()) == null) {
//do alert
}
However, I don't know which of the out-of-box virtual device has no calling service. I tried "10.1 WXGA (Tablet)", but it has calling service embedded. What should I do?
What about creating a unit test and testing your code without be depending on that device?
Google developers is a good place to start.
I'm developing an app for android that uses TTS. I've created a splash screen where I check if the TTS engine is installed and in case that is not installed, it goes to Google Play to download it.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
...
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
...
if (requestCode == PersonalTextToSpeech.MY_DATA_CHECK_CODE)
{
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS)
{
mTts = new TextToSpeech(context, this);
} else
{
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
context.startActivity(installIntent);
}
}
}
It was working fine in Samsung devices with 2.2 and 2.3.x OS. It goes to Google Play if needed, but now I've tried with a Samsung Galaxy S3 (with 4.1.1), which has 2 TTS installed by default (Samsung and Google), so I get a dialog asking to select one.
If the user selects Samsung it works perfect, but if the user selects Google, it goes to Settings --> Language and input --> Text-to-speech output --> Google Text-to-speech Engine --> Settings --> Install Voice Data and I get this:
So, I have 3 questions/problems:
Is there any way to force programatically to use Samsung TTS without asking?
My device is from Spain, but if I change the language to English, this one is not available in my Google list of TTS languages, and I can't find a way to add it (see screenshot #2).
If I change the language to spanish, this language is supposed to be installed in my device (see screenshot #2), but for some reason TTS resultCode is LANG_NOT_SUPPORTED (-2).
In fact, right now while I write this, I've just found something weird.
If you select Samsung TTS, it will "work" (resultCode = CHECK_VOICE_DATA_PASS (1)), but the "voice sound" will change depending on how you have your setting (view Screenshot #3):
If you choose Samsung, it will use Samsung TTS or Google TTS according to what you have selected in:
Settings --> Language and input --> Text-to-speech output.
So, even if you select Samsung TTS, you could be using Google TTS, but if you select Google TTS directly (see Screenshot #1) it will fail.
Can someone explain me what I'm doing wrong?
Thanks for your help.
i too stucked in this problem and i solved it by just replacing a code in my onActivityResult.
Instead of checking for TTS Data,i just checked for available voices.
if (availableLanguages.isEmpty()) {
// no language data available, prompt for install
Intent installIntent = new Intent();
installIntent
.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
} else {
// some language data is available, create TTS instance
myTTS = new TextToSpeech(this, this);
}
my app makes use of ZXing barcode scanner using the ZXing helper classes IntentIntegrator and IntentResult.
Now I found there are no longer scanning results submitted from ZXing, the related return values are empty/null.
Thus I updated to latest helper classes http://code.google.com/p/zxing/source/browse/trunk/android-integration/src/com/google/zxing/integration/android/IntentIntegrator.java and http://code.google.com/p/zxing/source/browse/trunk/android-integration/src/com/google/zxing/integration/android/IntentResult.java
Now my onActivityResult method is called immediately after ZXing is started - of course with an empty result again.
My code is quite simple, scanning is started this way:
if (v==scanButton)
{
com.google.zxing.integration.android.IntentIntegrator integrator = new IntentIntegrator(this);
integrator.initiateScan();
}
and fetching the results this way:
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
com.google.zxing.integration.android.IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanResult != null)
{
String format;
format=scanResult.getFormatName();
if ((format!=null) && (format.length()>0))
{
if ((format.equals("EAN_8")) || (format.equals("EAN_13")) ||(format.equals("UPC_A")) ||(format.equals("UPC_E")))
getEANData(scanResult.getContents());
}
}
}
On my android the latest ZXing code is installed. Any ideas why it does not work any more?
From what I found out meanwhile: this seems to be an installation-dependent problem. On my Android device I can see that problem but it is not reproducible, other users of my App do not experience this. ZXing code itself wasn't changed for longer time and there users confirm it works too - so that seems to be a really ugly bug.
Here it happens with ZXing-code installed from Playstore, haven't tested it with ZXing included into my app yet...