Project Tango Pythagoras: Can't trigger OnXYZijAvailable Callback - java

Developing a Project Tango Android app in the Java API, and I can't get the tablet to trigger an onXYZijAvailable callback, and I'd really like to use the depth data in my application.
Here is my code for setting up the Tango and attaching its listeners:
Upon Tango initialization:
try {
Log.d(TAG, "Creating TangoPoseHandler Object");
this.main = main;
mTango = new Tango(main);
mConfig = new TangoConfig();
mConfig = mTango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);
mConfig.putBoolean(TangoConfig.KEY_BOOLEAN_MOTIONTRACKING, true);
mConfig.putBoolean(TangoConfig.KEY_BOOLEAN_DEPTH, true);
mConfig.putBoolean(TangoConfig.KEY_BOOLEAN_AUTORECOVERY, true);
framePairs = new ArrayList<TangoCoordinateFramePair>();
} catch (TangoErrorException e) {
Log.d("TANGO ERROR", "TangoErrorException");
}
During the activity's onResume():
if (!isTangoConnected) {
main.startActivityForResult(
Tango.getRequestPermissionIntent(Tango.PERMISSIONTYPE_MOTION_TRACKING),
Tango.TANGO_INTENT_ACTIVITYCODE);
}
Upon Activity result:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(MAIN_ACTIVITY, "Activity Result Triggered");
if (Tango.TANGO_INTENT_ACTIVITYCODE == requestCode) {
((TangoPoseHandler)poseHandler).setup(requestCode, resultCode, data);
}
}
The setup method called:
public void setup(int requestCode, int resultCode, Intent data) {
if (requestCode == Tango.TANGO_INTENT_ACTIVITYCODE) {
// Make sure the request was successful
if (resultCode == android.app.Activity.RESULT_CANCELED) {
Toast.makeText(main,
"This app requires Motion Tracking permission!",
Toast.LENGTH_LONG).show();
main.finish();
return;
}
try {
setTangoListeners();
} catch (TangoErrorException e) {
Log.d(TAG, "TANGO ERROR WHEN SETTING LISTENERS");
Toast.makeText(main, "Tango Error! Restart the app!",
Toast.LENGTH_SHORT).show();
return;
}
try {
mTango.connect(mConfig);
isTangoConnected = true;
} catch (TangoOutOfDateException e) {
Toast.makeText(main.getApplicationContext(),
"Tango Service out of date!", Toast.LENGTH_SHORT)
.show();
} catch (TangoErrorException e) {
Toast.makeText(main.getApplicationContext(),
"Tango Error! Restart the app!", Toast.LENGTH_SHORT)
.show();
}
}
}
The setTangoListeners() method called:
private void setTangoListeners() {
// Select coordinate frame pairs
framePairs.clear();
framePairs.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE ,
TangoPoseData.COORDINATE_FRAME_DEVICE ));
mTango.connectListener(framePairs, new Tango.OnTangoUpdateListener() {
/**
* Callback called when new pose data is made available from the Tango
* #param tangoPoseData
*/
#Override
public void onPoseAvailable(final TangoPoseData tangoPoseData) {
if (tangoPoseData.baseFrame == TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE &&
tangoPoseData.targetFrame == TangoPoseData.COORDINATE_FRAME_DEVICE ) {
float[] transform = new float[16];
Matrix.setIdentityM(transform, 0);
NVector translationData = new NVector(
SCALE_FACTOR * tangoPoseData.getTranslationAsFloats()[TangoPoseData.INDEX_TRANSLATION_X],
SCALE_FACTOR * tangoPoseData.getTranslationAsFloats()[TangoPoseData.INDEX_TRANSLATION_Y],
SCALE_FACTOR * tangoPoseData.getTranslationAsFloats()[TangoPoseData.INDEX_TRANSLATION_Z]);
rotationQuat = new NVector((float) tangoPoseData.rotation[TangoPoseData.INDEX_ROTATION_X],
tangoPoseData.getRotationAsFloats()[TangoPoseData.INDEX_ROTATION_Y],
tangoPoseData.getRotationAsFloats()[TangoPoseData.INDEX_ROTATION_Z],
tangoPoseData.getRotationAsFloats()[TangoPoseData.INDEX_ROTATION_W]);
float[] quatMat = new float[16];
Matrix.setIdentityM(quatMat, 0);
quatMat = quaternionToMatrix(rotationQuat);
Matrix.multiplyMM(transform, 0, openGLConversion, 0, quatMat, 0);
transform[12] = translationData.getX();
transform[13] = translationData.getZ();
transform[14] = -1.f * translationData.getY();
float[] invertedTransform = new float[16];
Matrix.setIdentityM(invertedTransform, 0);
Matrix.invertM(invertedTransform, 0, transform, 0);
//main.displayMat(invertedTransform);
SceneCamera.instance().setEye(translationData);
SceneCamera.instance().set(invertedTransform);
//main.displayVals(tempPosition, rotationQuat);
}
}
/**
* Callback called when new depth data is made available from the tango
*
* #param tangoXyzIjData
*/
#Override
public void onXyzIjAvailable(final TangoXyzIjData tangoXyzIjData) {
Log.d("Depth Data", "Collected");
pointCloudBuffer = tangoXyzIjData.xyz;
}
/**
* Callback when new Image Frame is available for capture
* #param cameraID ID of the camera who has a fresh frame prepared
*/
#Override
public void onFrameAvailable(int cameraID) {
Log.d(TAG, "onFrameAvailable Called");
// Intentionally left empty
}
/**
* Callback when tango has an issue that needs addressing
* #param tangoEvent the event storing the data of the issue
*/
#Override
public void onTangoEvent(final TangoEvent tangoEvent) {
if (tangoEvent.eventKey.equals(TangoEvent.DESCRIPTION_FISHEYE_OVER_EXPOSED) ||
tangoEvent.eventKey.equals((TangoEvent.DESCRIPTION_COLOR_OVER_EXPOSED))) {
sendMessage("The Camera is overexposed. Please try facing somewhere with less direct light.");
}
if (tangoEvent.eventKey.equals(TangoEvent.DESCRIPTION_FISHEYE_UNDER_EXPOSED) ||
tangoEvent.eventKey.equals((TangoEvent.DESCRIPTION_COLOR_UNDER_EXPOSED))) {
sendMessage("Fisheye Lens is underexposed. Please try facing somewhere with more light.");
}
}
});
}
I hate to vomit code like this, but I've been trying on and off for weeks to get the depth sensing to work, but the onXYZijAvailable callback just refuses to be called, and I'm at the end of my rope.
One thing that might be an issue is that the app uses Vuforia for some extra Augmented Reality features, and has access to the color camera and camera preview, but I didn't see anything in the Tango documentation that would suggest that that might cause an issue.
Thanks much to anyone that can help me out.

Related

Can only open camera once?

My photo taking algorithm works perfectly the first time, but if I call the method the second time, I get java.lang.RuntimeException: Fail to connect to camera service on camera.open()
takePhoto(this, 0);//back camera.
takePhoto(this, 1);//selfie. No matter what, the second line crashes. Even if I switch the two lines.
Here is the method that only works the first time:
private void takePhoto(final Context context, final int frontorback) {
Log.v("myTag", "In takePhoto()");
final SurfaceView preview = new SurfaceView(context);
SurfaceHolder holder = preview.getHolder();
// deprecated setting, but required on Android versions prior to 3.0
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new SurfaceHolder.Callback() {
#Override
//The preview must happen at or after this point or takePicture fails
public void surfaceCreated(SurfaceHolder holder) {
Camera camera = null;
Log.v("myTag", "Surface created ");
try {
camera = Camera.open(frontorback); //** THIS IS WHERE IT CRASHES THE SECOND TIME **
Log.v("myTag", "Opened camera");
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.v("myTag", "Can't assign preview to Surfaceview holder" + e.toString());
}
try {
camera.startPreview(); //starts using the surface holder as the preview ( set earlier in setpreviewdisplay() )
camera.autoFocus(new Camera.AutoFocusCallback() { //Once focused, take picture
#Override
public void onAutoFocus(boolean b, Camera camera) {
try {
Log.v("myTag", "Started focusing");
camera.takePicture(null, null, mPictureCallback);
Log.v("myTag", "Took picture!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (Exception e) {
Log.v("myTag", "Can't start camera preview " + e.toString());
if (camera != null)
camera.release();
throw new RuntimeException(e);
}
}catch(Exception e){
Log.v("myTag", "can't open camera " +e.toString());
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
});
addPreviewToSurfaceView(); //Irrelavent here
}
//CALLBACK WHERE I RELEASE:
android.hardware.Camera.PictureCallback mPictureCallback = new android.hardware.Camera.PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
downloadPicture(data);
sendPicture(data);
Log.v("myTag","Picture downloaded and sent");
}
};
It's odd, because takePhoto(context, int) only works the first time no matter what. Even if I switch the second parameter, only the first takePhoto() works.
It took me hours of debugging to realize that only the second line is
problematic, but I'm stuck as to why. Any feedback is much
appreciated!
EDIT:
Even after removing the code in my onPictureTaken callback, the problem continues to persist. I suspect the camera may need time to reopen immediately, but I can't sleep the thread since I'm performing UI interactions on it. This bug is like a puzzle right now!
You cannot call takePhoto() one after another, because this call takes long time (and two callbacks) to complete. You should start the second call after the first picture is finished. Here is an example, based on your code:
private void takePhoto(final Context context, final int frontorback) {
...
android.hardware.Camera.PictureCallback mPictureCallback = new android.hardware.Camera.PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
if (frontorback == 0) {
takePhoto(context, 1);
}
}
downloadPicture(data);
sendPicture(data);
Log.v("myTag","Picture downloaded and sent");
}
};
This will start the first photo and start the second photo only when the first is complete.
Here might be problem.
After you take photo, the picture taken callback get called.
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
And the camera has been released, so the second time won't work. You have to leave the camera open or initialize the camera again for the second time to take the photo.

Android Service: Stopself is not killing my app service

I'm doing a Foreground service in my application, and when I'm calling the method Stopself inside the service it is calling my OnDestroy method but it's not killing my service. It still using memory, I check it through adb shell dumpsys meminfo.
I tried to call StopService too from my application but it's not working. I read a lot of posts from other people with the same problem, but they are using Handlers inside the Service. In my case I manage everything with a Singleton ThreadPool manager, that I already close with shutdown() method when app is closed.
It just happened when I close the app and my service still working. For example:
If I record a Fastmotion video and I wait until it is process, and later, I close my app. I don't have this memory lead. But, if I close the app then the service is processing this, It finish the processing, but I have a memory lead because Server is not killed.
So, hope that someone can see where it fails or what can I change to make this work. Here is my Service code:
/*
Base Service is a abstract class which implement the concurrent methods for the different services of the app
*/
public abstract class BaseService extends Service {
private static final String TAG = "BaseService";
private static final int NOTIFICATION_ID = 10;
private Notification mNotification;
private boolean mIsNotificationShow = false;
/**
* mIsRegistered boolean controls when the application is in background or not.
* Is set to true in {#link #ServiceConnection method}
* Is set to false in {#link #unbindMediaSaveService()}
*/
protected boolean mIsRegistered = false;
/**
* Count the number of request in the service to show the notification
* and hide it when all of them are over
*/
protected int mNotificationCount = 0;
protected synchronized void showNotification() {
mNotificationCount++;
// Notification already shown.
if (mIsNotificationShow)
return;
if (mNotification == null) {
Bitmap bigIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
mNotification = new Notification.Builder(this)
.setContentTitle(getString(R.string.app_name))
.setContentText(getResources().getString(R.string.string_processing_notification_service))
.setSmallIcon(R.drawable.ic_menu_savephoto)
.setLargeIcon(bigIcon).build();
}
startForeground(NOTIFICATION_ID, mNotification);
mIsNotificationShow = true;
}
protected synchronized void hideNotification() {
mNotificationCount--;
// Notification already hidden.
if (!mIsNotificationShow)
return;
if (mNotificationCount == 0) {
stopForeground(true);
mIsNotificationShow = false;
tryToCloseService();
}
}
/**
* Set IsRegistered boolean to true or false to check in the service when the application is in background or not
*
* #param register set the boolean value
*/
public void registerServiceClient(boolean register) {
mIsRegistered = register;
Log.i(TAG, "[registerServiceClient] Client registered: " + register);
if (!register) {
tryToCloseService();
}
}
/**
* Try to close the current service. It will be close if the application is in background{#link #mIsRegistered}
* and the service don't have current actions{#link #mNotificationCount}
*/
public void tryToCloseService() {
Log.i(TAG, "[tryToCloseService] Trying to close Service");
if (!mIsRegistered && mNotificationCount == 0) {
Log.i(TAG, "[tryToCloseService] Service stopped");
stopSelf();
} else {
Log.i(TAG, "[tryToCloseService] pending actions " + mNotificationCount);
}
}
}
I initialize a ServiceConnection and bind the service in my activity:
private ServiceConnection mMediaSaveConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder b) {
mMediaSaveService = ((MediaSaveService.LocalBinder) b).getService();
m
MediaSaveService.registerServiceClient(true);
}
#Override
public void onServiceDisconnected(ComponentName className) {
if (mMediaSaveService != null) {
mMediaSaveService.setListener(null);
mMediaSaveService.setPhotoListener(null);
mMediaSaveService = null;
}
}
};
private void bindMediaSaveService() {
Intent intent = new Intent(this, MediaSaveService.class);
startService(intent);
if (mMediaSaveConnection != null) {
bindService(intent, mMediaSaveConnection, Context.BIND_AUTO_CREATE);
mMediaSaverIsBind = true;
}
}
private void unbindMediaSaveService() {
if (mMediaSaveService != null) {
mMediaSaveService.registerServiceClient(false);
}
if (mMediaSaveConnection != null && mMediaSaverIsBind) {
unbindService(mMediaSaveConnection);
mMediaSaverIsBind = false;
}
}
Finally I call this methods in my onStart / onStop of my activity. Also, if it can help, in the services where I extend my BaseService, I put a START_NOT_STICKY flag to don't recreate the service when it's killed.

Integration of Google Play Services with LibGDX

I have been trying out Google Play Services Multiplayer APK, and have tried out the sample code, "Button Clicker" as shown below.
However, I am not sure how to port this over to LibGDX as currently the code is running based off a normal project without the "core" and "androidlauncher" that libGDX has. Does anyone perhaps have any advise on how should i do it? From what i know, core has a Mainclass with a method called render() which always run in a loop. However I cant think of a way of integrating it.
I have checked out several websites , However, could i ask why cant i just place the whole Buttonclicker project into the core module and call methods from it? Like sign in and sign out.
I only require the functionalities currently implemented in Button Clicker
CODE AS FOLLOWS:
/* Copyright (C) 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ryanhello;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.games.Games;
import com.google.android.gms.games.GamesStatusCodes;
import com.google.android.gms.games.GamesActivityResultCodes;
import com.google.android.gms.games.multiplayer.Invitation;
import com.google.android.gms.games.multiplayer.Multiplayer;
import com.google.android.gms.games.multiplayer.OnInvitationReceivedListener;
import com.google.android.gms.games.multiplayer.Participant;
import com.google.android.gms.games.multiplayer.realtime.RealTimeMessage;
import com.google.android.gms.games.multiplayer.realtime.RealTimeMessageReceivedListener;
import com.google.android.gms.games.multiplayer.realtime.Room;
import com.google.android.gms.games.multiplayer.realtime.RoomConfig;
import com.google.android.gms.games.multiplayer.realtime.RoomStatusUpdateListener;
import com.google.android.gms.games.multiplayer.realtime.RoomUpdateListener;
import com.google.android.gms.plus.Plus;
import com.google.example.games.basegameutils.BaseGameUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Button Clicker 2000. A minimalistic game showing the multiplayer features of
* the Google Play game services API. The objective of this game is clicking a
* button. Whoever clicks the button the most times within a 20 second interval
* wins. It's that simple. This game can be played with 2, 3 or 4 players. The
* code is organized in sections in order to make understanding as clear as
* possible. We start with the integration section where we show how the game
* is integrated with the Google Play game services API, then move on to
* game-specific UI and logic.
*
* INSTRUCTIONS: To run this sample, please set up
* a project in the Developer Console. Then, place your app ID on
* res/values/ids.xml. Also, change the package name to the package name you
* used to create the client ID in Developer Console. Make sure you sign the
* APK with the certificate whose fingerprint you entered in Developer Console
* when creating your Client Id.
*
* #author Bruno Oliveira (btco), 2013-04-26
*/
public class MainActivity extends Activity
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener, RealTimeMessageReceivedListener,
RoomStatusUpdateListener, RoomUpdateListener, OnInvitationReceivedListener {
/*
* API INTEGRATION SECTION. This section contains the code that integrates
* the game with the Google Play game services API.
*/
final static String TAG = "ButtonClicker2000";
// Request codes for the UIs that we show with startActivityForResult:
final static int RC_SELECT_PLAYERS = 10000;
final static int RC_INVITATION_INBOX = 10001;
final static int RC_WAITING_ROOM = 10002;
// Request code used to invoke sign in user interactions.
private static final int RC_SIGN_IN = 9001;
// Client used to interact with Google APIs.
private GoogleApiClient mGoogleApiClient;
// Are we currently resolving a connection failure?
private boolean mResolvingConnectionFailure = false;
// Has the user clicked the sign-in button?
private boolean mSignInClicked = false;
// Set to true to automatically start the sign in flow when the Activity starts.
// Set to false to require the user to click the button in order to sign in.
private boolean mAutoStartSignInFlow = true;
// Room ID where the currently active game is taking place; null if we're
// not playing.
String mRoomId = null;
// Are we playing in multiplayer mode?
boolean mMultiplayer = false;
// The participants in the currently active game
ArrayList<Participant> mParticipants = null;
// My participant ID in the currently active game
String mMyId = null;
// If non-null, this is the id of the invitation we received via the
// invitation listener
String mIncomingInvitationId = null;
// Message buffer for sending messages
byte[] mMsgBuf = new byte[2];
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the Google Api Client with access to Plus and Games
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API).addScope(Plus.SCOPE_PLUS_LOGIN)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
.build();
// set up a click listener for everything we care about
for (int id : CLICKABLES) {
findViewById(id).setOnClickListener(this);
}
}
#Override
public void onClick(View v) {
Intent intent;
switch (v.getId()) {
case R.id.button_single_player:
case R.id.button_single_player_2:
// play a single-player game
resetGameVars();
startGame(false);
break;
case R.id.button_sign_in:
// user wants to sign in
// Check to see the developer who's running this sample code read the instructions :-)
// NOTE: this check is here only because this is a sample! Don't include this
// check in your actual production app.
if (!BaseGameUtils.verifySampleSetup(this, R.string.app_id)) {
Log.w(TAG, "*** Warning: setup problems detected. Sign in may not work!");
}
// start the sign-in flow
Log.d(TAG, "Sign-in button clicked");
mSignInClicked = true;
mGoogleApiClient.connect();
break;
case R.id.button_sign_out:
// user wants to sign out
// sign out.
Log.d(TAG, "Sign-out button clicked");
mSignInClicked = false;
Games.signOut(mGoogleApiClient);
mGoogleApiClient.disconnect();
switchToScreen(R.id.screen_sign_in);
break;
case R.id.button_invite_players:
// show list of invitable players
intent = Games.RealTimeMultiplayer.getSelectOpponentsIntent(mGoogleApiClient, 1, 3);
switchToScreen(R.id.screen_wait);
startActivityForResult(intent, RC_SELECT_PLAYERS);
break;
case R.id.button_see_invitations:
// show list of pending invitations
intent = Games.Invitations.getInvitationInboxIntent(mGoogleApiClient);
switchToScreen(R.id.screen_wait);
startActivityForResult(intent, RC_INVITATION_INBOX);
break;
case R.id.button_accept_popup_invitation:
// user wants to accept the invitation shown on the invitation popup
// (the one we got through the OnInvitationReceivedListener).
acceptInviteToRoom(mIncomingInvitationId);
mIncomingInvitationId = null;
break;
case R.id.button_quick_game:
// user wants to play against a random opponent right now
startQuickGame();
break;
case R.id.button_click_me:
// (gameplay) user clicked the "click me" button
scoreOnePoint();
break;
}
}
void startQuickGame() {
// quick-start a game with 1 randomly selected opponent
final int MIN_OPPONENTS = 1, MAX_OPPONENTS = 1;
Bundle autoMatchCriteria = RoomConfig.createAutoMatchCriteria(MIN_OPPONENTS,
MAX_OPPONENTS, 0);
RoomConfig.Builder rtmConfigBuilder = RoomConfig.builder(this);
rtmConfigBuilder.setMessageReceivedListener(this);
rtmConfigBuilder.setRoomStatusUpdateListener(this);
rtmConfigBuilder.setAutoMatchCriteria(autoMatchCriteria);
switchToScreen(R.id.screen_wait);
keepScreenOn();
resetGameVars();
Games.RealTimeMultiplayer.create(mGoogleApiClient, rtmConfigBuilder.build());
}
#Override
public void onActivityResult(int requestCode, int responseCode,
Intent intent) {
super.onActivityResult(requestCode, responseCode, intent);
switch (requestCode) {
case RC_SELECT_PLAYERS:
// we got the result from the "select players" UI -- ready to create the room
handleSelectPlayersResult(responseCode, intent);
break;
case RC_INVITATION_INBOX:
// we got the result from the "select invitation" UI (invitation inbox). We're
// ready to accept the selected invitation:
handleInvitationInboxResult(responseCode, intent);
break;
case RC_WAITING_ROOM:
// we got the result from the "waiting room" UI.
if (responseCode == Activity.RESULT_OK) {
// ready to start playing
Log.d(TAG, "Starting game (waiting room returned OK).");
startGame(true);
} else if (responseCode == GamesActivityResultCodes.RESULT_LEFT_ROOM) {
// player indicated that they want to leave the room
leaveRoom();
} else if (responseCode == Activity.RESULT_CANCELED) {
// Dialog was cancelled (user pressed back key, for instance). In our game,
// this means leaving the room too. In more elaborate games, this could mean
// something else (like minimizing the waiting room UI).
leaveRoom();
}
break;
case RC_SIGN_IN:
Log.d(TAG, "onActivityResult with requestCode == RC_SIGN_IN, responseCode="
+ responseCode + ", intent=" + intent);
mSignInClicked = false;
mResolvingConnectionFailure = false;
if (responseCode == RESULT_OK) {
mGoogleApiClient.connect();
} else {
BaseGameUtils.showActivityResultError(this,requestCode,responseCode, R.string.signin_other_error);
}
break;
}
super.onActivityResult(requestCode, responseCode, intent);
}
// Handle the result of the "Select players UI" we launched when the user clicked the
// "Invite friends" button. We react by creating a room with those players.
private void handleSelectPlayersResult(int response, Intent data) {
if (response != Activity.RESULT_OK) {
Log.w(TAG, "*** select players UI cancelled, " + response);
switchToMainScreen();
return;
}
Log.d(TAG, "Select players UI succeeded.");
// get the invitee list
final ArrayList<String> invitees = data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);
Log.d(TAG, "Invitee count: " + invitees.size());
// get the automatch criteria
Bundle autoMatchCriteria = null;
int minAutoMatchPlayers = data.getIntExtra(Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
int maxAutoMatchPlayers = data.getIntExtra(Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
if (minAutoMatchPlayers > 0 || maxAutoMatchPlayers > 0) {
autoMatchCriteria = RoomConfig.createAutoMatchCriteria(
minAutoMatchPlayers, maxAutoMatchPlayers, 0);
Log.d(TAG, "Automatch criteria: " + autoMatchCriteria);
}
// create the room
Log.d(TAG, "Creating room...");
RoomConfig.Builder rtmConfigBuilder = RoomConfig.builder(this);
rtmConfigBuilder.addPlayersToInvite(invitees);
rtmConfigBuilder.setMessageReceivedListener(this);
rtmConfigBuilder.setRoomStatusUpdateListener(this);
if (autoMatchCriteria != null) {
rtmConfigBuilder.setAutoMatchCriteria(autoMatchCriteria);
}
switchToScreen(R.id.screen_wait);
keepScreenOn();
resetGameVars();
Games.RealTimeMultiplayer.create(mGoogleApiClient, rtmConfigBuilder.build());
Log.d(TAG, "Room created, waiting for it to be ready...");
}
// Handle the result of the invitation inbox UI, where the player can pick an invitation
// to accept. We react by accepting the selected invitation, if any.
private void handleInvitationInboxResult(int response, Intent data) {
if (response != Activity.RESULT_OK) {
Log.w(TAG, "*** invitation inbox UI cancelled, " + response);
switchToMainScreen();
return;
}
Log.d(TAG, "Invitation inbox UI succeeded.");
Invitation inv = data.getExtras().getParcelable(Multiplayer.EXTRA_INVITATION);
// accept invitation
acceptInviteToRoom(inv.getInvitationId());
}
// Accept the given invitation.
void acceptInviteToRoom(String invId) {
// accept the invitation
Log.d(TAG, "Accepting invitation: " + invId);
RoomConfig.Builder roomConfigBuilder = RoomConfig.builder(this);
roomConfigBuilder.setInvitationIdToAccept(invId)
.setMessageReceivedListener(this)
.setRoomStatusUpdateListener(this);
switchToScreen(R.id.screen_wait);
keepScreenOn();
resetGameVars();
Games.RealTimeMultiplayer.join(mGoogleApiClient, roomConfigBuilder.build());
}
// Activity is going to the background. We have to leave the current room.
#Override
public void onStop() {
Log.d(TAG, "**** got onStop");
// if we're in a room, leave it.
leaveRoom();
// stop trying to keep the screen on
stopKeepingScreenOn();
if (mGoogleApiClient == null || !mGoogleApiClient.isConnected()){
switchToScreen(R.id.screen_sign_in);
}
else {
switchToScreen(R.id.screen_wait);
}
super.onStop();
}
// Activity just got to the foreground. We switch to the wait screen because we will now
// go through the sign-in flow (remember that, yes, every time the Activity comes back to the
// foreground we go through the sign-in flow -- but if the user is already authenticated,
// this flow simply succeeds and is imperceptible).
#Override
public void onStart() {
switchToScreen(R.id.screen_wait);
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Log.w(TAG,
"GameHelper: client was already connected on onStart()");
} else {
Log.d(TAG,"Connecting client.");
mGoogleApiClient.connect();
}
super.onStart();
}
// Handle back key to make sure we cleanly leave a game if we are in the middle of one
#Override
public boolean onKeyDown(int keyCode, KeyEvent e) {
if (keyCode == KeyEvent.KEYCODE_BACK && mCurScreen == R.id.screen_game) {
leaveRoom();
return true;
}
return super.onKeyDown(keyCode, e);
}
// Leave the room.
void leaveRoom() {
Log.d(TAG, "Leaving room.");
mSecondsLeft = 0;
stopKeepingScreenOn();
if (mRoomId != null) {
Games.RealTimeMultiplayer.leave(mGoogleApiClient, this, mRoomId);
mRoomId = null;
switchToScreen(R.id.screen_wait);
} else {
switchToMainScreen();
}
}
// Show the waiting room UI to track the progress of other players as they enter the
// room and get connected.
void showWaitingRoom(Room room) {
// minimum number of players required for our game
// For simplicity, we require everyone to join the game before we start it
// (this is signaled by Integer.MAX_VALUE).
final int MIN_PLAYERS = Integer.MAX_VALUE;
Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(mGoogleApiClient, room, MIN_PLAYERS);
// show waiting room UI
startActivityForResult(i, RC_WAITING_ROOM);
}
// Called when we get an invitation to play a game. We react by showing that to the user.
#Override
public void onInvitationReceived(Invitation invitation) {
// We got an invitation to play a game! So, store it in
// mIncomingInvitationId
// and show the popup on the screen.
mIncomingInvitationId = invitation.getInvitationId();
((TextView) findViewById(R.id.incoming_invitation_text)).setText(
invitation.getInviter().getDisplayName() + " " +
getString(R.string.is_inviting_you));
switchToScreen(mCurScreen); // This will show the invitation popup
}
#Override
public void onInvitationRemoved(String invitationId) {
if (mIncomingInvitationId.equals(invitationId)&&mIncomingInvitationId!=null) {
mIncomingInvitationId = null;
switchToScreen(mCurScreen); // This will hide the invitation popup
}
}
/*
* CALLBACKS SECTION. This section shows how we implement the several games
* API callbacks.
*/
#Override
public void onConnected(Bundle connectionHint) {
Log.d(TAG, "onConnected() called. Sign in successful!");
Log.d(TAG, "Sign-in succeeded.");
// register listener so we are notified if we receive an invitation to play
// while we are in the game
Games.Invitations.registerInvitationListener(mGoogleApiClient, this);
if (connectionHint != null) {
Log.d(TAG, "onConnected: connection hint provided. Checking for invite.");
Invitation inv = connectionHint
.getParcelable(Multiplayer.EXTRA_INVITATION);
if (inv != null && inv.getInvitationId() != null) {
// retrieve and cache the invitation ID
Log.d(TAG,"onConnected: connection hint has a room invite!");
acceptInviteToRoom(inv.getInvitationId());
return;
}
}
switchToMainScreen();
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended() called. Trying to reconnect.");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed() called, result: " + connectionResult);
if (mResolvingConnectionFailure) {
Log.d(TAG, "onConnectionFailed() ignoring connection failure; already resolving.");
return;
}
if (mSignInClicked || mAutoStartSignInFlow) {
mAutoStartSignInFlow = false;
mSignInClicked = false;
mResolvingConnectionFailure = BaseGameUtils.resolveConnectionFailure(this, mGoogleApiClient,
connectionResult, RC_SIGN_IN, getString(R.string.signin_other_error));
}
switchToScreen(R.id.screen_sign_in);
}
// Called when we are connected to the room. We're not ready to play yet! (maybe not everybody
// is connected yet).
#Override
public void onConnectedToRoom(Room room) {
Log.d(TAG, "onConnectedToRoom.");
//get participants and my ID:
mParticipants = room.getParticipants();
mMyId = room.getParticipantId(Games.Players.getCurrentPlayerId(mGoogleApiClient));
// save room ID if its not initialized in onRoomCreated() so we can leave cleanly before the game starts.
if(mRoomId==null)
mRoomId = room.getRoomId();
// print out the list of participants (for debug purposes)
Log.d(TAG, "Room ID: " + mRoomId);
Log.d(TAG, "My ID " + mMyId);
Log.d(TAG, "<< CONNECTED TO ROOM>>");
}
// Called when we've successfully left the room (this happens a result of voluntarily leaving
// via a call to leaveRoom(). If we get disconnected, we get onDisconnectedFromRoom()).
#Override
public void onLeftRoom(int statusCode, String roomId) {
// we have left the room; return to main screen.
Log.d(TAG, "onLeftRoom, code " + statusCode);
switchToMainScreen();
}
// Called when we get disconnected from the room. We return to the main screen.
#Override
public void onDisconnectedFromRoom(Room room) {
mRoomId = null;
showGameError();
}
// Show error message about game being cancelled and return to main screen.
void showGameError() {
BaseGameUtils.makeSimpleDialog(this, getString(R.string.game_problem));
switchToMainScreen();
}
// Called when room has been created
#Override
public void onRoomCreated(int statusCode, Room room) {
Log.d(TAG, "onRoomCreated(" + statusCode + ", " + room + ")");
if (statusCode != GamesStatusCodes.STATUS_OK) {
Log.e(TAG, "*** Error: onRoomCreated, status " + statusCode);
showGameError();
return;
}
// save room ID so we can leave cleanly before the game starts.
mRoomId = room.getRoomId();
// show the waiting room UI
showWaitingRoom(room);
}
// Called when room is fully connected.
#Override
public void onRoomConnected(int statusCode, Room room) {
Log.d(TAG, "onRoomConnected(" + statusCode + ", " + room + ")");
if (statusCode != GamesStatusCodes.STATUS_OK) {
Log.e(TAG, "*** Error: onRoomConnected, status " + statusCode);
showGameError();
return;
}
updateRoom(room);
}
#Override
public void onJoinedRoom(int statusCode, Room room) {
Log.d(TAG, "onJoinedRoom(" + statusCode + ", " + room + ")");
if (statusCode != GamesStatusCodes.STATUS_OK) {
Log.e(TAG, "*** Error: onRoomConnected, status " + statusCode);
showGameError();
return;
}
// show the waiting room UI
showWaitingRoom(room);
}
// We treat most of the room update callbacks in the same way: we update our list of
// participants and update the display. In a real game we would also have to check if that
// change requires some action like removing the corresponding player avatar from the screen,
// etc.
#Override
public void onPeerDeclined(Room room, List<String> arg1) {
updateRoom(room);
}
#Override
public void onPeerInvitedToRoom(Room room, List<String> arg1) {
updateRoom(room);
}
#Override
public void onP2PDisconnected(String participant) {
}
#Override
public void onP2PConnected(String participant) {
}
#Override
public void onPeerJoined(Room room, List<String> arg1) {
updateRoom(room);
}
#Override
public void onPeerLeft(Room room, List<String> peersWhoLeft) {
updateRoom(room);
}
#Override
public void onRoomAutoMatching(Room room) {
updateRoom(room);
}
#Override
public void onRoomConnecting(Room room) {
updateRoom(room);
}
#Override
public void onPeersConnected(Room room, List<String> peers) {
updateRoom(room);
}
#Override
public void onPeersDisconnected(Room room, List<String> peers) {
updateRoom(room);
}
void updateRoom(Room room) {
if (room != null) {
mParticipants = room.getParticipants();
}
if (mParticipants != null) {
updatePeerScoresDisplay();
}
}
My current interface code
package com.macrohard.game;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.google.example.games.basegameutils.GameHelper;
import com.macrohard.game.SomeGame;
import com.google.android.gms.games.Games;
import com.google.example.games.basegameutils.GameHelper;
import com.google.example.games.basegameutils.GameHelper.GameHelperListener;
import com.macrohard.game.ActionResolver;
import com.macrohard.game.MainMenu;
public class AndroidLauncher extends AndroidApplication implements ActionResolver {
private GameHelper gameHelper;
private final static int requestCode = 1;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
gameHelper = new GameHelper(this, GameHelper.CLIENT_GAMES);
gameHelper.enableDebugLog(false);
GameHelper.GameHelperListener gameHelperListener = new GameHelper.GameHelperListener()
{
#Override
public void onSignInFailed(){ }
#Override
public void onSignInSucceeded(){ }
};
gameHelper.setup(gameHelperListener);
//initialize(new SomeGame(), config);
initialize(new MainMenu(this), config);
}
//...
#Override
protected void onStart()
{
super.onStart();
gameHelper.onStart(this);
}
#Override
protected void onStop()
{
super.onStop();
gameHelper.onStop();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
gameHelper.onActivityResult(requestCode, resultCode, data);
}
#Override
public void signIn()
{
try
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
gameHelper.beginUserInitiatedSignIn();
}
});
}
catch (Exception e)
{
Gdx.app.log("MainActivity", "Log in failed: " + e.getMessage() + ".");
}
}
#Override
public void signOut()
{
try
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
gameHelper.signOut();
}
});
}
catch (Exception e)
{
Gdx.app.log("MainActivity", "Log out failed: " + e.getMessage() + ".");
}
}
#Override
public void rateGame()
{
String str = "Your PlayStore Link";
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(str)));
}
#Override
public void unlockAchievement()
{
}
#Override
public void submitScore(int highScore)
{
}
#Override
public void showAchievement()
{
}
#Override
public void showScore()
{
}
#Override
public boolean isSignedIn()
{
return gameHelper.isSignedIn();
}
}
LibGDX separates platform specific codes into different modules for providing multiplatform by using the same code base (Core project). So you should implement android specific stuff in android project as you show in the code example.
You can not use any class in the package "com.google.android" in your core project. Because Google Play Services depends on android specific resources. You should read the document about platform specific code
https://github.com/libgdx/libgdx/wiki/Interfacing-with-platform-specific-code
So, you should prepare an interface which defines your methods you want to use and implement separately for each of platforms that you are planning to support in your project.
It seems that we are both trying to implement a real-time multiplayer using the Google Play Games Services with the very specific architecture of any libGDX project. I suggest you to check out this GitHub repository : GarrapuchoFootball. Tell me if it helps you.

CameraDevice failing to create session [Camera2]

I'm trying to use the Camera2 API to stream camera data to a SurfaceView. I'm following this guide: Camera2 guide
I cannot get past step 5
MainActivity.java::onCreate()
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView)findViewById(R.id.surface);
manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
MainActivity.java::onClick()
for (String id : manager.getCameraIdList()) {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
Integer direction = characteristics.get(CameraCharacteristics.LENS_FACING);
if (direction != null && direction == CameraCharacteristics.LENS_FACING_BACK) {
if (checkCallingOrSelfPermission("android.permission.CAMERA") == PackageManager.PERMISSION_GRANTED)
manager.openCamera(id, new StateCallback(), null);
break;
}
}
MainActivity.java.StateCallback::onOpened(CameraDevice camera)
List<Surface> surfaces = new LinkedList<>();
surfaces.add(surfaceView.getHolder().getSurface());
CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(surfaces.get(0));
camera.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
Log.i(TAG, "Configured");
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.e(TAG, "Configured failed"); // Ends up in this function :(
}
}, null);
The program ends up in the onConfigureFailed() function. I don't know what could be the error, and I don't know how to check what is.
My guess would be that I'm missing something in the CaptureRequest, but I have no idea what.
I'm running on a Samsung Galaxy S4.
add to onConfigured:
if (null == cameraDevice) {
Log.e(TAG, "updatePreview error, return");
return;
}
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Override onConfigureFailed() like this:
#Override
public void onConfigureFailed(CameraCaptureSession session) {
ImageReader mReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1);
takePicture() // function to get image
createCameraPreview(); // function to set camera Preview on screen
}
Call createCameraPreview function to restart the camera, otherwise, it will stay stuck.
You can change the ImageReader with new values
ImageReader mReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1);
And call the takePicture() function again so that user don't have to click again to capture image.

Android Speech Recogntion won't work in a separate class

I'm a beginner in Android development. What I'm trying to create is an app the speaks to you then waits for your answer so its kind of text to speech works ,then it activates speech recognition and with my code the text to speech works then it calls speech recognition.Then an erro msg is shown ,the catch block is executed.
The problem is that I have to add Speech Recognition in a separate class, then add an Object of it in the Adapter not Main Activity. Speech Recognition won't work and since all tutorials for speech recognition for Android are adding the code in Main Activity and I'm doing it as class called in the adapter is the problem ?
UPDATE startActivityForResult() method is not working
Here is the code for SpeechRecogntion class
public class SpeechRecog extends Activity {
private static final int VOICE_RECOGNITION_REQUEST_CODE = 1001;
String textResult ;
public void Start (Intent i , Context c){
i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");
i.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Are You Done , yet? ");
try{
startActivityForResult(i,VOICE_RECOGNITION_REQUEST_CODE);
} catch(Exception e) {
Toast.makeText(c, "SpeechRecogntion is not avalible on your device ", Toast.LENGTH_LONG).show();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ((requestCode == VOICE_RECOGNITION_REQUEST_CODE)&& (resultCode== RESULT_OK)) {
textResult= data.getStringExtra(RecognizerIntent.EXTRA_RESULTS);
if (checkResult())
Toast.makeText(getApplicationContext(), "You are done ", Toast.LENGTH_LONG).show();
else
Toast.makeText(getApplicationContext(), "You are not done ", Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
private boolean checkResult() {
if (textResult.equals("done")||(textResult.equals("yes")))
return true ;
return false;
}
}
And Here is the object of it in the Adapter class
private SpeechRecog mySP;
private Intent mySpIntetn ;
public ListAdapterClass(Context context) {
mytts = new TxtToSpeechClass(context);
mySP = new SpeechRecog();
}
And Here is where my problem relies ,the on clicklistener inside the Adapter class
Lh.btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
if (Lh.btn.getText().equals("Play"))
{
Lh.btn.setText("Pause"); //change the btn status so user know how to stop it
List<Items> hResults=db.getAllItems(Lh.idList + 1);
for (int i = 0; i < hResults.size(); i++)
{
Items item = hResults.get(i);
String s = item.getItemname();
mytts.Talk(s,1);
mySP.Start(mySpIntetn , context ); //the code in here wont work is there something I'm missing here
Toast.makeText(context,s, Toast.LENGTH_SHORT).show();
}
mytts.Talk("Congrats ",1);// 1 means Queue_add
} else {
Lh.btn.setText("Play");
mytts.Talk("See you later", 0); // 0 means Queue_Flush
}
}
);
mySpIntetn is private. Try to change it to public in the Adapter class.

Categories