I am new to google cardboard and trying to implement a very simple demo.
I have tried with VrVideowidget & panowidget separately but failed to implement it with GvrView. My work with code and output is given below.
I have added a GvrView which provide split screen automatically, after that i want to add same image/video into each screen so that it can appear well on google cardboard . The view I am adding via addView() appear single instead of two on both screen. I have added it on onDrawEye(). Please help me to reslove.
My final aim is to create a very basic demo of image/video on Google Cardboard with required feature.
MainActivity.java
public class MainActivity extends GvrActivity implements GvrView.StereoRenderer {
GvrView gvrView;
private ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
imageView = new ImageView(this);
gvrView = new GvrView(this);
gvrView.setRenderer(this);
setContentView(gvrView);
}
#Override
public void onDrawEye(Eye eye) {
imageView.setImageResource(R.drawable.ic_launcher);
// gvrView.addView(imageView);
gvrView.addView(imageView,400,400);
}
}
Use VrPanoramaView instead, code sample is as follow:
add panowidget lib in your project
import com.google.vr.sdk.widgets.pano.VrPanoramaView;
VrPanoramaView panoWidgetView = (VrPanoramaView) findViewById(R.id.pano_view);
panoWidgetView.loadImageFromBitmap(img,null);
panoWidgetView.resumeRendering();
I am not an expert but my understanding is that you use onDrawEye to render images specific to the individual eyes, while you use onNewFrame() for non-eye specific rendering.
So moving
imageView.setImageResource(R.drawable.ic_launcher);
// gvrView.addView(imageView);
gvrView.addView(imageView,400,400);
to onNewFrame() should be enough.
Related
I am trying to bring a VideoView from the back to the front, but nothing worked. In the following, I will first present the code, then I will present what I attempted, and hopefully someone will be able to solve my problem:
It is a simplified repro for Android app written using Xamarin.
Without further ado, here is my code:
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Media;
using System;
namespace Experiment
{
public class Listener : Java.Lang.Object, MediaPlayer.IOnCompletionListener
{
private Action action;
public Listener(Action action)
{
this.action = action;
}
public void OnCompletion(MediaPlayer unused)
{
this.action();
}
}
[Activity(Label = "Experiment", MainLauncher = true, Icon = "#mipmap/icon")]
public class MainActivity : Activity
{
private VideoView foreView;
private VideoView backView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
this.foreView = this.FindViewById<VideoView>(Resource.Id.foreView);
this.backView = this.FindViewById<VideoView>(Resource.Id.backView);
this.foreView.SetVideoURI(Android.Net.Uri.Parse("..."));
this.foreView.Start();
this.foreView.SetOnCompletionListener(new Listener(this.OnForeViewCompleted1));
this.backView.SetVideoURI(Android.Net.Uri.Parse("..."));
this.backView.SetOnCompletionListener(new Listener(this.OnBackViewCompleted1));
}
private void OnForeViewCompleted1()
{
this.backView.Start();
this.foreView.SetVideoURI(Android.Net.Uri.Parse("..."));
this.backView.BringToFront();
}
private void OnBackViewCompleted1()
{
this.foreView.SetOnCompletionListener(null);
this.foreView.Start();
this.foreView.BringToFront();
}
}
}
For privacy reason - the actual video URL are replaced with '...', any URL that can serve a mp4 file will work.
And here is the layout associated with the activity
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<VideoView
android:id="#+id/backView"
android:layout_width="200px"
android:layout_height="200px"
android:layout_marginTop="0px"
android:layout_marginLeft="0px" />
<VideoView
android:id="#+id/foreView"
android:layout_width="200px"
android:layout_height="200px"
android:layout_marginTop="0px"
android:layout_marginLeft="50px" />
</RelativeLayout>
I intended to have the foreView to completely occlude the backView, for this example, however, I deliberately shift the foreView by 50px to the right to show the effect.
The full, runnable Xamarin solution can be found in my GitHub repository
When we run the program, it will first play a video on the foreView, on completion, it will play a video on the backView, on completion, it attempts to bring the foreView up again and play the foreView, but it will not show up to occlude backView, and instead backView occluded the frontView, that something I need to solve.
The above described the problem, here is what I attempted:
foreView.Invalidate() does not work.
foreView.RequestLayout() does not work.
foreView.Parent.RequestLayout() does not work.
A pull request that fix the problem would be awesome, thanks a lot in advance!
I have tried some way to bring the VideoView to the front, but it not works as you said.
But you can find the VideoView Z-Order level is dependent on the the order of addition.
So as a workaround I changed the order of the addition of the two VideoView:
private void OnForeViewCompleted1()
{
//backView.BringToFront();
//backView.SetZOrderOnTop(true);
//myfatherLayout.UpdateViewLayout(backView, backView.LayoutParameters);
myfatherLayout.RemoveView(foreView);
myfatherLayout.AddView(foreView);
img1.BringToFront();
this.backView.Start();
}
private void OnBackViewCompleted1()
{
//foreView.BringToFront();
// foreView.SetZOrderOnTop(true);
//myfatherLayout.UpdateViewLayout(foreView, foreView.LayoutParameters);
myfatherLayout.RemoveView(backView);
myfatherLayout.AddView(backView);
img2.BringToFront();
this.foreView.Start();
}
the myfatherLayout is the video view container(your RelativeLayout).
You can see the video view will show as your requirement:
I'm brand new to Android development, so I'm probably doing something stupid. Any ideas why this code shouldn't work?
It compiles and runs, but doesn't actually successfully set the image (which is previously set to a gray background).
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_activity);
Button getImageButton = (Button) (findViewById(R.id.btnGetImage));
getImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ImageView myImageView = (ImageView) (findViewById(R.id.myImageView));
Picasso.with(v.getContext()).load("https://www.example.com/someimage").into(myImageView);
}
});
}
alter you code this way
Picasso.with(YOUR_ACTIVITY_NAME.this).load("https://www.example.com/someimage").into(myImageView);
Here v.getContext() is not related to the main context, so it won't help you, we need to pass context of current activity
Please try this and let me know.
#Override
protected void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_activity);
Button getImageButton = (Button) (findViewById(R.id.btnGetImage));
ImageView myImageView = (ImageView) (findViewById(R.id.myImageView));
getImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Picasso.with(YourActivityName.this).load("https://www.example.com/someimage").into(myImageView);
}
});
}
Ding ding here is my answer
I am sure that you add the dependency
compile 'com.squareup.picasso:picasso:2.5.2'
and used the right url
Picasso.with(v.getContext()).load("http://i.imgur.com/DvpvklR.png").into(imageView);
I am telling you where you went wrong !!
Magic : Have you added the internet permission ? It needs to be in your manifest
<uses-permission android:name="android.permission.INTERNET" />
Rather than that your code is just fine
But i recommend you to use getApplicationContext()
copying from my comment
Picasso is a library and not an application. While creating
Picasso instance if you'll not pass context, then how do you think
it will get the application context from ? For it to work it requires
context , and it definitely needs to be provided by the application
using this library.It also prevents leaking an Activity (if that's
what you pass ,some of below answers have used ) by switching to the
application context. use getApplicationContext()
And for the people who randomly put an answer here read this as well
View.getContext(): Returns the context the view is currently running in. Usually the currently active Activity.
Activity.getApplicationContext(): Returns the context for the entire application (the process all the Activities are running inside
of). Use this instead of the current Activity context if you need a
context tied to the lifecycle of the entire application, not just the
current Activity.
ContextWrapper.getBaseContext(): If you need access to a Context from within another context, you use a ContextWrapper. The
Context referred to from inside that ContextWrapper is accessed via
getBaseContext().
so any way he is accessing the currant activity context.
Cheers!
step 1 In Menifest check Internet Connection
<uses-permission android:name="android.permission.INTERNET" />
step 2 compile "com.squareup.picasso:picasso:2.4.0"
step 3 Image url is not showing any image in browser paste your url in browser and if you get image then you can set that image to imagview
step 4 check url is working or not there is not .png or .jpg extension for imagfile
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_activity);
Button getImageButton = (Button) (findViewById(R.id.btnGetImage));
getImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Initializing the ImageView
imageView = (ImageView) findViewById(R.id.imageView);
//Loading Image from URL
Picasso.with(this)
.load("https://www.example.com/someimage")
.placeholder(R.drawable.placeholder) // optional
.error(R.drawable.error) // optional
.resize(400,400) // optional
.into(imageView);
}
});
}
My application keeps crashing every time I try to use the PhotoViewAttacher on my application of the PhotoView library. I'm using ION to display images and trying to get the PhotoView library to allow me to zoom into them. My code currently is:
public class massiveImageView extends Activity {
ImageView mImageView;
PhotoViewAttacher mAttacher;
Drawable drawable;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.massive_image_view);
// Any implementation of ImageView can be used!
mImageView = (ImageView) findViewById(R.id.imageViewMassivePage);
Ion.with(this).load("https://pbs.twimg.com/profile_images/522909800191901697/FHCGSQg0.png").withBitmap().asBitmap()
.setCallback(new FutureCallback<Bitmap>() {
#Override
public void onCompleted(Exception e, Bitmap result) {
// do something with your bitmap
drawable=new BitmapDrawable(result);
mImageView.setImageDrawable(drawable);
}
});
mAttacher = new PhotoViewAttacher(mImageView);
}
}
And the error I'm getting is at this line:
mAttacher = new PhotoViewAttacher(mImageView);
Saying:
java.lang.NoClassDefFoundError: uk.co.senab.photoview.PhotoViewAttacher
Any help would be hugely appreciated.
I still don't quite understand why it doesn't work, but I was able to find an answer, where instead of adding the dependency of the library, I just found the jar file online and added that instead, now everything is working perfect.
Library Link
I've read so many tutorials and Google documentation on how to implement Google Play Services into my Game, all in how are implemented solely in the Android project. However, LIBGDX has several other packages, namely the core project, where the core Game engine goes.
What I would I like to ask help for is:
For example, if in my core project, the player finishes the "match" and gets a score, and I would like to relay that score to Google Play Services, how do I call to the MainActivity to handle the "score"?
Let's say you have a "desktop" and "android" version of your game. Create an interface in your "core" project that handles all these Google Play Services events. For instance:
public interface GameEventListener {
// Called when a score is to be submitted
pubic void submitScore(int score);
}
Your game instantiation should now receive an implementation of this interface:
public class MyGame extends Game {
public MyGame(GameEventListener listener) {
// Keep the reference to this listener, you'll be calling it from your game
}
}
Then, you have to make your DesktopLauncher and your AndroidLauncher implement this interface and pass themselves as an argument when you create your game:
DesktopLauncher:
public class DesktopLauncher implements GameEventListener {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.width = Constants.APP_WIDTH;
config.height = Constants.APP_HEIGHT;
new LwjglApplication(new MyGame(new GameEventListener() {
#Override
public void submitScore(int score) {
// Handle the event as you wish for your desktop version
Gdx.app.log("DesktopLauncher", "submitScore");
}
}), config);
}
}
AndroidLauncher (MainActivity):
public class AndroidLauncher extends AndroidApplication implements GameEventListener {
// ...
#Override
public void onCreate(Bundle savedInstanceState) {
// ... example code not intended to work, take only what you need
// Create the layout
RelativeLayout layout = new RelativeLayout(this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
// Game view. Pass the activity as the argument to your game class
View gameView = initializeForView(new MyGame(this), config);
layout.addView(gameView);
setContentView(layout);
}
#Override
public void submitScore(int score) {
// Submit your score to Google Play Services
gameServicesClient.submitScore(score);
}
}
Now, whenever your "match" is over, send the message to your listener and it will call your MainActivity's implementation of "submitScore" if you are running the Android version of the game:
private void onMatchOver() {
listener.submitScore(match.getFinalScore());
}
Hope it helps.
The activities of my game extends BaseGameActivity as stated in guidelines from Google Play Game Services. The problem is that when my activities are launched, a dialog for login in Google Play Services is displayed on the screen. I want to avoid it. I want to put a button on the screen for the login.
¿How can be avoided the auto prompt of the login dialog? I can't find anything in the guidelines
https://developers.google.com/games/services/training/signin?hl=es
https://developers.google.com/games/services/checklist?hl=es#improving_the_sign_in_experience_for_games
Instead of extended BaseGameActivity, I recommend you import the BaseGameUtils library and use the GameHelper class. Eg..
public class MainActivity extends Activity {
private GameHelper mHelper;
private GameHelperListener listener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHelper = new GameHelper(this, GameHelper.CLIENT_ALL);
listener = new GameHelper.GameHelperListener() {
#Override
public void onSignInSucceeded() {
}
#Override
public void onSignInFailed() {
}
};
mHelper.setup(listener);
}
}
Check out this link. You can control when google services asks to log in by controllign when setup is called
As Ogen mentions in his answer, using BaseGameUtils is quite useful. It does require some extra work from your part, which might be worth it but it might also not be.
If you want to keep using BaseGameActivity, then you can add the following
mHelper.mConnectOnStart = false;
to onCreate() of your activity that extends BaseGameActivity. This will prevent auto sign-in.