I have a static map, i know center coordinates in latitude and longitude, zoom level and image dimensions.
I don't understood if google static maps are already flattened and latitude and longitude per pixel are the same anywhere. If it's not like that i whant to know how can i calculate latidude and longitude per pixel and then meters per pixel , and how does that values vary with latitude .
P.S. I'm developing an android application that download an static map and computes distance between 2 points , but i've done that asuming the lat and long per pixel are the same ...and doesn't depend on latitude(position on globe)
Here is my mainactivity
package com.mnav.nav;
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.view.View.*;
import java.net.*;
import org.apache.http.*;
import android.graphics.*;
import java.io.*;
import android.graphics.drawable.*;
public class MainActivity extends Activity
{ Button start, dist;
TextView txt;
EditText lat, longit, zoom;
ImageView img;
Handler mhandler ;
Bitmap bit, original;
Boolean run = false, firstpoint = false, secondpoint = false;
String z, latitude, longitude;
int level;
int[] pointa = new int[2];
int[] pointb = new int[2];
double unit;
int maxx, maxy, minx, miny, distx, disty, distance1;
double distance;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
start=(Button)findViewById(R.id.button);
lat = (EditText)findViewById(R.id.latitude);
longit = (EditText)findViewById(R.id.longitude);
img = (ImageView)findViewById(R.id.img);
zoom =(EditText)findViewById(R.id.zoom);
dist = (Button)findViewById(R.id.dist);
txt = (TextView)findViewById(R.id.txt);
mhandler = new Handler();
start.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{ z = zoom.getText().toString();
latitude = lat.getText().toString();
longitude = longit.getText().toString();
Thread thr = new Thread(new GetImage());
thr.start();
}
});
img.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{ int i, j;
int x = (int)event.getX();
int vertical = (int)event.getY();
if(secondpoint==true)
{ bit = original.copy(Bitmap.Config.ARGB_4444, true);
img.setImageBitmap(bit);
secondpoint = false;
}
txt.setText(Integer.toString(x)+ " "+Integer.toString(vertical));
for (i = x-2; i < x+3; i++)
{
for(j=vertical-2; j<vertical+3; j++)
{
bit.setPixel(i,j, Color.WHITE);
}
}
bit.setPixel(x,vertical,Color.GREEN);
img.setImageBitmap(bit);
if(firstpoint)
{
pointb[0] = x; pointb[1]=vertical;
secondpoint = true;
firstpoint = false;
}
else
{
pointa[0]=x; pointa[1]=vertical;
firstpoint=true;
}
return false;
}
});
dist.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View p1)
{
unit = 0.1412/800;
unit = unit*500;
level = Integer.parseInt(z);
if(level == 20)
{
unit = unit;
}
else
if(level == 19)
{
unit = unit*2;
}
else
if(level==18)
{
unit = unit*4;
}
else
if(level == 17)
{
unit =unit*8;
}
else
if(level==16)
{
unit = unit*16;
}
else
if(level==15)
{
unit = unit*32;
}
else
if(level==14)
{
unit = unit*64;
}
else
if(level==13)
{
unit = unit*128;
}
else
if(level == 12)
{
unit = unit*256;
}
else
if(level==11)
{
unit = unit*512;
}
else
if(level==10)
{
unit = unit*1024;
}
distx = Math.abs(pointa[0]-pointb[0]);
disty= Math.abs(pointa[1]-pointb[1]);
distance1 = distx*distx+disty*disty;
distance = Math.sqrt(distance1);
distance = unit*distance;
txt.setText(Double.toString(distance)+" meters");
}
});
}
public class GetImage implements Runnable
{
String Url = "http://maps.google.com/staticmap?center=" + latitude+","+longitude+"&format=png&zoom="+ z +"&size=500x500&scale=1&maptype=hybrid&key=ABQIAAAA-O3c-Om9OcvXMOJXreXHAxRexG7zW5nSjltmIc1ZE-b8yotBWhQYQEU3J87QIBc4nfuySpoW_K6woA";
Bitmap bmp;
#Override
public void run()
{
try
{ mhandler.post(new Runnable()
{
#Override
public void run()
{
txt.setText("Wait...file is downloading...");
}
});
bmp = BitmapFactory.decodeStream((InputStream)new URL(Url).getContent());
}
catch (IOException e)
{ mhandler.post(new Runnable()
{
#Override
public void run()
{
// TODO: Implement this method
Toast.makeText(getApplicationContext(), "Something wrong just happend", Toast.LENGTH_LONG).show();
}
});
e.printStackTrace();
}
mhandler.post(new Runnable()
{
#Override
public void run()
{
if (bmp!=null)
{ txt.setText("Map downloaded..");
img.setImageBitmap(bmp);
bit = ((BitmapDrawable)img.getDrawable()).getBitmap();
bit = bit.copy(Bitmap.Config.ARGB_4444, true);
original = bit.copy(Bitmap.Config.ARGB_4444, true);
}
else
{
mhandler.post(new Runnable()
{
#Override
public void run()
{
Toast.makeText(getApplicationContext(), "null bitmap, sorry", Toast.LENGTH_LONG).show();
}
});
}
}
});
}
}
}
Related
I make whole video player app but stuck at mediacontroller. I want to show my own mediacontroller with different button, not the default one. It's 4rth day, i'm just trying to make my own mediacontroller but didn't succeed.
I succeed by doing it with surfaceview but i want to use it with videoview.
I try the following code.
public class MyMediaController extends MediaController {
private static final String TAG = "VideoControllerView";
MediaController.MediaPlayerControl mPlayer;
private Context mContext;
private View mAnchor;
private View mRoot;
private ProgressBar mProgress;
private TextView mEndTime, mCurrentTime;
private boolean mShowing;
private boolean mDragging;
private static final int sDefaultTimeout = 3000;
private static final int FADE_OUT = 1;
private static final int SHOW_PROGRESS = 2;
private boolean mUseFastForward;
private boolean mFromXml;
private boolean mListenersSet;
StringBuilder mFormatBuilder;
Formatter mFormatter;
private ImageButton mPauseButton;
private ImageButton mSubtitleButton;
private ImageButton mResizeButton;
private ImageButton mNextButton;
private ImageButton mPrevButton;
private final AccessibilityManager mAccessibilityManager;
public MyMediaController(Context context, AttributeSet attrs) {
super(context, attrs);
mRoot = null;
mContext = context;
mUseFastForward = true;
mFromXml = true;
mAccessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
}
public MyMediaController(Context context, boolean useFastForward) {
super(context, useFastForward);
mUseFastForward = useFastForward;
mAccessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
}
public MyMediaController(Context context) {
this(context, true);
mContext = context;
}
#Override
public void setMediaPlayer(MediaController.MediaPlayerControl player) {
mPlayer = player;
updatePausePlay();
}
#Override
public void setAnchorView(View view) {
mAnchor = view;
FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
removeAllViews();
View v = makeControllerView();
addView(v, frameParams);
}
protected View makeControllerView() {
LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mRoot = inflate.inflate(R.layout.media_controller_layout, null);
initControllerView(mRoot);
return mRoot;
}
private void initControllerView(View mRoot) {
mPauseButton = mRoot.findViewById(R.id.pause);
if (mPauseButton != null) {
mPauseButton.requestFocus();
mPauseButton.setOnClickListener(mPauseListener);
}
mResizeButton = mRoot.findViewById(R.id.resize);
if (mResizeButton != null) {
mResizeButton.requestFocus();
mResizeButton.setOnClickListener(mResizeListener);
}
mSubtitleButton = mRoot.findViewById(R.id.subtitle);
if (mSubtitleButton != null)
{
mSubtitleButton.requestFocus();
mSubtitleButton.setOnClickListener(mSubtitleListener);
}
mNextButton = mRoot.findViewById(R.id.next);
if (mNextButton != null ) {
mNextButton.requestFocus();
mNextButton.setOnClickListener(mNextListener);
}
mPrevButton = mRoot.findViewById(R.id.prev);
if (mPrevButton != null ) {
mPrevButton.requestFocus();
mPrevButton.setOnClickListener(mPrevListener);
}
mProgress = mRoot.findViewById(R.id.mediacontroller_progress);
if (mProgress != null) {
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
seeker.setOnSeekBarChangeListener(mSeekListener);
}
mProgress.setMax(1000);
}
mEndTime = mRoot.findViewById(R.id.time);
mCurrentTime = mRoot.findViewById(R.id.time_current);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
}
public final View.OnClickListener mPauseListener = new OnClickListener() {
#Override
public void onClick(View v) {
doPauseResume();
show(sDefaultTimeout);
}
};
private void doPauseResume() {
if (mPlayer == null) {
return;
}
if (mPlayer.isPlaying()) {
mPlayer.pause();
} else {
mPlayer.start();
}
updatePausePlay();
}
private void updatePausePlay() {
if (mRoot == null || mPauseButton == null)
return;
if (mPlayer.isPlaying())
mPauseButton.setImageResource(R.drawable.ic_pause);
else
mPauseButton.setImageResource(R.drawable.ic_play);
}
public final View.OnClickListener mResizeListener = new OnClickListener() {
#Override
public void onClick(View v) {
//Todo
Toast.makeText(mContext,"Resize is clicked",Toast.LENGTH_SHORT).show();
}
};
public final View.OnClickListener mNextListener = new OnClickListener() {
#Override
public void onClick(View v) {
//Todo
Toast.makeText(mContext,"NextBtn is clicked",Toast.LENGTH_SHORT).show();
}
};
public final View.OnClickListener mPrevListener = new OnClickListener() {
#Override
public void onClick(View v) {
//Todo
Toast.makeText(mContext,"PreviousBtn is clicked",Toast.LENGTH_SHORT).show();
}
};
public final View.OnClickListener mSubtitleListener = new OnClickListener() {
#Override
public void onClick(View v) {
//Todo
Toast.makeText(mContext,"subtitleBtn is clicked",Toast.LENGTH_SHORT).show();
}
};
private final SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStartTrackingTouch(SeekBar bar) {
show(3600000);
mDragging = true;
// By removing these pending progress messages we make sure
// that a) we won't update the progress while the user adjusts
// the seekbar and b) once the user is done dragging the thumb
// we will post one of these messages to the queue again and
// this ensures that there will be exactly one message queued up.
removeCallbacks(mShowProgress);
}
#Override
public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
if (!fromuser) {
// We're not interested in programmatically generated changes to
// the progress bar's position.
return;
}
long duration = mPlayer.getDuration();
long newposition = (duration * progress) / 1000L;
mPlayer.seekTo( (int) newposition);
if (mCurrentTime != null)
mCurrentTime.setText(stringForTime( (int) newposition));
}
#Override
public void onStopTrackingTouch(SeekBar bar) {
mDragging = false;
setProgress();
updatePausePlay();
show(sDefaultTimeout);
// Ensure that progress is properly updated in the future,
// the call to show() does not guarantee this because it is a
// no-op if we are already showing.
post(mShowProgress);
}
};
private int setProgress() {
if (mPlayer == null || mDragging) {
return 0;
}
int position = mPlayer.getCurrentPosition();
int duration = mPlayer.getDuration();
if (mProgress != null) {
if (duration > 0) {
// use long to avoid overflow
long pos = 1000L * position / duration;
mProgress.setProgress( (int) pos);
}
int percent = mPlayer.getBufferPercentage();
mProgress.setSecondaryProgress(percent * 10);
}
if (mEndTime != null)
mEndTime.setText(stringForTime(duration));
if (mCurrentTime != null)
mCurrentTime.setText(stringForTime(position));
return position;
}
private String stringForTime(int timeMs) {
int totalSeconds = timeMs / 1000;
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
mFormatBuilder.setLength(0);
if (hours > 0) {
return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
} else {
return mFormatter.format("%02d:%02d", minutes, seconds).toString();
}
}
private final Runnable mShowProgress = new Runnable() {
#Override
public void run() {
int pos = setProgress();
if (!mDragging && mShowing && mPlayer.isPlaying()) {
postDelayed(mShowProgress, 1000 - (pos % 1000));
}
}
};
#Override
public void show(int timeout) {
if (!mShowing && mAnchor != null) {
setProgress();
if (mPauseButton != null) {
mPauseButton.requestFocus();
}
FrameLayout.LayoutParams tlp = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM
);
addView(this, tlp);
mShowing = true;
}
updatePausePlay();
// cause the progress bar to be updated even if mShowing
// was already true. This happens, for example, if we're
// paused with the progress bar showing the user hits play.
post(mShowProgress);
if (timeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
removeCallbacks(mFadeOut);
postDelayed(mFadeOut, timeout);
}
}
#Override
public boolean isShowing() {
return mShowing;
}
/**
* Remove the controller from the screen.
*/
#Override
public void hide() {
if (mAnchor == null)
return;
if (mShowing) {
try {
removeCallbacks(mShowProgress);
removeView(this);
} catch (IllegalArgumentException ex) {
Log.w("MediaController", "already removed");
}
mShowing = false;
}
}
private final Runnable mFadeOut = new Runnable() {
#Override
public void run() {
hide();
}
};
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
show(0);
break;
case MotionEvent.ACTION_UP:
show(sDefaultTimeout);
break;
case MotionEvent.ACTION_CANCEL:
hide();
break;
default:
break;
}
return true;
}
}
Plz someone suggest my the right way to do it. I realy need help.
I'm currently developing an android application which detect objects using camera using tensorflow detection API. I want to take screenshot of the camera activity where the detection is happening.
How can I take screenshot of the camera activity including the camera preview itself?
This code came from tensorflow demo application. I just want to add a screenshot functionality using a button. That's why I added a button and an Image View. The Image View is where the screenshot preview will show but I dont have any idea on how to implement this :(
This is the code for the camera activity:
CameraActivity.java
public abstract class CameraActivity extends Activity
implements OnImageAvailableListener, Camera.PreviewCallback {
private static final Logger LOGGER = new Logger();
private static final int PERMISSIONS_REQUEST = 1;
private static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
private static final String PERMISSION_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
private boolean debug = false;
private Handler handler;
private HandlerThread handlerThread;
private boolean useCamera2API;
private boolean isProcessingFrame = false;
private byte[][] yuvBytes = new byte[3][];
private int[] rgbBytes = null;
private int yRowStride;
protected int previewWidth = 0;
protected int previewHeight = 0;
private Runnable postInferenceCallback;
private Runnable imageConverter;
#Override
protected void onCreate(final Bundle savedInstanceState) {
LOGGER.d("onCreate " + this);
super.onCreate(null);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_camera);
if (hasPermission()) {
setFragment();
} else {
requestPermission();
}
}
private byte[] lastPreviewFrame;
protected int[] getRgbBytes() {
imageConverter.run();
return rgbBytes;
}
protected int getLuminanceStride() {
return yRowStride;
}
protected byte[] getLuminance() {
return yuvBytes[0];
}
/**
* Callback for android.hardware.Camera API
*/
#Override
public void onPreviewFrame(final byte[] bytes, final Camera camera) {
if (isProcessingFrame) {
LOGGER.w("Dropping frame!");
return;
}
try {
// Initialize the storage bitmaps once when the resolution is known.
if (rgbBytes == null) {
Camera.Size previewSize = camera.getParameters().getPreviewSize();
previewHeight = previewSize.height;
previewWidth = previewSize.width;
rgbBytes = new int[previewWidth * previewHeight];
onPreviewSizeChosen(new Size(previewSize.width, previewSize.height), 90);
}
} catch (final Exception e) {
LOGGER.e(e, "Exception!");
return;
}
isProcessingFrame = true;
lastPreviewFrame = bytes;
yuvBytes[0] = bytes;
yRowStride = previewWidth;
imageConverter =
new Runnable() {
#Override
public void run() {
ImageUtils.convertYUV420SPToARGB8888(bytes, previewWidth, previewHeight, rgbBytes);
}
};
postInferenceCallback =
new Runnable() {
#Override
public void run() {
camera.addCallbackBuffer(bytes);
isProcessingFrame = false;
}
};
processImage();
}
/**
* Callback for Camera2 API
*/
#Override
public void onImageAvailable(final ImageReader reader) {
//We need wait until we have some size from onPreviewSizeChosen
if (previewWidth == 0 || previewHeight == 0) {
return;
}
if (rgbBytes == null) {
rgbBytes = new int[previewWidth * previewHeight];
}
try {
final Image image = reader.acquireLatestImage();
if (image == null) {
return;
}
if (isProcessingFrame) {
image.close();
return;
}
isProcessingFrame = true;
Trace.beginSection("imageAvailable");
final Plane[] planes = image.getPlanes();
fillBytes(planes, yuvBytes);
yRowStride = planes[0].getRowStride();
final int uvRowStride = planes[1].getRowStride();
final int uvPixelStride = planes[1].getPixelStride();
imageConverter =
new Runnable() {
#Override
public void run() {
ImageUtils.convertYUV420ToARGB8888(
yuvBytes[0],
yuvBytes[1],
yuvBytes[2],
previewWidth,
previewHeight,
yRowStride,
uvRowStride,
uvPixelStride,
rgbBytes);
}
};
postInferenceCallback =
new Runnable() {
#Override
public void run() {
image.close();
isProcessingFrame = false;
}
};
processImage();
} catch (final Exception e) {
LOGGER.e(e, "Exception!");
Trace.endSection();
return;
}
Trace.endSection();
}
#Override
public synchronized void onStart() {
LOGGER.d("onStart " + this);
super.onStart();
}
#Override
public synchronized void onResume() {
LOGGER.d("onResume " + this);
super.onResume();
handlerThread = new HandlerThread("inference");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
#Override
public synchronized void onPause() {
LOGGER.d("onPause " + this);
if (!isFinishing()) {
LOGGER.d("Requesting finish");
finish();
}
handlerThread.quitSafely();
try {
handlerThread.join();
handlerThread = null;
handler = null;
} catch (final InterruptedException e) {
LOGGER.e(e, "Exception!");
}
super.onPause();
}
#Override
public synchronized void onStop() {
LOGGER.d("onStop " + this);
super.onStop();
}
#Override
public synchronized void onDestroy() {
LOGGER.d("onDestroy " + this);
super.onDestroy();
}
protected synchronized void runInBackground(final Runnable r) {
if (handler != null) {
handler.post(r);
}
}
#Override
public void onRequestPermissionsResult(
final int requestCode, final String[] permissions, final int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
setFragment();
} else {
requestPermission();
}
}
}
private boolean hasPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return checkSelfPermission(PERMISSION_CAMERA) == PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(PERMISSION_STORAGE) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
}
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(PERMISSION_CAMERA) ||
shouldShowRequestPermissionRationale(PERMISSION_STORAGE)) {
Toast.makeText(CameraActivity.this,
"Camera AND storage permission are required for this demo", Toast.LENGTH_LONG).show();
}
requestPermissions(new String[] {PERMISSION_CAMERA, PERMISSION_STORAGE}, PERMISSIONS_REQUEST);
}
}
// Returns true if the device supports the required hardware level, or better.
private boolean isHardwareLevelSupported(
CameraCharacteristics characteristics, int requiredLevel) {
int deviceLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
return requiredLevel == deviceLevel;
}
// deviceLevel is not LEGACY, can use numerical sort
return requiredLevel <= deviceLevel;
}
private String chooseCamera() {
final CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for (final String cameraId : manager.getCameraIdList()) {
final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
// We don't use a front facing camera in this sample.
final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
final StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
continue;
}
// Fallback to camera1 API for internal cameras that don't have full support.
// This should help with legacy situations where using the camera2 API causes
// distorted or otherwise broken previews.
useCamera2API = (facing == CameraCharacteristics.LENS_FACING_EXTERNAL)
|| isHardwareLevelSupported(characteristics,
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
LOGGER.i("Camera API lv2?: %s", useCamera2API);
return cameraId;
}
} catch (CameraAccessException e) {
LOGGER.e(e, "Not allowed to access camera");
}
return null;
}
protected void setFragment() {
String cameraId = chooseCamera();
Fragment fragment;
if (useCamera2API) {
CameraConnectionFragment camera2Fragment =
CameraConnectionFragment.newInstance(
new CameraConnectionFragment.ConnectionCallback() {
#Override
public void onPreviewSizeChosen(final Size size, final int rotation) {
previewHeight = size.getHeight();
previewWidth = size.getWidth();
CameraActivity.this.onPreviewSizeChosen(size, rotation);
}
},
this,
getLayoutId(),
getDesiredPreviewFrameSize());
camera2Fragment.setCamera(cameraId);
fragment = camera2Fragment;
} else {
fragment =
new LegacyCameraConnectionFragment(this, getLayoutId(), getDesiredPreviewFrameSize());
}
getFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
protected void fillBytes(final Plane[] planes, final byte[][] yuvBytes) {
// Because of the variable row stride it's not possible to know in
// advance the actual necessary dimensions of the yuv planes.
for (int i = 0; i < planes.length; ++i) {
final ByteBuffer buffer = planes[i].getBuffer();
if (yuvBytes[i] == null) {
LOGGER.d("Initializing buffer %d at size %d", i, buffer.capacity());
yuvBytes[i] = new byte[buffer.capacity()];
}
buffer.get(yuvBytes[i]);
}
}
public boolean isDebug() {
return debug;
}
public void requestRender() {
final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay);
if (overlay != null) {
overlay.postInvalidate();
}
}
public void addCallback(final OverlayView.DrawCallback callback) {
final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay);
if (overlay != null) {
overlay.addCallback(callback);
}
}
public void onSetDebug(final boolean debug) {}
#Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
debug = !debug;
requestRender();
onSetDebug(debug);
return true;
}
return super.onKeyDown(keyCode, event);
}
protected void readyForNextImage() {
if (postInferenceCallback != null) {
postInferenceCallback.run();
}
}
protected int getScreenOrientation() {
switch (getWindowManager().getDefaultDisplay().getRotation()) {
case Surface.ROTATION_270:
return 270;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_90:
return 90;
default:
return 0;
}
}
protected abstract void processImage();
protected abstract void onPreviewSizeChosen(final Size size, final int rotation);
protected abstract int getLayoutId();
protected abstract Size getDesiredPreviewFrameSize();
}
And this is the layout file
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="500dp"
tools:context="org.tensorflow.demo.CameraActivity">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Screenshot" />
</FrameLayout>
<ImageView
android:id="#+id/imageView"
android:layout_width="140dp"
android:layout_height="160dp"
android:layout_marginStart="205dp"
android:layout_marginTop="0dp" />
I just want to take screenshot of the activity including the camera where the detection is happening. I tried some tutorials on how to take screenshot. It captures all the parts of the screen but doesnt capture the camera part. It only shows black screen. HELP!
So I am running into a problem with a function I made to slowly change the value of a monitored variable over time that is causing all the java logic to lock up. It doesn't seem to be producing an error or make the application crash so it must be getting stuck in the while loop or something but the logging isn't firing while it is locked so I am just very confused. If anyone can help me figure out how to diagnose what is causing the freezing that would be very much appreciated
EDIT: Turns out the problem was updating the UI from another thread, I manged to get it to crash and got the error and used a CountDownTimer instead of the background thread and now it is working fine. For those curious checkout my GitHub for this project.
Function in question:
public static void changeOverTime(final MonitoredVariable<Integer> tVar, final int tTo, final long tTime, final long tUpdateFreq) {
if (tTime < tUpdateFreq) { Log.e(TAG, "Time must be greater then update freq."); }
if (tVar == null) { Log.e(TAG, "Container cannot be null."); }
else {
final Thread tBackgroundThread = new Thread(new Runnable() {
#Override
public void run() {
float tSteps = tTime / tUpdateFreq; // 2000/100 = 20
float tInterval = (tTo - tVar.get()) / tSteps; // 67-175 = -108/20 = -5.4
float tVal = tVar.get(); //175
while (Math.round(tVal) != tTo) { //67(After 20 Times) != 67 -> FALSE
Debug.Log(TAG, "EQ: " + Math.round(tVal) + "?=" + tTo);
tVal += tInterval; // -5.4 * 20(Times) = -108+175 = 67
tryToSleep(tUpdateFreq); // 100ms * 20(Times) = 2000ms total
tVar.set(Math.round(tVal));
}
}
});
tBackgroundThread.start();
}
}
Supporting Function:
private static void tryToSleep(long tTime) {
try { sleep(tTime); }
catch (InterruptedException e) { e.printStackTrace(); }
}
Monitored Variable Class:
public class MonitoredVariable<Prototype> {
protected Prototype mData;
protected ChangeListener mListener;
public MonitoredVariable(Prototype tData) {
this(tData, null);
}
public MonitoredVariable(Prototype tData, ChangeListener tListener) {
if (tListener != null) setListener(tListener);
mData = tData;
}
public Prototype get() {
return mData;
}
public void set(Prototype tData) {
if (mData != tData) {
mData = tData;
notifyChange();
}
}
public void setListener(ChangeListener tListener) {
mListener = tListener;
}
public ChangeListener getListener() {
return mListener;
}
public void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}
}
Usage:
public static void init() {
MonitoredVariable.ChangeListener tUpdateBackground = new MonitoredVariable.ChangeListener() {
#Override
public void onChange() { updateBackgroud();
}
};
mTop = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mBottom = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mAnimationLoop = new Handler();
mAnimation = new Runnable() {
#Override
public void run() {
Debug.Log(TAG, "RUNNING ANIMATION");
final Random RNG = new Random();
for (MonitoredVariable<Integer>[] tBackground: new MonitoredVariable[][] {mTop, mBottom}) {
for (MonitoredVariable<Integer> tColor : tBackground) {
int tRandomColor = RNG.nextInt(255);
//tColor.set(tRandomColor);
Shift.changeOverTime(tColor, tRandomColor, 2000, 100);
}
}
if(mAnimate.get()) {
mAnimationLoop.postDelayed(mAnimation, 10000);
}
}
};
mAnimate = new MonitoredVariable<>(false, new MonitoredVariable.ChangeListener() {
#Override
public void onChange() {
if (mAnimate.get()) mAnimationLoop.postDelayed(mAnimation, 0);
else mAnimationLoop.removeCallbacks(mAnimation);
}
});
}
public static void setBackground(final Activity tActivity){
final View tActivityBackground = tActivity.findViewById(R.id.background);
mListener = new ChangeListener() {
#Override
public void onChange() { tActivityBackground.setBackground(mBackground); }
};
notifyChange();
}
private static void updateBackgroud() {
int tTop = Color.argb(255, mTop[0].get(), mTop[1].get(), mTop[2].get());
int tBottom = Color.argb(255, mBottom[0].get(), mBottom[1].get(), mBottom[2].get());
int[] colors = {tTop, tBottom};
mBackground = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
mBackground.setCornerRadius(0f);
notifyChange();
}
public static void animateBackground(boolean tAnimate) {
mAnimate.set(tAnimate);
}
public static void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}
I found a Flappy Bird GitHub project and changed it a little bit.
I successfully implemented the AdMob Banner.
But now I also want a Interstitial Ad which pops up when the Game is over (not every time of course) so here is my GitHub project: https://github.com/DaFaack/FlappyBibi
Please explain me how to do it because I can't find a good explanation on the internet.
I want to display the ad in the run() method. You can find it in the core package -> GameplayScreen.java File -> renderPlaying() method and then the run() method.
This is the method i am talking about:
private void renderPlaying() {
if (justTouched) {
bird.jump();
justTouched = false;
}
updatePipePairs();
gameplayStage.act();
uiStage.act();
checkCollisions();
if (bird.getState() == Bird.State.DYING) {
stopTheWorld();
RunnableAction playWooshAction = Actions.run(new Runnable() {
#Override
public void run() {
com.pentagames.flappybibi.Assets.playWooshSound();
//Here I want to display the Interstitial Ad!
}
});
What do I have to do to display the Interstitial Ad when the game is over?
This is my AndroidLauncher.java file:
package com.pentagames.flappybibi.android;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.pentagames.flappybibi.FlappyGame;
public class AndroidLauncher extends AndroidApplication{
private static final String TAG = "AndroidLauncher";
protected AdView adView;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout layout = new RelativeLayout(this);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
View gameView=initializeForView(new FlappyGame(), config);
layout.addView(gameView);
adView = new AdView(this);
adView.setAdListener(new AdListener(){
#Override
public void onAdLoaded(){
int visibility = adView.getVisibility();
adView.setVisibility(AdView.GONE);
adView.setVisibility(AdView.VISIBLE);
Log.i(TAG, "Ad Loaded...");
}
});
adView.setAdSize(AdSize.SMART_BANNER);
adView.setAdUnitId("ca-app-pub-XXXXXXXXXXXXXX/XXXXXXXXX");
AdRequest.Builder builder = new AdRequest.Builder();
RelativeLayout.LayoutParams adParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
);
adParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
adParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
layout.addView(adView, adParams);
adView.loadAd(builder.build());
setContentView(layout);
}
#Override
protected void onResume() {
super.onResume();
adView.resume();
}
#Override
protected void onPause() {
super.onPause();
adView.pause();
}
#Override
protected void onDestroy() {
super.onDestroy();
adView.destroy();
}
}
And this the GameplayScreen file:
package com.pentagames.flappybibi;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.actions.RunnableAction;
import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.viewport.StretchViewport;
public class GameplayScreen extends ScreenAdapter{
public static final float PIPE_SPACING = 200f;
public static final int PIPE_SETS = 3;
protected OrthographicCamera camera;
protected com.pentagames.flappybibi.FlappyGame game;
private Stage gameplayStage;
private Stage uiStage;
private Label scoreLabel;
private Label tapToRetry;
private Label best;
private Label tapToFlap;
private Image whitePixel;
private Image backgroundBuildings;
private int score;
private Bird bird;
private Array<PipePair> pipePairs;
private com.pentagames.flappybibi.Ground ground;
private boolean justTouched;
private Color backgroundColor;
private State screenState = State.PREGAME;
private boolean allowRestart = false;
private enum State {PREGAME, PLAYING, DYING, DEAD}
public GameplayScreen(com.pentagames.flappybibi.FlappyGame game) {
this.game = game;
camera = new OrthographicCamera(com.pentagames.flappybibi.FlappyGame.WIDTH, com.pentagames.flappybibi.FlappyGame.HEIGHT);
gameplayStage = new Stage(new StretchViewport(com.pentagames.flappybibi.FlappyGame.WIDTH, com.pentagames.flappybibi.FlappyGame.HEIGHT, camera));
uiStage = new Stage(new StretchViewport(com.pentagames.flappybibi.FlappyGame.WIDTH, com.pentagames.flappybibi.FlappyGame.HEIGHT));
bird = new Bird();
bird.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH * .25f, com.pentagames.flappybibi.FlappyGame.HEIGHT / 2, Align.center);
bird.addAction(Utils.getFloatyAction());
bird.setState(Bird.State.PREGAME);
whitePixel = new Image(com.pentagames.flappybibi.Assets.whitePixel);
scoreLabel = new Label("0", new Label.LabelStyle(com.pentagames.flappybibi.Assets.fontMedium, Color.WHITE));
scoreLabel.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, com.pentagames.flappybibi.FlappyGame.HEIGHT * .9f, Align.center);
uiStage.addActor(scoreLabel);
tapToRetry = new Label("Nochmal?", new Label.LabelStyle(com.pentagames.flappybibi.Assets.fontMedium, Color.WHITE));
tapToRetry.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, 0, Align.top);
uiStage.addActor(tapToRetry);
best = new Label("Highscore: ", new Label.LabelStyle(com.pentagames.flappybibi.Assets.fontMedium, Color.WHITE));
best.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, 0, Align.top);
uiStage.addActor(best);
tapToFlap = new Label("Fass mich an!", new Label.LabelStyle(com.pentagames.flappybibi.Assets.fontMedium, Color.WHITE));
tapToFlap.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, com.pentagames.flappybibi.FlappyGame.HEIGHT, Align.bottom);
uiStage.addActor(tapToFlap);
initBackgroundBuildings();
pipePairs = new Array<PipePair>();
ground = new com.pentagames.flappybibi.Ground();
ground.setPosition(0, 0);
backgroundColor = Utils.getRandomBackgroundColor();
// The order actors are added determines the order they are drawn so make sure the background is first
gameplayStage.addActor(ground);
gameplayStage.addActor(backgroundBuildings);
gameplayStage.addActor(bird);
// Setup the input processor
initInputProcessor();
}
private void initBackgroundBuildings() {
backgroundBuildings = new Image(com.pentagames.flappybibi.Assets.backgroundBuildings);
backgroundBuildings.setWidth(com.pentagames.flappybibi.FlappyGame.WIDTH);
backgroundBuildings.setHeight(backgroundBuildings.getHeight()*2f);
backgroundBuildings.setY(com.pentagames.flappybibi.Ground.HEIGHT);
}
#Override
public void show() {
tapToFlap.addAction(Actions.moveToAligned(com.pentagames.flappybibi.FlappyGame.CENTER_X, com.pentagames.flappybibi.FlappyGame.CENTER_Y + 100f, Align.center, .75f, Interpolation.sine));
com.pentagames.flappybibi.Assets.playWooshSound();
}
#Override
public void render(float delta) {
Gdx.graphics.getGL20().glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 1f);
Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
switch (screenState) {
case PREGAME:
updateAndDrawStages();
break;
case PLAYING:
renderPlaying();
break;
case DYING:
case DEAD:
renderDeadOrDying();
break;
}
}
private void renderDeadOrDying() {
if (bird.getState() == Bird.State.DEAD) {
screenState = State.DEAD;
}
updateAndDrawStages();
}
private void renderPlaying() {
if (justTouched) {
bird.jump();
justTouched = false;
}
updatePipePairs();
gameplayStage.act();
uiStage.act();
checkCollisions();
if (bird.getState() == Bird.State.DYING) {
stopTheWorld();
RunnableAction playWooshAction = Actions.run(new Runnable() {
#Override
public void run() {
com.pentagames.flappybibi.Assets.playWooshSound();
//Here I want to display the Interstitial Ad!
}
});
SequenceAction actions = Actions.sequence(Actions.delay(1f), playWooshAction, Actions.moveToAligned(com.pentagames.flappybibi.FlappyGame.CENTER_X, com.pentagames.flappybibi.FlappyGame.CENTER_Y, Align.bottom,
.75f, Interpolation.sine), Actions.run(new Runnable() {
#Override
public void run() {
// Allow the player to restart the game once the tap to retry finishes coming up
allowRestart = true;
}
}));
tapToRetry.addAction(actions);
best.setText("Highscore: " + com.pentagames.flappybibi.SavedDataManager.getInstance().getHighScore());
best.setWidth(best.getTextBounds().width);
best.setPosition(com.pentagames.flappybibi.FlappyGame.CENTER_X, 0, Align.top);
best.addAction(Actions.delay(1f, Actions.moveToAligned(com.pentagames.flappybibi.FlappyGame.CENTER_X, com.pentagames.flappybibi.FlappyGame.CENTER_Y, Align.top,
.75f, Interpolation.sine)));
screenState = State.DYING;
}
gameplayStage.draw();
uiStage.draw();
}
private void updateAndDrawStages() {
gameplayStage.act();
gameplayStage.draw();
uiStage.act();
uiStage.draw();
}
#Override
public void resize(int width, int height) {
camera.setToOrtho(false, width, height);
com.pentagames.flappybibi.Assets.batch.setProjectionMatrix(camera.combined);
gameplayStage.getViewport().update(width, height, true);
uiStage.getViewport().update(width, height, true);
}
#Override
public void dispose() {
gameplayStage.dispose();
uiStage.dispose();
}
private void checkCollisions() {
for (int i = 0; i < pipePairs.size; i++) {
PipePair pair = pipePairs.get(i);
if (pair.getBottomPipe().getBounds().overlaps(bird.getBounds()) || pair.getTopPipe().getBounds().overlaps(bird.getBounds())) {
stopTheWorld();
com.pentagames.flappybibi.SavedDataManager.getInstance().setHighScore(score);
showWhiteScreen();
} else if (bird.isBelowGround()) {
bird.setY(com.pentagames.flappybibi.FlappyGame.GROUND_LEVEL);
bird.clearActions();
bird.setToDying();
showWhiteScreen();
} else if (bird.isAboveCeiling()) {
bird.setY(com.pentagames.flappybibi.FlappyGame.HEIGHT - bird.getHeight());
bird.setToDying();
showWhiteScreen();
} else if (pair.getRuby().getBounds().overlaps(bird.getBounds())) {
score++;
updateScoreLabel();
pair.moveCoinOffscreen();
com.pentagames.flappybibi.Assets.playBingSound();
}
}
}
private void showWhiteScreen() {
whitePixel.setWidth(com.pentagames.flappybibi.FlappyGame.WIDTH);
whitePixel.setHeight(com.pentagames.flappybibi.FlappyGame.HEIGHT);
gameplayStage.addActor(whitePixel);
whitePixel.addAction(Actions.fadeOut(.5f));
}
private void updateScoreLabel() {
scoreLabel.setText(String.valueOf(score));
scoreLabel.setWidth(scoreLabel.getTextBounds().width);
scoreLabel.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, com.pentagames.flappybibi.FlappyGame.HEIGHT * .9f, Align.center);
}
private void stopTheWorld() {
bird.setToDying();
killPipePairs();
stopTheGround();
screenState = State.DYING;
}
private void stopTheGround() {
ground.vel.x = 0;
}
private void killPipePairs() {
for (PipePair pair : pipePairs) {
pair.getBottomPipe().setState(Pipe.State.dead);
pair.getTopPipe().setState(Pipe.State.dead);
pair.getRuby().setVel(0, 0);
}
}
private void updatePipePairs() {
for (int i = 0; i < pipePairs.size; i++) {
pipePairs.get(i).update();
}
}
private void addPipes(Stage gameplayStage) {
for (int i = 0; i < pipePairs.size; i++) {
gameplayStage.addActor(pipePairs.get(i).getBottomPipe());
gameplayStage.addActor(pipePairs.get(i).getTopPipe());
gameplayStage.addActor(pipePairs.get(i).getRuby());
}
}
private void initThirdSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initThird();
// add the pair to the list
pipePairs.add(pair);
}
private void initSecondSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initSecond();
// add the pair to the list
pipePairs.add(pair);
}
private void initFirstSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initFirst();
// add the pair to the list
pipePairs.add(pair);
}
/**
* Tells libgdx to listen for inputs coming from the InputAdapter we give it
*/
private void initInputProcessor() {
Gdx.input.setInputProcessor(new InputAdapter() {
// We only care about the touch down event
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
switch (screenState) {
case DYING:
justTouched = true;
break;
case DEAD:
if (allowRestart) {
game.setScreen(new GameplayScreen(game));
}
justTouched = true;
break;
case PLAYING:
justTouched = true;
break;
case PREGAME:
justTouched = true;
screenState = State.PLAYING;
bird.setState(Bird.State.ALIVE);
bird.clearActions();
tapToFlap.addAction(Actions.moveToAligned(com.pentagames.flappybibi.FlappyGame.CENTER_X, com.pentagames.flappybibi.FlappyGame.HEIGHT, Align.bottom, .75f, Interpolation.sine));
initFirstSetOfPipes();
initSecondSetOfPipes();
initThirdSetOfPipes();
addPipes(gameplayStage);
gameplayStage.addActor(ground);
gameplayStage.addActor(bird);
break;
}
return true;
}
});
}
}
This is the first time that I'm working with LibGDX, would be great if you can explain me how to implement the Interstitial Ad in this project.
Sorry for my bad English.
You already integrated banner Ad so no need to injected dependent artifact in your project.
Follow these steps for Interstitial Ad integration.
AndroidManifest.xml
Make an entry of AdActivity for Interstitial Ad
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="#android:style/Theme.Translucent" />
Create an interface inside your core module
public interface AdService {
boolean isInterstitialLoaded();
void showInterstitial();
}
Create a parameterized constructor of FlappyGame class
public AdService adService;
public FlappyGame(AdService ads){
adService=ads;
}
Implement AdService interface to your AndroidLauncher class
public class AndroidLauncher extends AndroidApplication implements AdService {
private static final String AD_UNIT_ID_INTERSTITIAL = "ca-app-pub-XXXXX/XXXXX";
private InterstitialAd interstitialAd;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
View gameView=initializeForView(new FlappyGame(this), config);
...
interstitialAd = new InterstitialAd(this);
interstitialAd.setAdUnitId(AD_UNIT_ID_INTERSTITIAL);
interstitialAd.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {}
#Override
public void onAdClosed() {
loadIntersitialAd();
}
});
loadIntersitialAd();
}
private void loadIntersitialAd(){
AdRequest interstitialRequest = new AdRequest.Builder().build();
interstitialAd.loadAd(interstitialRequest);
}
#Override
public void showInterstitial() {
runOnUiThread(new Runnable() {
public void run() {
if (interstitialAd.isLoaded())
interstitialAd.show();
else
loadIntersitialAd();
}
});
}
#Override
public boolean isInterstitialLoaded() {
return interstitialAd.isLoaded();
}
}
GameScreen class
RunnableAction playWooshAction = Actions.run(new Runnable() {
#Override
public void run() {
com.pentagames.flappybibi.Assets.playWooshSound();
game.adService.showInterstitial();
}
});
I integrated Interstitial Ad in your project, created a pull request for the same. You can merge my pull request.
I found a Flappy Bird GitHub project and changed it a little bit.
I successfully implemented the AdMob Banner.
But now I also want a Interstitial Ad which pops up when the Game is over (not every time of course) so here is my GitHub project: https://github.com/DaFaack/FlappyBibi
Please explain me how to do it because I can't find a good explanation on the internet.
I want to display the ad in the run() method. You can find it in the core package -> GameplayScreen.java File -> renderPlaying() method and then the run() method.
This is the method i am talking about:
private void renderPlaying() {
if (justTouched) {
bird.jump();
justTouched = false;
}
updatePipePairs();
gameplayStage.act();
uiStage.act();
checkCollisions();
if (bird.getState() == Bird.State.DYING) {
stopTheWorld();
RunnableAction playWooshAction = Actions.run(new Runnable() {
#Override
public void run() {
com.pentagames.flappybibi.Assets.playWooshSound();
//Here I want to display the Interstitial Ad!
}
});
What do I have to do to display the Interstitial Ad when the game is over?
This is my AndroidLauncher.java file:
package com.pentagames.flappybibi.android;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.pentagames.flappybibi.FlappyGame;
public class AndroidLauncher extends AndroidApplication{
private static final String TAG = "AndroidLauncher";
protected AdView adView;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout layout = new RelativeLayout(this);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
View gameView=initializeForView(new FlappyGame(), config);
layout.addView(gameView);
adView = new AdView(this);
adView.setAdListener(new AdListener(){
#Override
public void onAdLoaded(){
int visibility = adView.getVisibility();
adView.setVisibility(AdView.GONE);
adView.setVisibility(AdView.VISIBLE);
Log.i(TAG, "Ad Loaded...");
}
});
adView.setAdSize(AdSize.SMART_BANNER);
adView.setAdUnitId("ca-app-pub-XXXXXXXXXXXXXX/XXXXXXXXX");
AdRequest.Builder builder = new AdRequest.Builder();
RelativeLayout.LayoutParams adParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
);
adParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
adParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
layout.addView(adView, adParams);
adView.loadAd(builder.build());
setContentView(layout);
}
#Override
protected void onResume() {
super.onResume();
adView.resume();
}
#Override
protected void onPause() {
super.onPause();
adView.pause();
}
#Override
protected void onDestroy() {
super.onDestroy();
adView.destroy();
}
}
And this the GameplayScreen file:
package com.pentagames.flappybibi;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.actions.RunnableAction;
import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.viewport.StretchViewport;
public class GameplayScreen extends ScreenAdapter{
public static final float PIPE_SPACING = 200f;
public static final int PIPE_SETS = 3;
protected OrthographicCamera camera;
protected com.pentagames.flappybibi.FlappyGame game;
private Stage gameplayStage;
private Stage uiStage;
private Label scoreLabel;
private Label tapToRetry;
private Label best;
private Label tapToFlap;
private Image whitePixel;
private Image backgroundBuildings;
private int score;
private Bird bird;
private Array<PipePair> pipePairs;
private com.pentagames.flappybibi.Ground ground;
private boolean justTouched;
private Color backgroundColor;
private State screenState = State.PREGAME;
private boolean allowRestart = false;
private enum State {PREGAME, PLAYING, DYING, DEAD}
public GameplayScreen(com.pentagames.flappybibi.FlappyGame game) {
this.game = game;
camera = new OrthographicCamera(com.pentagames.flappybibi.FlappyGame.WIDTH, com.pentagames.flappybibi.FlappyGame.HEIGHT);
gameplayStage = new Stage(new StretchViewport(com.pentagames.flappybibi.FlappyGame.WIDTH, com.pentagames.flappybibi.FlappyGame.HEIGHT, camera));
uiStage = new Stage(new StretchViewport(com.pentagames.flappybibi.FlappyGame.WIDTH, com.pentagames.flappybibi.FlappyGame.HEIGHT));
bird = new Bird();
bird.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH * .25f, com.pentagames.flappybibi.FlappyGame.HEIGHT / 2, Align.center);
bird.addAction(Utils.getFloatyAction());
bird.setState(Bird.State.PREGAME);
whitePixel = new Image(com.pentagames.flappybibi.Assets.whitePixel);
scoreLabel = new Label("0", new Label.LabelStyle(com.pentagames.flappybibi.Assets.fontMedium, Color.WHITE));
scoreLabel.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, com.pentagames.flappybibi.FlappyGame.HEIGHT * .9f, Align.center);
uiStage.addActor(scoreLabel);
tapToRetry = new Label("Nochmal?", new Label.LabelStyle(com.pentagames.flappybibi.Assets.fontMedium, Color.WHITE));
tapToRetry.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, 0, Align.top);
uiStage.addActor(tapToRetry);
best = new Label("Highscore: ", new Label.LabelStyle(com.pentagames.flappybibi.Assets.fontMedium, Color.WHITE));
best.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, 0, Align.top);
uiStage.addActor(best);
tapToFlap = new Label("Fass mich an!", new Label.LabelStyle(com.pentagames.flappybibi.Assets.fontMedium, Color.WHITE));
tapToFlap.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, com.pentagames.flappybibi.FlappyGame.HEIGHT, Align.bottom);
uiStage.addActor(tapToFlap);
initBackgroundBuildings();
pipePairs = new Array<PipePair>();
ground = new com.pentagames.flappybibi.Ground();
ground.setPosition(0, 0);
backgroundColor = Utils.getRandomBackgroundColor();
// The order actors are added determines the order they are drawn so make sure the background is first
gameplayStage.addActor(ground);
gameplayStage.addActor(backgroundBuildings);
gameplayStage.addActor(bird);
// Setup the input processor
initInputProcessor();
}
private void initBackgroundBuildings() {
backgroundBuildings = new Image(com.pentagames.flappybibi.Assets.backgroundBuildings);
backgroundBuildings.setWidth(com.pentagames.flappybibi.FlappyGame.WIDTH);
backgroundBuildings.setHeight(backgroundBuildings.getHeight()*2f);
backgroundBuildings.setY(com.pentagames.flappybibi.Ground.HEIGHT);
}
#Override
public void show() {
tapToFlap.addAction(Actions.moveToAligned(com.pentagames.flappybibi.FlappyGame.CENTER_X, com.pentagames.flappybibi.FlappyGame.CENTER_Y + 100f, Align.center, .75f, Interpolation.sine));
com.pentagames.flappybibi.Assets.playWooshSound();
}
#Override
public void render(float delta) {
Gdx.graphics.getGL20().glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 1f);
Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
switch (screenState) {
case PREGAME:
updateAndDrawStages();
break;
case PLAYING:
renderPlaying();
break;
case DYING:
case DEAD:
renderDeadOrDying();
break;
}
}
private void renderDeadOrDying() {
if (bird.getState() == Bird.State.DEAD) {
screenState = State.DEAD;
}
updateAndDrawStages();
}
private void renderPlaying() {
if (justTouched) {
bird.jump();
justTouched = false;
}
updatePipePairs();
gameplayStage.act();
uiStage.act();
checkCollisions();
if (bird.getState() == Bird.State.DYING) {
stopTheWorld();
RunnableAction playWooshAction = Actions.run(new Runnable() {
#Override
public void run() {
com.pentagames.flappybibi.Assets.playWooshSound();
//Here I want to display the Interstitial Ad!
}
});
SequenceAction actions = Actions.sequence(Actions.delay(1f), playWooshAction, Actions.moveToAligned(com.pentagames.flappybibi.FlappyGame.CENTER_X, com.pentagames.flappybibi.FlappyGame.CENTER_Y, Align.bottom,
.75f, Interpolation.sine), Actions.run(new Runnable() {
#Override
public void run() {
// Allow the player to restart the game once the tap to retry finishes coming up
allowRestart = true;
}
}));
tapToRetry.addAction(actions);
best.setText("Highscore: " + com.pentagames.flappybibi.SavedDataManager.getInstance().getHighScore());
best.setWidth(best.getTextBounds().width);
best.setPosition(com.pentagames.flappybibi.FlappyGame.CENTER_X, 0, Align.top);
best.addAction(Actions.delay(1f, Actions.moveToAligned(com.pentagames.flappybibi.FlappyGame.CENTER_X, com.pentagames.flappybibi.FlappyGame.CENTER_Y, Align.top,
.75f, Interpolation.sine)));
screenState = State.DYING;
}
gameplayStage.draw();
uiStage.draw();
}
private void updateAndDrawStages() {
gameplayStage.act();
gameplayStage.draw();
uiStage.act();
uiStage.draw();
}
#Override
public void resize(int width, int height) {
camera.setToOrtho(false, width, height);
com.pentagames.flappybibi.Assets.batch.setProjectionMatrix(camera.combined);
gameplayStage.getViewport().update(width, height, true);
uiStage.getViewport().update(width, height, true);
}
#Override
public void dispose() {
gameplayStage.dispose();
uiStage.dispose();
}
private void checkCollisions() {
for (int i = 0; i < pipePairs.size; i++) {
PipePair pair = pipePairs.get(i);
if (pair.getBottomPipe().getBounds().overlaps(bird.getBounds()) || pair.getTopPipe().getBounds().overlaps(bird.getBounds())) {
stopTheWorld();
com.pentagames.flappybibi.SavedDataManager.getInstance().setHighScore(score);
showWhiteScreen();
} else if (bird.isBelowGround()) {
bird.setY(com.pentagames.flappybibi.FlappyGame.GROUND_LEVEL);
bird.clearActions();
bird.setToDying();
showWhiteScreen();
} else if (bird.isAboveCeiling()) {
bird.setY(com.pentagames.flappybibi.FlappyGame.HEIGHT - bird.getHeight());
bird.setToDying();
showWhiteScreen();
} else if (pair.getRuby().getBounds().overlaps(bird.getBounds())) {
score++;
updateScoreLabel();
pair.moveCoinOffscreen();
com.pentagames.flappybibi.Assets.playBingSound();
}
}
}
private void showWhiteScreen() {
whitePixel.setWidth(com.pentagames.flappybibi.FlappyGame.WIDTH);
whitePixel.setHeight(com.pentagames.flappybibi.FlappyGame.HEIGHT);
gameplayStage.addActor(whitePixel);
whitePixel.addAction(Actions.fadeOut(.5f));
}
private void updateScoreLabel() {
scoreLabel.setText(String.valueOf(score));
scoreLabel.setWidth(scoreLabel.getTextBounds().width);
scoreLabel.setPosition(com.pentagames.flappybibi.FlappyGame.WIDTH / 2, com.pentagames.flappybibi.FlappyGame.HEIGHT * .9f, Align.center);
}
private void stopTheWorld() {
bird.setToDying();
killPipePairs();
stopTheGround();
screenState = State.DYING;
}
private void stopTheGround() {
ground.vel.x = 0;
}
private void killPipePairs() {
for (PipePair pair : pipePairs) {
pair.getBottomPipe().setState(Pipe.State.dead);
pair.getTopPipe().setState(Pipe.State.dead);
pair.getRuby().setVel(0, 0);
}
}
private void updatePipePairs() {
for (int i = 0; i < pipePairs.size; i++) {
pipePairs.get(i).update();
}
}
private void addPipes(Stage gameplayStage) {
for (int i = 0; i < pipePairs.size; i++) {
gameplayStage.addActor(pipePairs.get(i).getBottomPipe());
gameplayStage.addActor(pipePairs.get(i).getTopPipe());
gameplayStage.addActor(pipePairs.get(i).getRuby());
}
}
private void initThirdSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initThird();
// add the pair to the list
pipePairs.add(pair);
}
private void initSecondSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initSecond();
// add the pair to the list
pipePairs.add(pair);
}
private void initFirstSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initFirst();
// add the pair to the list
pipePairs.add(pair);
}
/**
* Tells libgdx to listen for inputs coming from the InputAdapter we give it
*/
private void initInputProcessor() {
Gdx.input.setInputProcessor(new InputAdapter() {
// We only care about the touch down event
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
switch (screenState) {
case DYING:
justTouched = true;
break;
case DEAD:
if (allowRestart) {
game.setScreen(new GameplayScreen(game));
}
justTouched = true;
break;
case PLAYING:
justTouched = true;
break;
case PREGAME:
justTouched = true;
screenState = State.PLAYING;
bird.setState(Bird.State.ALIVE);
bird.clearActions();
tapToFlap.addAction(Actions.moveToAligned(com.pentagames.flappybibi.FlappyGame.CENTER_X, com.pentagames.flappybibi.FlappyGame.HEIGHT, Align.bottom, .75f, Interpolation.sine));
initFirstSetOfPipes();
initSecondSetOfPipes();
initThirdSetOfPipes();
addPipes(gameplayStage);
gameplayStage.addActor(ground);
gameplayStage.addActor(bird);
break;
}
return true;
}
});
}
}
This is the first time that I'm working with LibGDX, would be great if you can explain me how to implement the Interstitial Ad in this project.
Sorry for my bad English.
You already integrated banner Ad so no need to injected dependent artifact in your project.
Follow these steps for Interstitial Ad integration.
AndroidManifest.xml
Make an entry of AdActivity for Interstitial Ad
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="#android:style/Theme.Translucent" />
Create an interface inside your core module
public interface AdService {
boolean isInterstitialLoaded();
void showInterstitial();
}
Create a parameterized constructor of FlappyGame class
public AdService adService;
public FlappyGame(AdService ads){
adService=ads;
}
Implement AdService interface to your AndroidLauncher class
public class AndroidLauncher extends AndroidApplication implements AdService {
private static final String AD_UNIT_ID_INTERSTITIAL = "ca-app-pub-XXXXX/XXXXX";
private InterstitialAd interstitialAd;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
View gameView=initializeForView(new FlappyGame(this), config);
...
interstitialAd = new InterstitialAd(this);
interstitialAd.setAdUnitId(AD_UNIT_ID_INTERSTITIAL);
interstitialAd.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {}
#Override
public void onAdClosed() {
loadIntersitialAd();
}
});
loadIntersitialAd();
}
private void loadIntersitialAd(){
AdRequest interstitialRequest = new AdRequest.Builder().build();
interstitialAd.loadAd(interstitialRequest);
}
#Override
public void showInterstitial() {
runOnUiThread(new Runnable() {
public void run() {
if (interstitialAd.isLoaded())
interstitialAd.show();
else
loadIntersitialAd();
}
});
}
#Override
public boolean isInterstitialLoaded() {
return interstitialAd.isLoaded();
}
}
GameScreen class
RunnableAction playWooshAction = Actions.run(new Runnable() {
#Override
public void run() {
com.pentagames.flappybibi.Assets.playWooshSound();
game.adService.showInterstitial();
}
});
I integrated Interstitial Ad in your project, created a pull request for the same. You can merge my pull request.