I'm following this tutorial to learn Android's Camera API. I made it the end of the first section (right before "Providing an overlay" begins), and I'm getting the following error:
06-20 23:33:50.903: ERROR/AndroidRuntime(1114): at android.hardware.Camera.startPreview(Native Method)
06-20 23:33:50.903: ERROR/AndroidRuntime(1114): at com.sobel.Sobel.startCamera(Sobel.java:73)
06-20 23:33:50.903: ERROR/AndroidRuntime(1114): at com.sobel.Sobel.surfaceChanged(Sobel.java:36)
(Full trace)
Git repo here. Main Activity here. Manifest here.
I checked and re-checked my code and have followed the tutorial to a t, so what could be causing this error?
Try setting the type of Surface in initCamera().
private void initCamera() {
mCamSV = (SurfaceView)findViewById(R.id.surface_camera);
mCamSH = mCamSV.getHolder();
mCamSH.addCallback(this);
**mCamSH.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);**
}
EDIT 1
I am copying all the files here which worked for me with android 2.2 sdk
Activity
package com.stack.camera;
import java.io.IOException;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.FrameLayout;
public class CameraStackActivity extends Activity implements SurfaceHolder.Callback {
private Camera mCam;
private SurfaceView mCamSV;
private SurfaceHolder mCamSH;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
initCamera();
}
#Override
public void onDestroy() {
stopCamera();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
startCamera(holder, width, height);
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mCam = Camera.open();
try {
mCam.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
private void initCamera() {
mCamSV = (SurfaceView)findViewById(R.id.surface_camera);
mCamSH = mCamSV.getHolder();
mCamSH.addCallback(this);
mCamSH.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
private void startCamera(SurfaceHolder sh, int width, int height) {
Camera.Parameters p = mCam.getParameters();
// Camera.Size s = p.getSupportedPreviewSizes().get(0);
p.setPreviewSize(width, height);
mCam.setParameters(p);
try {
mCam.setPreviewDisplay(sh);
} catch (Exception e) {
}
mCam.startPreview();
}
private void stopCamera() {
mCamSH.removeCallback(this);
mCam.stopPreview();
mCam.release();
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<SurfaceView android:id="#+id/surface_camera"
android:layout_width="fill_parent" android:layout_height="fill_parent" />
</FrameLayout>
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.stack.camera"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name="CameraStackActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Check if it still doesnt work out for you.
Related
I tried to set an Android camera preview on my Activity but failed. There's nothing but black screen on my surface View. Seems to be too simple for others but I still cannot figure it out.
Here's my code:
package com.example.peterchen.camerapreviewexample;
import android.hardware.Camera;
import android.graphics.PixelFormat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
Camera myCamera;
SurfaceView previewSurfaceView;
SurfaceHolder previewSurfaceHolder;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
previewSurfaceView = (SurfaceView)findViewById(R.id.surfaceView);
previewSurfaceHolder = previewSurfaceView.getHolder();
previewSurfaceHolder.addCallback(this);
previewSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onResume() {
super.onResume();
myCamera.open();
myCamera.startPreview();
}
#Override
public void onPause() {
myCamera.stopPreview();
myCamera.release();
myCamera=null;
super.onPause();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {}
}
my layout xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.peterchen.camerapreviewexample.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="#+id/textView" />
<SurfaceView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/surfaceView"
android:layout_alignParentRight="true"
android:layout_below="#+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true" />
</RelativeLayout>
and my manifest xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.peterchen.camerapreviewexample">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
Great thanks to all of you guys.
You can try to below 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" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical" >
<SurfaceView
android:id="#+id/surfaceview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1" >
<Button
android:id="#+id/startcamerapreview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="Show Preview" />
<Button
android:id="#+id/stopcamerapreview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="Stop Preview" />
</LinearLayout>
</LinearLayout>
AndroidCamera.java
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class AndroidCamera extends Activity implements SurfaceHolder.Callback
{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Button buttonStartCameraPreview, buttonStopCameraPreview;
boolean previewing = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStartCameraPreview = (Button) findViewById(R.id.startcamerapreview);
buttonStopCameraPreview = (Button) findViewById(R.id.stopcamerapreview);
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
buttonStartCameraPreview.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if (!previewing)
{
camera = Camera.open();
if (camera != null)
{
try
{
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
buttonStopCameraPreview.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if (camera != null && previewing)
{
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
}
});
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// TODO Auto-generated method stub
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.camera.preview"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.CAMERA" >
</uses-permission>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".AndroidCamera"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Replace "AndroidCamera.java" your 90 Degree Screen Rotate Problem Solve
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class AndroidCamera extends Activity implements SurfaceHolder.Callback
{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Button buttonStartCameraPreview, buttonStopCameraPreview;
boolean previewing = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStartCameraPreview = (Button) findViewById(R.id.startcamerapreview);
buttonStopCameraPreview = (Button) findViewById(R.id.stopcamerapreview);
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
buttonStartCameraPreview.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if (!previewing)
{
camera = Camera.open();
if (camera != null)
{
try
{
camera.setDisplayOrientation(90);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
buttonStopCameraPreview.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if (camera != null && previewing)
{
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
}
});
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// TODO Auto-generated method stub
}
}
I try to display camera preview on a surface. but it just display black surface. What should I do ? I put the code below
Thanks for your help
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
public class MainActivity extends ActionBarActivity implements SurfaceHolder.Callback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().setFormat(PixelFormat.UNKNOWN);
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Camera camera = Camera.open();
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<SurfaceView
android:id="#+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.frontcamerateststartup" >
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
............................................................................................................................................................................
put the following code in surfaceCreated()
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
The surface needs to be setup before use
Hi I want to play a media(video) file on surfaceview, so I am trying in follwing way.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myProject" >
<permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<SurfaceView
android:id="#+id/surfView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
Then I have created a /raw folder under /res folder and added a video(newmovie.mp4) in it.
Now In MainActivity I am trying to play that video in this way.
package com.example.myProject;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.app.Activity;
import android.app.Fragment;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.view.LayoutInflater;
import android.media.MediaPlayer.OnPreparedListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends Activity implements SurfaceHolder.Callback,OnPreparedListener{
private MediaPlayer mediaPlayer;
private SurfaceHolder vidHolder;
private SurfaceView vidSurface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vidSurface = (SurfaceView) findViewById(R.id.surfView);
vidHolder = vidSurface.getHolder();
vidHolder.addCallback(this);
vidHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_main, container,
false);
return rootView;
}
}
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mediaPlayer.start();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
String fileName = "android.resource://" + getPackageName() + "/" + R.raw.newmovie;
mediaPlayer.setDataSource(this, Uri.parse(fileName));
mediaPlayer.setDisplay(vidHolder);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.prepare();
}
catch(Exception e){
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
But I am getting error as 'E/MediaPlayer﹕ Error (1,-38)' after running this application as a result getting blank screen.
Also getting error as 'E/MediaPlayer﹕ Should have subtitle controller already set' which can be neglected as it will not stop to play video file.
When I tried to debug and see the file-name at run-time is like "android.resource://com.example.myProject/21348349", but my video resides in res/raw/ folder. How android gets my video at run-time ?
Can anyone guide me for this what is the meaning of this error and how can I resolve it.
I am using two different Layouts for same Activity, On orientation change the activity state is not maintained. Please suggest how to do that?
You can easily store your "activity state" using onSavedInstanceState. For example:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(saveInstanceState != null) {
if(savedInstanceState.getBoolean("running") == true) {
// previously is running
} else {
// previously not running
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(condition) {
outState.putBoolean("running", true);
}
}
You seem to do some work in an AsyncTask and then you're changing the orientation.
Move the task you're doing from AsyncTask in an IntentService. Once the job is executed, send a broadcast with the result. In your activity, register a BroadcastReceiver in onCreate and de-register it in onDestroy.
That receiver will handle the result of your operation. You could also send from IntentService some intermediary data/progress update that can be received and processed by the same Receiver.
EDIT: to show some code.
The first search result on Google for IntentService tutorial. But I would strongly recommend reading more about Services. Also Vogella has a nice article about this.
About BroadcastReceivers.
If you want something to get you started here's a sample project I built in 15 mins:
The activity:
package com.adip.droid.sampleandroid;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class FrontActivity extends FragmentActivity {
private TextView labelData;
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WorkerService.WORK_PROGRESS_ACTION.equals(action)) {
publishProgress(intent.getStringExtra(WorkerService.WORK_KEY_PROGRESS));
} else if (WorkerService.WORK_END_ACTION.equals(action)) {
workInProgress = false;
publishResult(intent.getStringExtra(WorkerService.WORK_KEY_RESULT));
}
}
};
protected void publishProgress(String data) {
showMessage(data);
}
protected void publishResult(String data) {
showMessage(data);
}
private void showMessage(String data) {
labelData.setText(data);
}
/**
* Maybe you need this in order to not start the service once you have an ongoing job ...
* */
private boolean workInProgress;
#Override
protected void onCreate(Bundle instanceState) {
super.onCreate(instanceState);
setContentView(R.layout.front_layout);
if (instanceState != null) {
workInProgress = instanceState.getBoolean("WORK_IN_PROGRESS", false);
}
labelData = (TextView) findViewById(R.id.labelData);
findViewById(R.id.btnWorker).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
doTheJob();
}
});
IntentFilter filter = new IntentFilter(WorkerService.WORK_END_ACTION);
filter.addAction(WorkerService.WORK_PROGRESS_ACTION);
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
}
protected void doTheJob() {
if (workInProgress) {
return;
}
Intent serviceIntent = new Intent(this, WorkerService.class);
serviceIntent.setAction(WorkerService.WORK_START_ACTION);
startService(serviceIntent);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("WORK_IN_PROGRESS", workInProgress);
}
#Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
}
its layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/btnWorker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Start the work" />
<TextView
android:id="#+id/labelData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/btnWorker"
android:layout_centerHorizontal="true"
android:layout_marginBottom="35dp"
android:freezesText="true"
android:text="No data yet"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
and the IntentService:
package com.adip.droid.sampleandroid;
import android.app.IntentService;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
public class WorkerService extends IntentService {
public static final String WORK_START_ACTION = "WORK_START_ACTION";
public static final String WORK_END_ACTION = "WORK_END_ACTION";
public static final String WORK_KEY_RESULT = "WORK_KEY_RESULT";
public static final String WORK_PROGRESS_ACTION = "WORK_PROGRESS_ACTION";
public static final String WORK_KEY_PROGRESS = "WORK_KEY_PROGRESS";
public WorkerService() {
super("WorkerService");
}
#Override
protected void onHandleIntent(Intent intent) {
if (WORK_START_ACTION.equals(intent.getAction())) {
startProgress();
}
}
private void startProgress() {
publishProgress("Starting the job");
synchronized (this) {
try {
wait(2500);
} catch (InterruptedException ignored) {
}
}
publishProgress("Progress Point A");
synchronized (this) {
try {
wait(2500);
} catch (InterruptedException ignored) {
}
}
publishJobDone();
}
public void publishProgress(String data) {
Intent progressIntent = new Intent(WORK_PROGRESS_ACTION);
progressIntent.putExtra(WORK_KEY_PROGRESS, data);
LocalBroadcastManager.getInstance(this).sendBroadcast(progressIntent);
}
public void publishJobDone() {
Intent progressIntent = new Intent(WORK_END_ACTION);
progressIntent.putExtra(WORK_KEY_RESULT, "Job done!");
LocalBroadcastManager.getInstance(this).sendBroadcast(progressIntent);
}
}
Also don't forget to update your manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.adip.droid.sampleandroid"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".FrontActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".WorkerService"
android:exported="false" >
</service>
</application>
</manifest>
I created a preference files for my slide show Live Wallpaper.
Most of the source are copied from several samples. I think I copied them correctly, and the eclipse shows no warnings or errors for my source.
My problem is that the "Settings" button doesn't appear when I choose the Live Wallpaper.
I checked the very close question "Can't get settings button to display for live wallpaper", but it didn't solve my problem.
I suspect something is wrong with my Manifest, or preference sources, but I couldn't find the point.
Sorry for my bad English.
My sources are follows:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="sample.slide_wallpaper"
android:versionCode="1"
android:versionName="1.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:icon="#drawable/icon"
android:label="#string/app_name">
<!-- =========================================================== -->
<!-- Launcher -->
<activity android:name=".Launcher" android:label="#string/app_name"
android:theme="#style/Theme.HalfTrans">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- ==============================================================-->
<!-- Live Wallpaper -->
<service
android:enabled="true"
android:permission="android.permission.BIND_WALLPAPER"
android:label="#string/app_name"
android:name="SlideWallpaper"
android:icon="#drawable/thumbnail">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService"></action>
</intent-filter>
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/wallpaper">
</meta-data>
</service>
<!-- ================================================================= -->
<!-- Preferences -->
<activity
android:name="sample.slide_wallpaper.Prefs"
android:label="#string/wallpaper_settings"
android:theme="#android:style/Theme.WallpaperSettings"
android:exported="true">
<intent-filter>
<category android:name="android.intent.category.PREFERENCE" />
</intent-filter>
</activity>
</application>
</manifest>
settings.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="#string/wallpaper_settings"
>
<ListPreference
android:key="timer_key"
android:title="#string/list_title"
android:summary="#string/list_summary"
android:entries="#array/timer_pref"
android:entryValues="#array/timer_pref_values"
android:defaultValue="5000"
/>
</PreferenceScreen>
**wallpaper.xml**
<?xml version="1.0" encoding="utf-8" ?>
<wallpaper xmlns:android="http://shemas.android.com/apk/res/android"
android:thumbnail="#drawable/thumbnail"
android:description="#string/description"
android:settingsActivity="sample.slidewallpaper.Prefs"
/>
**Prefs.java**
package sample.slide_wallpaper;
import sample.slide_wallpaper.R;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.util.Log;
public class Prefs extends PreferenceActivity
implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
Log.w("Prefs", "prefs onCreate");
addPreferencesFromResource(R.xml.settings);
}
#Override
protected void onDestroy()
{
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
}
}
SlideWallpaper.java
package sample.slide_wallpaper;
import java.util.Random;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.WindowManager;
import android.content.SharedPreferences;
import android.content.res.Resources;
//WallpaperService
public class SlideWallpaper extends WallpaperService {
// Path for Prefs
public static final String SHARED_PREFS_NAME = "sample.slide_wallpaper.Prefs";
#Override
public void onCreate() {
.....
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public WallpaperService.Engine onCreateEngine() {
return new WallpaperEngine(getResources());
}
//*********************************************************
//Wallpaper Engine
//*********************************************************
public class WallpaperEngine extends Engine
implements SharedPreferences.OnSharedPreferenceChangeListener {
private final Handler handler=new Handler();
SharedPreferences prefs;
public Bitmap img;
private Bitmap images[] = new Bitmap[5];
private Bitmap eximg;
private final Random randGen = new Random();
private static final String TAG = "WallpaperEngine";
//timer
private long timer = 5000;//interval(sec)×1000
private long startTime = 0;
private int currentAlpha;
private final Paint imagePaint;
private final Runnable drawThread=new Runnable() {
public void run() {
Log.d(TAG,"runnable");
drawFrame();
}
};
public WallpaperEngine(Resources r) {
prefs=SlideWallpaper.this.getSharedPreferences(SHARED_PREFS_NAME, 0);
prefs.registerOnSharedPreferenceChangeListener(this);
images[0]=BitmapFactory.decodeResource(r,R.drawable.imgA);
images[1]=BitmapFactory.decodeResource(r,R.drawable.imgB);
images[2]=BitmapFactory.decodeResource(r,R.drawable.imgC);
images[3]=BitmapFactory.decodeResource(r,R.drawable.imgD);
images[4]=BitmapFactory.decodeResource(r,R.drawable.imgE);
eximg = BitmapFactory.decodeResource(r,R.drawable.bg1);
img = eximg;
imagePaint = new Paint();
imagePaint.setAlpha(255);
}
//=============================
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
Log.w(TAG, "onPreferenceChanged");//this Log doesn't show up
String listString = prefs.getString("timer_key", "5000");
int listInt = Integer.parseInt(listString);
timer = listInt;
}
//=================================
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
Log.d(TAG, "onCreate");
drawFrame();
}
//=====================================
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(fadeAnimate);
handler.removeCallbacks(drawThread);
}
//==================================
#Override
public void onVisibilityChanged(boolean visible) {
Log.d(TAG, "Visibility changed");
if (visible) {
if(nowTime() - startTime + 100 < timer){
if (img.isRecycled()) {
img = eximg;
}
drawBitmap(img);
handler.postDelayed(drawThread, timer - (nowTime() - startTime));
}else {
drawFrame();
}
} else {
handler.removeCallbacks(fadeAnimate);
handler.removeCallbacks(drawThread);
}
}
//===================================================
//draws bitmap
private void drawBitmap(Bitmap b) {
............
}
//=========================
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
}
//============================
#Override
public void onSurfaceChanged(SurfaceHolder holder,
int format,int width,int height) {
super.onSurfaceChanged(holder,format,width,height);
drawFrame();
}
//==============================
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
handler.removeCallbacks(fadeAnimate);
handler.removeCallbacks(drawThread);
}
//=================================
#Override
public void onOffsetsChanged(float xOffset,float yOffset,
float xStep,float yStep,int xPixels,int yPixels) {
drawBitmap(img);
}
//=================================================
//Changes image==================================
protected void drawFrame() {
.....
}
private final Runnable fadeAnimate = new Runnable() {
public void run() {
fadeTransition(img, currentAlpha);
}
};
private void fadeTransition(Bitmap b, int alpha) {
.....
}//END fadeTransition
private long nowTime() {
return System.nanoTime() / 1000000;
}
}//Engine
}//END
I really need your help!!
Also, the thumbnail image doesn't show up on the Live Wallpaper list. But this is a small problem.
Your wallpaper.xml has a minor error. The package name is incorrect. It should be:
<?xml version="1.0" encoding="utf-8" ?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
android:thumbnail="#drawable/thumbnail"
android:description="#string/description"
android:settingsActivity="sample.slide_wallpaper.Prefs"
/>
I solved the problem by myself.
Thanks for Rajesh, I rewrote the whole code of "wallpaper.xml", and it worked correctly.
Actually, I couldn't find the difference, but my revised version is this:
<?xml version="1.0" encoding="utf-8" ?>
<wallpaper
xmlns:android="http://schemas.android.com/apk/res/android"
android:thumbnail="#drawable/thumbnail"
android:description="#string/description"
android:settingsActivity="sample.slide_wallpaper.Prefs"
/>
By revising the source, the thumbnail error was shown up, too!