Android overlaying GLSurfaceView with camera's SurfaceView - java

I'm looking to put an openGL model (via GLSurfaceView) on top of the camera, which has its own SurfaceView. Surely this must be possible, apps like Layar do this.
Here is what I am trying:
public class MainActivity extends Activity {
private CameraSurfaceView mCameraSurfaceView;
private GLSurfaceView mCubeGLSurfaceView;
private FrameLayout mFrameLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mFrameLayout = new FrameLayout(this);
mCameraSurfaceView = new CameraSurfaceView(this);
mCubeGLSurfaceView = new GLSurfaceView(this);
mCubeGLSurfaceView.setRenderer(new CubeRenderer());
//mCubeGLSurfaceView.setZOrderMediaOverlay(true);
mFrameLayout.addView(mCameraSurfaceView);
mFrameLayout.addView(mCubeGLSurfaceView);
setContentView(mFrameLayout);
}
}
Right now: just the camera shows up. I've read online about the SetZOrderMediaOverlay attribute for GLSurfaceView; setting it TRUE in the above code has the 3D cube show up with a black background (i.e. no camera preview shown).
References:
Here is the Cube OpenGL code I'm using: http://intransitione.com/blog/create-a-spinning-cube-with-opengl-es-and-android/
Here is the CameraSurfaceView code:
https://github.com/davefp/android-camera-api-example/blob/master/src/com/example/cameraexample/CameraSurfaceView.java
Other tests I've tried: changing the addView order of the respective surfaceviews doesn't help; it only shows the camera (I read somewhere changing the addView order may help).
Thanks for any help!

Since you state that only the camera preview is currently visible it may be that you have not ordered your views correctly. This is what I have done to create what you desire.
In the Activity create
instance of MySurfaceView derived from GLSurfaceView
instance of MyCameraPreview derived from SurfaceView
in my Activity's onCreate method I do the following:
mySurfaceView = new MySurfaceView(this);
addContentView(mySurfaceView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
myCameraPreview = new MyCameraPreview(this, myCamera);
addContentView(myCameraPreview, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
Please note that using this method you do not use a layout xml.
This will create your two views on top of each other with the camera preview in the background.
Now you need to get the MySurfaceView to draw a transparent background so the camera preview will show behind the objects you render. If you are using OpenGL ES 2.0 add this to the constructor of your MySurfaceView class.
setEGLContextClientVersion(2);
setEGLConfigChooser(8,8,8,8,16,0);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
I just worked through this process myself so I may have missed some details.

Related

How to display a simple ImageButton on a customly created view?

I've been browsing the entire internet, but I could not find any answer to this question. I want to create a background, some image buttons, along with a bunch of moving graphics (circles). Since I do not know how to overwrite a xml layout with moving graphics, I chose to customly create my view, draw the background, the imageButtons and the circles (2D graphics).
public class GameView extends View implements UtilConstants
since I extended the View class, I had to call the super class constructor in my constructor
GameView(Context context) {
super(context);
this.context = context;
this.paint = new Paint();
}
and to implement the onDraw method, which acts like the java paintComponent
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); // necessary for some reason
setGridBackground(); // sets the background
paint.setColor(Color.parseColor("#FF0000"));
canvas.drawCircle(this.x += 10, 300, 20, paint); //moves my graphics (ball) within the screen
drawScoreInLeftUpperCorner(canvas, 20); // paints a string text on the screen
setAbilitiesImages(); // places some imageButtons
try {
Thread.sleep(THREAD_REFRESH_RATE_MS);
} catch (InterruptedException ex) {
System.out.println(ex);
}
invalidate();
}
Now, to get to my problem:
I do not know how to set those ImageButtons !!! I am trying
private void setAbilititesImages() {
ImageButton imageButton = new ImageButton(this.context); // is this ok to put the argument this.context??
imageButton.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
imageButton.setImageResource(R.drawable.monster); // set my resource
RelativeLayout relativeLayout = findViewById(R.id.in_game_layout); // what is the purpose of this???
if (relativeLayout != null) { // it never enters this if, relativeLayout is always null
relativeLayout.addView(imageButton);
}
}
Aaaaand the image button never shows up...why is it necessary to use Relative/Linear layouts? That R.id.in_game_layout I created is just an empty RelativeLayout xml. Can't I just use something like
imageButton.setImageResource(R.drawable.monster); // set my resource
imageButton.setBounds(.....);
(View)this.add(imageButton); ???
ImageButton requires a parent view to be hosted in it. The parent View can be a RelativeLayout, a linearlayout or a ConstraintLayout.
In your case, the instance relativeLayout is always null because you not specify the view parent in which you do findViewById.
You should make something like :
RelativeLayout relativeLayout = view.findViewById(R.id.in_game_layout);
You need to add layout param to your parent Relative layout also to display your Image button appropriately.
Example
RelativeLayout relativeLayout = findViewById(R.id.relativeLayout);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ImageButton imageButton = new ImageButton(this);
imageButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher_background,null));
relativeLayout.addView(imageButton,params);

Android: How to add a layer on top no matter how many activities started?

I want to play a gif animation and this view will move on the screen every second, but if I start an activity I need to add this view again and the position will change.
See the attached image below. I need to stick this over every view. Any way to do it?
Create one BaseActivity for all activities in your app to show Overlay View or Layout.
you can inherit BaseActivity on other Activity
You can add gif supported views or layouts
for example i added overlay_layout in my showOverlay method.
you can call showOverlay method where ever you want to show and you can remove with removeOverlay with conditions.
Please note that showOverlay and removeOverlay should be in BaseActivity
void showOverlay(){
LayoutInflater inflater = activity.getLayoutInflater();
layout = inflater.inflate(R.layout.overlay_layout, null);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.gravity = Gravity.BOTTOM;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.type = WindowManager.LayoutParams.TYPE_APPLICATION;
final WindowManager mWindowManager = (WindowManager);
activity.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
mWindowManager.addView(layout, params);
}
void removeOverlay(){
windowManager.removeView(view);
}
set this view into WindowManager and it will always show on top

The java backend code to the xml code

I have a basic android application that has several pages accessible from the home page, anyways I change the layout by doing
public void main(View view) {
setContentView(R.layout.main);
}
and changing the layout to the main game page. Now I want to add characters to it and so I added protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint green = new Paint();
green.setColor(Color.GREEN);
Rect theRect = new Rect();
theRect.set(0,0,canvas.getWidth()/2,canvas.getHeight()/2);
canvas.drawRect(theRect, green);
}
but I only want to call it for the "main" or the scene/layout that the game is played in. It appears to not be called at all and that may be due to the fact that I do not completely understand the relationship between the xml and multiple java files and functions. I'm new to android so this may be a stupid question, I just couldn't find anything with multiple web searches, with no luck.
You can add your game view into activity class:
Class GameView extends View/SurfaceView
{
//-- contains onDraw() method
}
To add this game view into your activity, you have to do
get reference of layout in whioch you want to add this gameview.
eg: LinearLayout layout=(LinearLayout) findViewById(R.id.linearlayout);
Add GameView into this layout
eg: layout.addView(new GameView());
For more detail, you can get reference from http://www.edu4java.com/en/androidgame/androidgame3.html
Hope this helps you

setContentView() Crashes when used with GLSurfaceView

I have been trying to make my first android app. I am stuck with this strange problem. There are lot of people who had faced same problem (like here, here, here and lots of other places) in past but none of the solutions seems to work for me.
My problem is if I set layout file like setContentView(R.layout.MainActivity) application crashes on this function but if I directly set GLSurfaceView as content view application works just fine. I want to have a ListView and GLSurfaceView on same screen thats why I am trying to add it in XML.
Here is my layout file
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.camerafilters.CameraGLSurfaceView
android:id="#+id/CameraGLSurfaceView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<!-- <ListView
android:id="#+id/ShaderList"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
-->
</LinearLayout>
Here is relevant portion from main activity. Note that CameraGLSurfaceView is an inner class.
public class CameraMainActivity extends Activity implements
SurfaceTexture.OnFrameAvailableListener
{
private CameraGLSurfaceView _cameraGLView;
/**
* Captures frames from an image stream as an OpenGL ES texture. The image stream may come from either camera preview or video decode.
* A SurfaceTexture may be used in place of a SurfaceHolder when specifying the output destination of a Camera or MediaPlayer object
*/
private SurfaceTexture _surface;
CameraGLRenderer _renderer;
private Camera _camera;
private ListView _shaderListView;
class CameraGLSurfaceView extends GLSurfaceView
{
CameraGLRenderer renderer;
public CameraGLSurfaceView(Context context, AttributeSet attrs)
{
super(context, attrs);
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);
// Set the Renderer for drawing on the GLSurfaceView
renderer = new CameraGLRenderer((CameraMainActivity)context);
setRenderer(renderer);
// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
public CameraGLRenderer getRenderer()
{
return renderer;
}
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
_cameraGLView = new CameraGLSurfaceView(this, null);
// Create a GLSurfaceView instance and set it
// as the ContentView for this Activity.
setContentView(R.layout.activity_main);
_cameraGLView = (CameraGLSurfaceView) findViewById(R.id.CameraGLSurfaceView);
_renderer = _cameraGLView.getRenderer();
}
Any pointers where i am wrong ?
First, have a look at the exception stacktrace in logcat to find the exact problem.
Then, guessing the problem is that the view specified in your XML cannot be instantiated: your inner class needs to be public static and you need to refer to it correctly in XML, like
com.example.camerafilters.CameraMainActivity$CameraGLSurfaceView
though it's cleaner to have it as a separate class instead of an inner class.
Why u calling it before onCreate ? You don't need to call it since you defined it in your xml layout.
You dont need to call it all. Just delete the line before setContentView.
You should call GLSurfaceView.setRenderer() in your Activity.onCreate()

Add a Line/Image above ActionBar

I want to add a line above the action bar like in the "pocket"-app. How can i do this?
Here is a picture for example:
Thanks
tomtom
Taking advantage of an Activity's WindowManager, we can draw any view we want on top. Here's some (half-pseudo) code that should help:
// Create an instance of some View that does the actual drawing of the line
View customView = new CustomView(<some context>);
// Figure out the window we have to work with
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
// Make sure the view is measured before doing this
int requestedHeight = customView.getLayoutParams().height;
// setup the params of the new view we'll attach
WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(
rect.width(), requestedHeight,
WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
// set the parameters so we fit on the top left of the window
wlp.x = 0;
wlp.y = rect.top;
wlp.gravity = Gravity.TOP;
// finally add it to the screen
getWindowManager().addView(header, wlp);
The only thing to be careful is that you can't run that code from onCreate() or any lifecycle method of the Activity because the Window won't have been created yet (You'll get a BadTokenException). One way might be post a Runnable on the Window's DecorView so that your code to add the CustomView runs after the Window is created:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
getWindow().getDecorView().post(<Runnable that execs code above>);
}
As for the actual CustomView that will display that multi-coloured bar, I feel like that's a good exercise :-)
All you'd need to do is have the onDraw() method use canvas.drawRect() with specific x and widths.
Hope that helps.
What Pocket does
As for how Pocket actually does it. If you use HierarchyViewer on the Pocket app, you'll be able to determine that Pocket uses a custom class for their ActionBar. Since they already rebuild all the features of the ActionBar for their needs, in their case, adding the line is like adding a regular View to some ViewGroup.

Categories

Resources