I'm developing an Android app that have a overlay view that the user can access from anywhere.
I have taken the code from the following question:
Overlay
Put it simple, a class "HUD" that call a subclass ViewGroup"HUDView", containing all the necessary elements.
Now I want to add in this ViewGroup also a SeekBar that, on progress change, draw a Canvas every time: for example seekBar progress =1, draw a circle with 10° angle, progress=2, redraw the circle with 20° angle, and so on...
The circle and the seekbar must overlay the actual screen from everywhere.
I've managed to put the Canvas (created in the onDraw method of the ViewGroup) and the seekBar (created in the onCreate method of the HUD class, also with his listener).
In the method "onProgressChanged" I would like to redraw the circle, but this doesnt seems to work.
Here the listener code:
// SeekBar Change Listener
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progresValue, boolean fromUser) {
mView = new HUDView(getApplicationContext());
progress = progresValue;
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.CENTER | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
//Toast.makeText(getApplicationContext(), "Started tracking seekbar", Toast.LENGTH_SHORT).show();
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
//textView.setText("Covered: " + progress + "/" + seekBar.getMax());
//Toast.makeText(getApplicationContext(), "Stopped tracking seekbar", Toast.LENGTH_SHORT).show();
}
});
Here the onDraw method of the HUDView:
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final RectF oval = new RectF();
oval.set(30, 30, 450, 450);
Bitmap bg = Bitmap.createBitmap(480, 480, Bitmap.Config.ARGB_8888);
canvas.drawArc(oval, 90, progress*10 , true, paint);
}
Related
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
button.setOnClickListener(this);
int height = this.getWindow().getDecorView().getHeight();
int width = this.getWindow().getDecorView().getWidth();
bitmap = Bitmap.createBitmap(height, width, Bitmap.Config.ARGB_8888 );
canvas = new Canvas(bitmap);
imageView = findViewById(R.id.imageView);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.button){
canvas.drawColor(Color.RED);
}
imageView.setImageBitmap(bitmap);
}
}
Does anyone have any idea why the above code snippet for Android Studio would cause the app to crash constantly? I'm new to Android Studio and I want to get used to building rectangles and shapes before anything more, but it seems I'm having difficulty with even that.
Displays error of drawing Bitmap with values not > 0, but the issue is that after using a print function in onClick, grabbing height or width from either window or the imageView, I am returned a value > 0, so I don't understand.
You are getting height and width in onCreate method before view has been drawn and thus resulting in returning height 0, width 0 since android system don't know exact width and height of view.You can use some method like post(Runnable) to know if view has drawn.Modify you code like below.
View view = this.getWindow().getDecorView();
view.post( new Runnable() {
#Override
public void run() {
width = view.getMeasuredWidth();
height = view.getMeasuredHeight();
bitmap = Bitmap.createBitmap(height, width, Bitmap.Config.ARGB_8888 );
canvas = new Canvas(bitmap);
}
});
for some time I've been working on this app, that allows user to take photos. The interesting thing about it, is that there should be some lines drawn over camera preview. The problem is that I'm not quite sure how to do this. I do have codes to initiate camera and to draw line, but I do not know how to merge them.
I use this code to initiate camera on button click:
initCamera.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
//Starting a new Intent
/*Intent nextScreen = new Intent(getActivity().getApplicationContext(), CameraActivity.class);
startActivity(nextScreen);*/
count++;
String file = dir+count+".jpg";
File newfile = new File(file);
try {
newfile.createNewFile();
} catch (IOException e) {}
Uri outputFileUri = Uri.fromFile(newfile);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, TAKE_PHOTO_CODE);
}
});
And here's how I usually draw lines:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
height = displaymetrics.heightPixels;
width = displaymetrics.widthPixels;
imageView1 = (ImageView) findViewById(R.id.imageView1);
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
bmp = Bitmap.createBitmap(width, height, conf);
canvas = new Canvas(bmp);
p = new Paint();
p.setColor(Color.RED);
imageView1.setImageBitmap(bmp);
p.setStrokeWidth(5);
canvas.drawLine(0, height/2, width, height/2, p);
You will need an overlay to draw on top of the live camera preview. The overlay is a child class of the surface the preview is drawn on. The preview class looks something like this:
class Preview extends ViewGroup implements SurfaceHolder.Callback, Camera.PreviewCallback
{
Preview(Context context)
{
super(context);
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
mSurfaceView = new SurfaceView(PreviewContext);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
PreviewCameraOverlay = new CameraOverlay(context);
addView(PreviewCameraOverlay);
}
// Additional functions like:
// surfaceChanged(SurfaceHolder holder, int format, int width, int height)
// onPreviewFrame(byte[] data, Camera pCamera)
// etc.
}
protected class CameraOverlay extends View
{
public CameraOverlay(Context context)
{
super(context);
setWillNotDraw(false);
setBackgroundColor(Color.TRANSPARENT);
setAlpha(1f);
OverlayPaint = new Paint[PaintColors];
}
// Additional functions:
// onDraw(Canvas canvas)
// onMeasure(int widthMeasureSpec, int heightMeasureSpec)
}
From your main activity you would call: Preview CameraPreview = new Preview(this); and draw whatever it is you want to draw from CameraOverlay's onDraw().
I have an android device, it can only run a app (like ATM screen). Now I want to implement the following feature:
If the device is not in use for over 30 minutes, I will adjust the screen brightness to the lowest. At this time, if I touch the screen, I should adjust the screen brightness to the maximum. The user can not see any Android system menu, application, etc. They only can use this app (can't close it). This app will run in this device from the power on it and power off it.
I don't how to implement this feature.
Thanks.
You can use a class that extends service and can dim the screen brightness. Use AlarmManager to check the time that the user never touches the screen. I will give you an example of using the Service class:
public class DimScreen extends Service {
public static int ID_NOTIFICATION = 2018;
private WindowManager windowManager;
private LinearLayout saverScreen;
private PopupWindow pwindo;
boolean mHasDoubleClicked = false;
long lastPressTime;
private Boolean _enable = true;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
saverScreen = new LinearLayout(this);
saverScreen.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
Bitmap sample = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
saverScreen.setBackground(new BitmapDrawable(this.getResources(),
convertColorIntoBlackAndWhiteImage(sample)));
saverScreen.setClickable(false);
saverScreen.setFocusable(false);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FILL_PARENT,
WindowManager.LayoutParams.FILL_PARENT,
PixelFormat.TRANSLUCENT);
params.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|WindowManager.LayoutParams.FLAG_DIM_BEHIND;
params.dimAmount = (float) 0.6;
params.screenBrightness = (float) 0.3;
params.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE;
windowManager.addView(saverScreen, params);
}
#Override
public void onDestroy() {
super.onDestroy();
if (saverScreen != null) windowManager.removeView(saverScreen);
}
private Bitmap convertColorIntoBlackAndWhiteImage(Bitmap orginalBitmap) {
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(2);
ColorMatrixColorFilter colorMatrixFilter = new ColorMatrixColorFilter(
colorMatrix);
Bitmap blackAndWhiteBitmap = orginalBitmap.copy(
Bitmap.Config.ARGB_8888, true);
Paint paint = new Paint();
paint.setColorFilter(colorMatrixFilter);
Canvas canvas = new Canvas(blackAndWhiteBitmap);
canvas.drawBitmap(blackAndWhiteBitmap, 0, 0, paint);
return blackAndWhiteBitmap;
}
}
In your Activity class call
startService(new Intent(this,DimScreen.class));
You only have to implement the AlarmManager now. If the user never touches the screen, launch the Service class. If the user Interrupt with the app, then call stopService.
Try this
WindowManager.LayoutParams localLayoutParams = getWindow()
.getAttributes();
localLayoutParams.screenBrightness = 0.12F;
getWindow().setAttributes(localLayoutParams);
I first created a custom Surface View to draw things on; to visually describe, a green background on which I draw some lines and circles. Then, I decided to remove the green background and have a live camera preview as the background instead. This is what I tried, but could not get it working (below). What happens is, both the camera view and my custom surface view are being created, but only the camera view is being shown. I'm sure my custom Surface View is also created because I've a TouchListener in this custom view that prints x,y values when touched (and this happens). But my custom drawing is not being shown over the camera preview, as I want it to be. Please help!!
gameview.xml file:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</FrameLayout>
Camera View:
public class CameraView extends SurfaceView implements SurfaceHolder.Callback{
Camera camera;
public CameraView(Context context, Camera c) {
super(context);
camera = c;
getHolder().addCallback(this);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// TODO Auto-generated constructor stub
}
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
try {
camera.setPreviewDisplay(getHolder());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();
}
}
Custom Surface View named VirtuaParkView: This is where I draw stuff using onDraw() method being called continuously from a thread. Also implements SurfaceHolder.Callback. Code not written here for brevity.
How it's all put together:
CameraView cView = new CameraView(getApplicationContext(),Camera.open()); //get Camera View
VirtuaParkView vParkView = new VirtuaParkView(getApplicationContext()); // get custom surface view
setContentView(R.layout.gameview); //set the Frame layout
FrameLayout fl = (FrameLayout)findViewById(R.id.mainlayout); // get the layout root
fl.addView(cView); //add camera view
fl.addView(vParkView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); //add custom drawing
I don't know what your VirtualParkView looks like but try using this custom View. It should draw a small green square where you touch it.
public class CameraOverlay extends View {
private static final Integer rectSize = 30;
Paint paint;
private Rect touchRect;
public CameraOverlay(Context context) {
super(context);
paint = new Paint();
touchRect = new Rect(0,1,0,1);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
int height = canvas.getHeight();
int width = canvas.getWidth();
canvas.drawLine(width/2,0,width/2,height,paint);
canvas.drawLine(0,height/2,width,height/2,paint);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
canvas.drawRect(touchRect, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "CameraOverlay - onTouchEvent()");
invalidate();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
float x = event.getX();
float y = event.getY();
touchRect.left = (int) (x - rectSize);
touchRect.top =(int) (y - rectSize);
touchRect.right = (int) (x + rectSize);
touchRect.bottom = (int) (y + rectSize);
}
return false;
}
}
Then, instead of your VirtualParkView, add this to your frame -
if (mCameraOverlay == null)
mCameraOverlay = new CameraOverlay(this);
f1.addView(mCameraOverlay);
I have seen lots of tutorial and information but i could not find any single place how to use the default settings of the existing camera application into any other customized camera application. I have seen the sharpness of the image and its focus is very fine in the built-in camera application. Now i am creating my own application with my customized features but i am still unable to make it sharp and non-blurry... I dont want to use Intent technique of the camera because i have to do some image processing afterward.
I have used zooming but strangely zoom is not properly working ...like it works in built-in camera application
here is my surface change code
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.e(TAG, "surfaceChanged");
// XXX stopPreview() will crash if preview is not running
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
mFrameWidth = w;
mFrameHeight = h;
// selecting optimal camera preview size
{
double minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes)
{
if (Math.abs(size.height - h) < minDiff)
{
mFrameWidth = size.width;
mFrameHeight = size.height;
minDiff = Math.abs(size.height - h);
}
}
}
try
{
//params.set("rotation", 180);
//params.set("orientation", "landscape");
//params.set("auto", "WHITE_BALANCE_AUTO");//WHITE_BALANCE_AUTO
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
params.setPreviewSize(mFrameHeight, mFrameWidth);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90)
{
params.setPreviewSize(mFrameWidth, mFrameHeight);
}
if(display.getRotation() == Surface.ROTATION_180)
{
params.setPreviewSize(mFrameHeight, mFrameWidth);
}
if(display.getRotation() == Surface.ROTATION_270)
{
params.setPreviewSize(mFrameWidth, mFrameHeight);
mCamera.setDisplayOrientation(180);
}
if(params.isZoomSupported())
{
Log.e(TAG, params.getZoom()+"surfaceChanged camer zoom"+params.getMinExposureCompensation());
params.setZoom(params.getMaxZoom());
params.setExposureCompensation(1);
// params.setColorEffect("none");
params.setWhiteBalance(params.WHITE_BALANCE_AUTO);
params.setFocusMode(params.FOCUS_MODE_AUTO);
params.setSceneMode(params.SCENE_MODE_ACTION);
}
params.set("auto", "FOCUS_MODE_AUTO");
params.setPreviewSize(mFrameWidth,mFrameHeight);
mCamera.setParameters(params);
mCamera.setPreviewDisplay(holder);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
Kindly let me know how to make the camera preview exactly same as the built in application one.
You mean a fullscreen camera preview?
I use this code:
this.requestWindowFeature(Window.FEATURE_NO_TITLE); //no title
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //no status bar, etc
and this:
setContentView(R.layout.main);
addContentView(overlay, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
((FrameLayout) findViewById(R.id.preview)).addView(preview);
the first snippet sets the app to fullscreen and hide title and status bar.
the second snipppet adds my overlay (extended View) to the main layout.
Here my xml and java code:
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher" />
</LinearLayout>
Overlay.java:
class Overlay extends View {
String text = "";
String textBearing = "Bearing: ";
public Overlay(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setTextSize(16);
canvas.drawText(text, 20, 20, paint);
canvas.drawText(textBearing, 20, 50, paint);
super.onDraw(canvas);
}
}
And my activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE); //no title
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //fullscreen
overlay = new Overlay(this);
setContentView(R.layout.main);
addContentView(overlay, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
camera = getCameraInstance(); //camera.open();
preview = new Preview(this, camera);
((FrameLayout) findViewById(R.id.preview)).addView(preview);
}
Hope it helps
I encountered the same problem with you. After reading the source code of the builtin camera app, and comparing the focus processing of builtin camera and my own camera, I realized the problem is on autofocus.
So try this:
mCamera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
mCamera.takePicture(null, null, mPicture);
}
});
which makes the result image as sharp as builtin camera.
The documents is here.