Create a new view from a surface view - android

I have a small application in which i implement a surface view.Now depending on some condition(time) i would like to change the screen to a different layout.How do i do this in the following code.
Sketch of what i am doing.
public class df extends Activity
{
public void onCreate(Bundle savedInstanceState) {
}
class Panel extends SurfaceView implements SurfaceHolder.Callback {
public Panel(Context context){
super(context);
}
public void onDraw(Canvas canvas) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}

Related

take photo from camera in service

How can Take picture from front camera in service without showing camera on screen.
I have service class
public class PhotoTakingService extends Service {
//Camera variables
//a surface holder
private SurfaceHolder sHolder;
//a variable to control the camera
private Camera mCamera;
//the camera parameters
private Parameters parameters;
boolean mPreviewRunning = false;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent,int startId) {
// TODO Auto-generated method stub
super.onStart(intent,startId);
mCamera = Camera.open();
SurfaceView sv = new SurfaceView(getBaseContext());
try {
Camera.Parameters p = mCamera.getParameters();
mCamera.setParameters(p);
mCamera.startPreview();
mCamera.takePicture(null,null,mPictureCallback);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Get a surface
sHolder = sv.getHolder();
//tells Android that this surface will have its data constantly replaced
sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData,Camera c) {
Log.e("Callback TAG","Here in jpeg Callback");
if (imageData != null) {
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream("/sdcard/car_final/Image.jpg");
outputStream.write(imageData);
// Removed the finish call you had here
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) try {
outputStream.close();
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
}
}
};
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
and main activity. I want to call from main activity.
public class MainActivity extends Activity implements SurfaceHolder.Callback {
private static final String TAG = MainActivity.class.getSimpleName();
public static SurfaceView mSurfaceView;
public static SurfaceHolder mSurfaceHolder;
public static Camera mCamera;
public static boolean mPreviewRunning;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Button btnStart = (Button) findViewById(R.id.button1);
btnStart.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(MainActivity.this, PhotoTakingService.class);
//intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
}
});
/* Button btnStop = (Button) findViewById(R.id.StopService);
btnStop.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
stopService(new Intent(CameraRecorder.this, RecorderService.class));
}
});*/
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
When you are in background thread such as service use SurfaceTexture instead of SurfaceHolder. If you are looking for implementation here is a opensource app where I have implemented background video stream and UI video stream both.

SurfaceView with custom thread takes long to appear on screen

I used this tutorial to create a SurfaceView for a game. The tutorial fixed the problems I had with handling the thread but now whenever I open the fragment it takes anywhere between 3 and 15 seconds for the screen to turn yellow.
I thought it might have something to with the code in the container activity but the only thing I changed is this fragment alone. The speed before the change was fine.
public class VirtualMapFragment extends Fragment {
private MapSurfaceView mapSurfaceView;
#Override
public void onResume() {
if (mapSurfaceView != null){
mapSurfaceView.surfaceRestart();
}
super.onResume();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(mapSurfaceView == null)
mapSurfaceView = new MapSurfaceView(getActivity());
return mapSurfaceView;
}
#Override
public void onPause() {
if (mapSurfaceView != null){
mapSurfaceView.surfaceDestroyed(mapSurfaceView.getHolder());
}
super.onPause();
}
private class MapSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceThread surfaceThread;
public MapSurfaceView(Context context) {
super(context);
setFocusable(true);
surfaceThread = new SurfaceThread(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
surfaceThread.restartSurface();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
surfaceThread.terminateSurface();
}
public void surfaceRestart(){
if (surfaceThread != null){
surfaceThread.restartSurface();
}
}
public void doDraw(Canvas canvas){
canvas.drawColor(Color.YELLOW);
}
#Override
public boolean onTouchEvent(MotionEvent event){
return false;
}
}
private class SurfaceThread implements Runnable {
private SurfaceHolder mSurfaceHolder;
private MapSurfaceView mMapSurfaceView;
private Canvas mCanvas;
volatile Thread thread;
public SurfaceThread(MapSurfaceView mapSurfaceView){
mSurfaceHolder = mapSurfaceView.getHolder();
mMapSurfaceView = mapSurfaceView;
mCanvas = new Canvas();
thread = new Thread(this);
thread.start();
}
public void terminateSurface(){
this.thread.interrupt();
}
public void restartSurface() {
if (thread.getState() == Thread.State.TERMINATED){
thread = new Thread(this);
thread.start(); // Start a new thread
}
}
public SurfaceHolder getSurfaceHolder() {
return mSurfaceHolder;
}
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
mCanvas = mSurfaceHolder.lockCanvas(null);
if (mCanvas == null){
mSurfaceHolder = mMapSurfaceView.getHolder();
} else {
synchronized (mSurfaceHolder) {
mapSurfaceView.doDraw(mCanvas);
}
}
} finally {
if (mCanvas != null) {
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}
}
}
}

Error while displaying Camera Preview

I am trying to open a camera preview but I get an
FATAL EXCEPTION: AsyncTask #1 java.lang.RuntimeException: An error
occured while executing doInBackground()
Below is my code:
public class ScanActivity extends Activity implements SurfaceHolder.Callback, OnClickListener {
private SurfaceHolder surface_holder;
protected Camera camera;
protected boolean scanning;
private Animation laser_effect;
private Animation flash_effect;
public static final class id {
public static final int quit = 0;
public static final int found = 1;
public static final int nothing = 2;
public static final int error = 3;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
findViewById(R.id.capture_button).setOnClickListener(this);![enter image description here][1]
}
#Override
protected void onResume() {
super.onResume();
/* open camera if any, returns error otherwise */
camera = Camera.open();
if (camera == null) {
Intent error = new Intent();
error.putExtra("reason", "Camera Error");
setResult(id.error, error);
finish();
}
restartView();
surface_holder = ((SurfaceView) findViewById(R.id.surface_view)).getHolder();
surface_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surface_holder.addCallback(this);
}
#Override
protected void onPause() {
this.scanning=false;
/* release camera */
camera.cancelAutoFocus();
camera.stopPreview();
camera.release();
super.onPause();
}
private void restartView() {
findViewById(R.id.freeze).setVisibility(View.GONE);
findViewById(R.id.loading).setVisibility(View.GONE);
findViewById(R.id.capture_button).setVisibility(View.VISIBLE);
findViewById(R.id.surface_view).setVisibility(View.VISIBLE);
findViewById(R.id.camera_loading).setVisibility(View.GONE);
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.capture_button:
scanning = true;
break;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// void implementation
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
findViewById(R.id.camera_loading).setVisibility(View.VISIBLE);
//we use an AsyncTask to avoid ugly lag when camera is loading...
new InitCamera().execute(holder);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// void implementation
}
private class InitCamera extends AsyncTask<SurfaceHolder, Void, Boolean> {
#Override
protected Boolean doInBackground(SurfaceHolder... holder) {
/* initialize camera parameters and start Preview */
Rect dim = holder[0].getSurfaceFrame();
int w = dim.width();
int h = dim.height();
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(w, h);
camera.setParameters(params);
try {
camera.setPreviewDisplay(surface_holder);
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
return true;
}
#Override
protected void onPostExecute(Boolean a) {
findViewById(R.id.camera_loading).setVisibility(View.GONE);
}
}
}
Most likely, the problem comes from trying to manipulate the UI from a non-UI thread. Examining your stack trace would help confirm this theory. AFAIK, the work that you are doing in doInBackground() should be performed on the main application thread.

surfaceCreated is not called and so thread does not start

following is my simple code, actually i want to log HELLO in the draw() method repeatedly but my surfacecreated method is not called and so thread is not started. plz help me
public class MainActivity extends Activity{
private MyThread myThread ;
Panel _View;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
_View = new Panel(this);
}
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
Canvas canvas;
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
}//end of panel
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
myThread= new MyThread(this);
myThread.setRunning(true);
myThread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
myThread.setRunning(false);
}
public void Draw(Canvas canvas){
super.draw(canvas);
this.canvas = canvas;
Log.d("HELLO", 0+"");
}//end of DRAW()
}//end of Panel class
public class MyThread extends Thread {
Panel panel;
private SurfaceHolder myHolder;
boolean mRun=false;
public MyThread(Panel panel)
{
this.panel= panel;
this.myHolder = panel.getHolder();
}
public void setRunning(boolean run){
this.mRun=run;
}
public void run(){
Canvas canvas = null;
while(mRun)
{
canvas=myHolder.lockCanvas();
if(canvas!=null)
{
panel.Draw(canvas);
}
myHolder.unlockCanvasAndPost(canvas);
}
}
}//MyThread class ends
}//end of bird mania activity
The surface is not created until you add it to the View hierarchy. If it is your only View, you can set it with
setContentView( _View);
in your onCreate() method.

SurfaceView Crashes when returning from another activity

i have a thread problem with my surfaceView, its quite common but i have not found a solution anywhere.
I use a SurfaceView as a Background in a frame layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/blobmusic_layout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.myapp.Background
android:id="#+id/background_blobmusic"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
...
and my background class is the tipical surfaceview class, with the holder, the thread wich will call our onDraw method, etc. Some code to avoid questions (init() is called in the constructor methods):
public void init() {
ready = false;
holder = getHolder();
holder.addCallback( new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
while (retry) {
try {
bgdt.setRunning(false);
bgdt.join();
retry = false;
} catch (InterruptedException e) {}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
holder.setFormat(PixelFormat.RGBA_8888);
estrelles = new Estrelles(getResources(),getHeight());
bgdt.setRunning(true);
bgdt.start();
ready = true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
});
and my thread class (bgtd):
public class BGDrawThread extends Thread {
private Background view;
static final long FPS = 60;
private boolean running = false;
public BGDrawThread(Background view) {
this.view = view;
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean run) {
running = run;
}
#Override
public void run() {
long ticksPS = 1000/FPS;
long startTime;
long sleepTime;
//fps checker
long contms=0;
long lasttimecheck = System.currentTimeMillis();
int fps=0;
while (running) {
if(contms>1000) {
//souts ??
contms=0;
fps=0;
lasttimecheck = System.currentTimeMillis();
}
else {
fps++;
contms+=System.currentTimeMillis()-lasttimecheck;
lasttimecheck=System.currentTimeMillis();
}
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
This works fine, until another activity comes to front and then we come back from it, that crashes.
Here's my code of onpause/onresume methods of the class:
#Override
protected void onResume() {
super.onResume();
Background bmbg = (Background) findViewById(R.id.background_blobmusic);
bmbg.resumethread();
}
#Override
protected void onPause() {
super.onPause();
Background bmbg = (Background) findViewById(R.id.background_blobmusic);
bmbg.stopthread();
}
and the strop/resume thread in the surfaceview class:
public void stopthread() {
if(!bgdt.isAlive()) return;
boolean retry = true;
while (retry) {
try {
bgdt.setRunning(false);
bgdt.join();
retry = false;
} catch (InterruptedException e) {}
}
}
public void resumethread() {
if(ready && !bgdt.isRunning()) {
bgdt.setRunning(true);
bgdt.start();
}
}
All help is welcome :)
EDIT: i made it run (probably not an elegant solution, but i leave the code here):
(look at the comment below to see the other changes)
public void startthread() {
if(!surfacecreated) return;
if(threadrunning) return;
bgdt = new BGDrawThread(this);
bgdt.setRunning(true);
bgdt.start();
threadrunning = true;
}
public void stopthread() {
boolean retry = true;
while (retry) {
try {
bgdt.setRunning(false);
bgdt.join();
threadrunning = false;
retry = false;
} catch (InterruptedException e) {}
}
}
IIRC surface is ready for manipulations only after surfaceChanged() callback, not surfaceCreated() , and surfaceChanged() is called after onResume() - move your initialisation and thread startup there ( to surfaceChanged() )

Categories

Resources