I am making an Guitar app that have 3 activities and each activity include a audio function, reason why i am using SoundPool, and I have 66 samples.
My problem is that I have to load them in each and every activity, so my question is, is there any way that I upload those 66 samples right after my app starts, and keep them loaded in every activity ?
You can use a simple utility class for SoundPool. You can use a public static method so that it can be instantiated once and be accessed from any activity. Here a class that can be used for your case:
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.util.Log;
public class SoundPoolManager {
private static final String TAG = SoundPoolManager.class.getSimpleName();
private static SoundPool soundPool;
private static int[] sm;
private Context context;
private static float mVolume;
private static SoundPoolManager instance;
private static final int SOUND_TOTAL = 1;
private SoundPoolManager(Context context) {
this.context = context;
initSound();
// add sound here
// here the sample audio file which can be use with your audio file
int soundRawId = R.raw.watch_tick;
//you need to change SOUND_TOTAL for the size of the audio samples.
sm[sm.length - 1] = soundPool.load(context, soundRawId, 1);
}
public static void instantiate(Context context) {
if(instance == null) instance = new SoundPoolManager(context);
}
private void initSound() {
sm = new int[SOUND_TOTAL];
int maxStreams = 1;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
soundPool = new SoundPool.Builder()
.setMaxStreams(maxStreams)
.build();
} else {
soundPool = new SoundPool(maxStreams, AudioManager.STREAM_MUSIC, 0);
}
mVolume = setupVolume(context);
}
private float setupVolume(Context context) {
AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if(am == null) {
Log.e(TAG, "Can't access AudioManager!");
return 0;
}
float actualVolume = (float) am.getStreamVolume(AudioManager.STREAM_ALARM);
float maxVolume = (float) am.getStreamMaxVolume(AudioManager.STREAM_ALARM);
return actualVolume / maxVolume;
}
public static void playSound(int index) {
if(sm == null) {
Log.e(TAG, "sm is null, this should not happened!");
return;
}
if(soundPool == null) {
Log.e(TAG, "SoundPool is null, this should not happened!");
return;
}
if(sm.length <= index) {
Log.e(TAG, "No sound with index = " + index);
return;
}
if(mVolume > 0) {
soundPool.play(sm[index], mVolume, mVolume, 1, 0, 1f);
}
}
public static void cleanUp() {
sm = null;
if(soundPool != null) {
soundPool.release();
soundPool = null;
}
}
}
Then you can use the class with the following:
// need to call this for the first time
SoundPoolManager.instantiate(context);
// play the sound based on the index
SoundPoolManager.playSound(index);
// clear up the SoundPool when you don't need it anymore.
SoundPoolManager.cleanUp();
Related
I'm trying to create a plugin in java for Unity, I have already succeeded to fetch and get all connected midi devices, but now I'm stuck to get the pressed notes.
On java side I have theses classes :
public class UnityMidiAndroid {
private static UnityMidiAndroid _instance = new UnityMidiAndroid();
private static final String LOGTAG = "UnityMidiAndroid";
private MidiManager manager = null;
private MidiDeviceInfo[] midiDeviceInfos;
private MidiOutputPort midiOutputPort;
private final UnityMidiAndroidReceiver midiReceiver;
private MidiCallback midiCallback = null;
private UnityMidiAndroid()
{
Log.i(LOGTAG, "Ctor Created new UnityMidiAndroid");
midiReceiver = new UnityMidiAndroidReceiver();
}
public static UnityMidiAndroid getInstance()
{
return (_instance);
}
public void ctor(MidiCallback callback, Activity activity)
{
Context context = activity.getApplicationContext();
manager = (MidiManager) context.getSystemService(MIDI_SERVICE);
midiCallback = callback;
}
public String[] fetchDevices()
{
midiDeviceInfos = manager.getDevices();
String[] availableDevices = new String[midiDeviceInfos.length];
for (int i = 0; i < midiDeviceInfos.length; i++) {
Bundle property = midiDeviceInfos[i].getProperties();
String deviceName = property.getString(MidiDeviceInfo.PROPERTY_PRODUCT);
if (deviceName != null)
availableDevices[i] = deviceName;
}
return (availableDevices);
}
public void openDeviceAtIndex(int index)
{
if (midiDeviceInfos == null || midiDeviceInfos.length == 0)
midiDeviceInfos = manager.getDevices();
if (midiDeviceInfos.length == 0)
return;
openDevice(midiDeviceInfos[0]);
}
private void openDevice(MidiDeviceInfo deviceInfo)
{
if (deviceInfo == null)
return;
manager.openDevice(deviceInfo, device -> {
if (device == null)
Log.e(LOGTAG, "couldn't open " + deviceInfo.toString());
else {
midiOutputPort = device.openOutputPort(0);
if (midiOutputPort == null)
Log.e(LOGTAG, "couln't open input port on " + device);
midiOutputPort.connect(midiReceiver);
}
}, null);
}
private class UnityMidiAndroidReceiver extends MidiReceiver {
#Override
public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
if (midiCallback == null)
throw new IOException("midiCallback = null");
midiCallback.MidiMessage(0, msg);
midiReceiver.send(msg, offset, count);
}
}
public interface MidiCallback {
void MidiMessage(int index, byte[] data);
}
On Unity side I have these classes :
public class UnityMidiAndroidCallBack : AndroidJavaProxy
{
public UnityMidiAndroidCallBack() : base("com.test.unitymidianrdoid.MidiCallback")
{
}
public void MidiMessage(int index, byte[] data)
{
UnityMidiAndroidInputs.str += "NewNote__"; //static property for debug when new note is pressed
}
}
public class UnityMidiAndroid
{
private const string PluginName = "com.test.unitymidianrdoid.UnityMidiAndroid";
private const string UnityPlayer = "com.unity3d.player.UnityPlayer";
private static AndroidJavaClass _pluginClass;
private static AndroidJavaObject _pluginInstance;
private static UnityMidiAndroidCallBack _callBack;
public UnityMidiAndroid()
{
_callBack = new UnityMidiAndroidCallBack();
AndroidJavaClass unityPlayer = new AndroidJavaClass(UnityPlayer);
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
PluginInstance.Call("ctor", _callBack, activity);
PluginInstance.Call("openDeviceAtIndex", 0);
}
private static AndroidJavaClass PluginClass
{
get { return _pluginClass ??= new AndroidJavaClass(PluginName); }
}
private static AndroidJavaObject PluginInstance
{
get { return _pluginInstance ??= PluginClass.CallStatic<AndroidJavaObject>("getInstance"); }
}
public string[] GetAvailableDevices()
{
return (PluginInstance.Call<string[]>("fetchDevices"));
}
}
The problem is (I think) the callback function is never triggered, but I don't know why..
For the moment I don't want to know which note is pressed, I just want to trigger the callback when a note is pressed
PS: Sorry for my bad english
I want to make app which take photos only with faces but I get whole image instead of face when I save into my storage file. So how to crop face and save into storage with the help google vision face detection API.
So how to use frame in my code to get face list as well as how can I convert into bitmap and save into my storage.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/topLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
<com.google.android.gms.samples.vision.face.facetracker.ui.camera.CameraSourcePreview
android:id="#+id/preview"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.samples.vision.face.facetracker.ui.camera.GraphicOverlay
android:id="#+id/faceOverlay"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.gms.samples.vision.face.facetracker.ui.camera.CameraSourcePreview>
</LinearLayout>
<android.support.v7.widget.AppCompatButton
android:id="#+id/take_pic_btn"
android:layout_gravity="bottom"
android:gravity="center"
android:background="#color/green"
android:layout_margin="10dp"
android:text="Take Image"
android:textStyle="bold"
android:textSize="20sp"
android:textAllCaps="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
FaceTrackerActivity .java
public final class FaceTrackerActivity extends AppCompatActivity {
private static final String TAG = "FaceTracker";
private CameraSource mCameraSource = null;
private CameraSourcePreview mPreview;
private GraphicOverlay mGraphicOverlay;
private static final int RC_HANDLE_GMS = 9001;
// permission request codes need to be < 256
private static final int RC_HANDLE_CAMERA_PERM = 2;
private Button takePicButton;
FaceDetector detector;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
mPreview = (CameraSourcePreview) findViewById(R.id.preview);
mGraphicOverlay = (GraphicOverlay) findViewById(R.id.faceOverlay);
takePicButton=(Button)findViewById(R.id.take_pic_btn);
int rc = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
int gc = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (rc == PackageManager.PERMISSION_GRANTED && gc == PackageManager.PERMISSION_GRANTED) {
createCameraSource();
} else {
requestCameraPermission();
}
takePicButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(),"dilip",Toast.LENGTH_LONG).show();
captureImage();
}
});
}
private void requestCameraPermission() {
Log.w(TAG, "Camera permission is not granted. Requesting permission");
final String[] permissions = new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA) && !ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) ) {
ActivityCompat.requestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM);
return;
}
final Activity thisActivity = this;
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
ActivityCompat.requestPermissions(thisActivity, permissions,
RC_HANDLE_CAMERA_PERM);
}
};
Snackbar.make(mGraphicOverlay, R.string.permission_camera_rationale,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.ok, listener)
.show();
}
private void createCameraSource() {
Context context = getApplicationContext();
/* FaceDetector detector = new FaceDetector.Builder(context)
.setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
.build();
detector.setProcessor(
new MultiProcessor.Builder<>(new GraphicFaceTrackerFactory())
.build());*/
detector= new FaceDetector.Builder(context)
.setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
.build();
MyFaceDetector myFaceDetector = new MyFaceDetector(detector);
detector.setProcessor(
new MultiProcessor.Builder<>(new GraphicFaceTrackerFactory())
.build());
mCameraSource = new CameraSource.Builder(context, myFaceDetector)
.build();
if (!detector.isOperational()) {
}
mCameraSource = new CameraSource.Builder(context, detector)
.setRequestedPreviewSize(640, 480)
.setFacing(CameraSource.CAMERA_FACING_FRONT)
.setRequestedFps(10.0f)
.build();
}
/**
* Restarts the camera.
*/
#Override
protected void onResume() {
super.onResume();
startCameraSource();
}
/**
* Stops the camera.
*/
#Override
protected void onPause() {
super.onPause();
mPreview.stop();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mCameraSource != null) {
mCameraSource.release();
}
}
/**
* Callback for the result from requesting permissions. This method
* is invoked for every call on {#link #requestPermissions(String[], int)}.
* <p>
* <strong>Note:</strong> It is possible that the permissions request interaction
* with the user is interrupted. In this case you will receive empty permissions
* and results arrays which should be treated as a cancellation.
* </p>
*
* #param requestCode The request code passed in {#link #requestPermissions(String[], int)}.
* #param permissions The requested permissions. Never null.
* #param grantResults The grant results for the corresponding permissions
* which is either {#link PackageManager#PERMISSION_GRANTED}
* or {#link PackageManager#PERMISSION_DENIED}. Never null.
* #see #requestPermissions(String[], int)
*/
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode != RC_HANDLE_CAMERA_PERM) {
Log.d(TAG, "Got unexpected permission result: " + requestCode);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
return;
}
if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Camera permission granted - initialize the camera source");
// we have permission, so create the camerasource
createCameraSource();
return;
}
Log.e(TAG, "Permission not granted: results len = " + grantResults.length +
" Result code = " + (grantResults.length > 0 ? grantResults[0] : "(empty)"));
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Face Tracker sample")
.setMessage(R.string.no_camera_permission)
.setPositiveButton(R.string.ok, listener)
.show();
}
//==============================================================================================
// Camera Source Preview
//==============================================================================================
/**
* Starts or restarts the camera source, if it exists. If the camera source doesn't exist yet
* (e.g., because onResume was called before the camera source was created), this will be called
* again when the camera source is created.
*/
private void startCameraSource() {
// check that the device has play services available.
int code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(
getApplicationContext());
if (code != ConnectionResult.SUCCESS) {
Dialog dlg =
GoogleApiAvailability.getInstance().getErrorDialog(this, code, RC_HANDLE_GMS);
dlg.show();
}
if (mCameraSource != null) {
try {
mPreview.start(mCameraSource, mGraphicOverlay);
} catch (IOException e) {
Log.e(TAG, "Unable to start camera source.", e);
mCameraSource.release();
mCameraSource = null;
}
}
}
//==============================================================================================
// Graphic Face Tracker
//==============================================================================================
/**
* Factory for creating a face tracker to be associated with a new face. The multiprocessor
* uses this factory to create face trackers as needed -- one for each individual.
*/
private class GraphicFaceTrackerFactory implements MultiProcessor.Factory<Face> {
#Override
public Tracker<Face> create(Face face) {
return new GraphicFaceTracker(mGraphicOverlay);
}
}
/**
* Face tracker for each detected individual. This maintains a face graphic within the app's
* associated face overlay.
*/
private class GraphicFaceTracker extends Tracker<Face> {
private GraphicOverlay mOverlay;
private FaceGraphic mFaceGraphic;
GraphicFaceTracker(GraphicOverlay overlay) {
mOverlay = overlay;
mFaceGraphic = new FaceGraphic(overlay);
}
/**
* Start tracking the detected face instance within the face overlay.
*/
#Override
public void onNewItem(int faceId, Face item) {
mFaceGraphic.setId(faceId);
}
**`strong text`**
#Override
public void onUpdate(FaceDetector.Detections<Face> detectionResults, Face face) {
mOverlay.add(mFaceGraphic);
mFaceGraphic.updateFace(face);
}
/**
* Hide the graphic when the corresponding face was not detected. This can happen for
* intermediate frames temporarily (e.g., if the face was momentarily blocked from
* view).
*/
#Override
public void onMissing(FaceDetector.Detections<Face> detectionResults) {
mOverlay.remove(mFaceGraphic);
}
/**
* Called when the face is assumed to be gone for good. Remove the graphic annotation from
* the overlay.
*/
#Override
public void onDone() {
mOverlay.remove(mFaceGraphic);
}
}
private void captureImage() {
mPreview.setDrawingCacheEnabled(true);
final Bitmap drawingCache = mPreview.getDrawingCache();
mCameraSource.takePicture(null, new CameraSource.PictureCallback() {
#Override
public void onPictureTaken(byte[] bytes) {
int orientation = Exif.getOrientation(bytes);
Bitmap temp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Bitmap picture = rotateImage(temp,orientation);
Bitmap overlay = Bitmap.createBitmap(mGraphicOverlay.getWidth(),mGraphicOverlay.getHeight(),picture.getConfig());
Canvas canvas = new Canvas(overlay);
Matrix matrix = new Matrix();
matrix.setScale((float)overlay.getWidth()/(float)picture.getWidth(),(float)overlay.getHeight()/(float)picture.getHeight());
// mirror by inverting scale and translating
matrix.preScale(-1, 1);
matrix.postTranslate(canvas.getWidth(), 0);
Paint paint = new Paint();
canvas.drawBitmap(picture,matrix,paint);
canvas.drawBitmap(drawingCache,0,0,paint);
try {
String mainpath = getExternalStorageDirectory() + separator + "MaskIt" + separator + "images" + separator;
File basePath = new File(mainpath);
if (!basePath.exists())
Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success": "Failed");
String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
File captureFile = new File(path);
captureFile.createNewFile();
if (!captureFile.exists())
Log.d("CAPTURE_FILE_PATH", captureFile.createNewFile() ? "Success": "Failed");
FileOutputStream stream = new FileOutputStream(captureFile);
overlay.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.flush();
stream.close();
picture.recycle();
drawingCache.recycle();
mPreview.setDrawingCacheEnabled(false);
} catch (IOException e) {
e.printStackTrace();
}
}
private String getPhotoTime() {
DateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd hhmmss");
dateFormatter.setLenient(false);
Date today = new Date();
String s = dateFormatter.format(today);
return s;
}
});
}
private Bitmap rotateImage(Bitmap bm, int i) {
Matrix matrix = new Matrix();
switch (i) {
case ExifInterface.ORIENTATION_NORMAL:
return bm;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90);
break;
default:
return bm;
}
try {
Bitmap bmRotated = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
bm.recycle();
return bmRotated;
} catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
}
}
CameraSourcePreview.java
package com.google.android.gms.samples.vision.face.facetracker.ui.camera;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import com.google.android.gms.common.images.Size;
import com.google.android.gms.vision.CameraSource;
import java.io.IOException;
public class CameraSourcePreview extends ViewGroup {
private static final String TAG = "CameraSourcePreview";
private Context mContext;
private SurfaceView mSurfaceView;
private boolean mStartRequested;
private boolean mSurfaceAvailable;
private CameraSource mCameraSource;
private GraphicOverlay mOverlay;
public CameraSourcePreview(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mStartRequested = false;
mSurfaceAvailable = false;
mSurfaceView = new SurfaceView(context);
mSurfaceView.getHolder().addCallback(new SurfaceCallback());
addView(mSurfaceView);
}
public void start(CameraSource cameraSource) throws IOException {
if (cameraSource == null) {
stop();
}
mCameraSource = cameraSource;
if (mCameraSource != null) {
mStartRequested = true;
startIfReady();
}
}
public void start(CameraSource cameraSource, GraphicOverlay overlay) throws IOException {
mOverlay = overlay;
start(cameraSource);
}
public void stop() {
if (mCameraSource != null) {
mCameraSource.stop();
}
}
public void release() {
if (mCameraSource != null) {
mCameraSource.release();
mCameraSource = null;
}
}
private void startIfReady() throws IOException {
if (mStartRequested && mSurfaceAvailable) {
mCameraSource.start(mSurfaceView.getHolder());
if (mOverlay != null) {
Size size = mCameraSource.getPreviewSize();
int min = Math.min(size.getWidth(), size.getHeight());
int max = Math.max(size.getWidth(), size.getHeight());
if (isPortraitMode()) {
// Swap width and height sizes when in portrait, since it will be rotated by
// 90 degrees
mOverlay.setCameraInfo(min, max, mCameraSource.getCameraFacing());
} else {
mOverlay.setCameraInfo(max, min, mCameraSource.getCameraFacing());
}
mOverlay.clear();
}
mStartRequested = false;
}
}
private class SurfaceCallback implements SurfaceHolder.Callback {
#Override
public void surfaceCreated(SurfaceHolder surface) {
mSurfaceAvailable = true;
try {
startIfReady();
} catch (IOException e) {
Log.e(TAG, "Could not start camera source.", e);
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surface) {
mSurfaceAvailable = false;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int previewWidth = 320;
int previewHeight = 240;
if (mCameraSource != null) {
Size size = mCameraSource.getPreviewSize();
if (size != null) {
previewWidth = size.getWidth();
previewHeight = size.getHeight();
}
}
// Swap width and height sizes when in portrait, since it will be rotated 90 degrees
if (isPortraitMode()) {
int tmp = previewWidth;
previewWidth = previewHeight;
previewHeight = tmp;
}
final int viewWidth = right - left;
final int viewHeight = bottom - top;
int childWidth;
int childHeight;
int childXOffset = 0;
int childYOffset = 0;
float widthRatio = (float) viewWidth / (float) previewWidth;
float heightRatio = (float) viewHeight / (float) previewHeight;
// To fill the view with the camera preview, while also preserving the correct aspect ratio,
// it is usually necessary to slightly oversize the child and to crop off portions along one
// of the dimensions. We scale up based on the dimension requiring the most correction, and
// compute a crop offset for the other dimension.
if (widthRatio > heightRatio) {
childWidth = viewWidth;
childHeight = (int) ((float) previewHeight * widthRatio);
childYOffset = (childHeight - viewHeight) / 2;
} else {
childWidth = (int) ((float) previewWidth * heightRatio);
childHeight = viewHeight;
childXOffset = (childWidth - viewWidth) / 2;
}
for (int i = 0; i < getChildCount(); ++i) {
// One dimension will be cropped. We shift child over or up by this offset and adjust
// the size to maintain the proper aspect ratio.
getChildAt(i).layout(
-1 * childXOffset, -1 * childYOffset,
childWidth - childXOffset, childHeight - childYOffset);
}
try {
startIfReady();
} catch (IOException e) {
Log.e(TAG, "Could not start camera source.", e);
}
}
private boolean isPortraitMode() {
int orientation = mContext.getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
return false;
}
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
return true;
}
Log.d(TAG, "isPortraitMode returning false by default");
return false;
}
}
GraphicOverlay.java
package com.google.android.gms.samples.vision.face.facetracker.ui.camera;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import com.google.android.gms.vision.CameraSource;
import java.util.HashSet;
import java.util.Set;
public class GraphicOverlay extends View {
private final Object mLock = new Object();
private int mPreviewWidth;
private float mWidthScaleFactor = 1.0f;
private int mPreviewHeight;
private float mHeightScaleFactor = 1.0f;
private int mFacing = CameraSource.CAMERA_FACING_BACK;
private Set<Graphic> mGraphics = new HashSet<>();
public static abstract class Graphic {
private GraphicOverlay mOverlay;
public Graphic(GraphicOverlay overlay) {
mOverlay = overlay;
}
public abstract void draw(Canvas canvas);
public float scaleX(float horizontal) {
return horizontal * mOverlay.mWidthScaleFactor;
}
public float scaleY(float vertical) {
return vertical * mOverlay.mHeightScaleFactor;
}
public float translateX(float x) {
if (mOverlay.mFacing == CameraSource.CAMERA_FACING_FRONT) {
return mOverlay.getWidth() - scaleX(x);
} else {
return scaleX(x);
}
}
public float translateY(float y) {
return scaleY(y);
}
public void postInvalidate() {
mOverlay.postInvalidate();
}
}
public GraphicOverlay(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void clear() {
synchronized (mLock) {
mGraphics.clear();
}
postInvalidate();
}
public void add(Graphic graphic) {
synchronized (mLock) {
mGraphics.add(graphic);
}
postInvalidate();
}
public void remove(Graphic graphic) {
synchronized (mLock) {
mGraphics.remove(graphic);
}
postInvalidate();
}
public void setCameraInfo(int previewWidth, int previewHeight, int facing) {
synchronized (mLock) {
mPreviewWidth = previewWidth;
mPreviewHeight = previewHeight;
mFacing = facing;
}
postInvalidate();
}
/**
* Draws the overlay with its associated graphic objects.
*/
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
synchronized (mLock) {
if ((mPreviewWidth != 0) && (mPreviewHeight != 0)) {
mWidthScaleFactor = (float) canvas.getWidth() / (float)mPreviewWidth;
mHeightScaleFactor = (float) canvas.getHeight() / (float) mPreviewHeight;
}
for (Graphic graphic : mGraphics) {
graphic.draw(canvas);
}
}
}
}
You should pass the captured image to FaceDetector API and crop it thereafter.
fun getFace(context: Context, data: ByteArray): Bitmap? {
try {
val imageStrem = ByteArrayInputStream(data)
var bitmap = BitmapFactory.decodeStream(imageStrem)
if (bitmap.width > bitmap.height) {
val matrix = Matrix()
matrix.postRotate(270f)
if (bitmap.width > 1500) matrix.postScale(0.5f, 0.5f)
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
}
val faceDetector = FaceDetector.Builder(context).setProminentFaceOnly(true).setTrackingEnabled(false).build()
val frame = Frame.Builder().setBitmap(bitmap).build()
val faces = faceDetector.detect(frame)
var results: Bitmap? = null
for (i in 0 until faces.size()) {
val thisFace = faces.valueAt(i)
val x = thisFace.position.x
val y = thisFace.position.y
val x2 = x / 4 + thisFace.width
val y2 = y / 4 + thisFace.height
results = Bitmap.createBitmap(bitmap, x.toInt(), y.toInt(), x2.toInt(), y2.toInt())
}
return results
} catch (e: Exception) {
Log.e("GET_FACE", e.message)
}
return null
}
Source
I'm working on making my first Android App, and I cannot get the text to speech to work.
The gist of the app: user selects the time they want to set an alarm (using a TimePicker), then the app calculates the amount of time left, continuously updating the amount of time left.
I want the use the text to speech engine to verbally update the user at 5 minute intervals on how much time they have left.
Everything compiles and runs without error, but the text to speech just doesn't do anything. I've looked for days to find out how to properly initialize the TextToSpeech class in java, but everything I find seems to initialize it differently on a case by case basis.
After trying multiple different implementations, all with the same result, I decided to just make a separate inner class to make editing and trying new things easier, and I can just make a Voice class and call methods on it.
I've only been coding in Java for a few months, and this is my first Android App, so I am having a lot of trouble sorting through this on my own.
Below is the separate (inner/nested) class that I am using to initialize the TextToSpeech class:
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}
Here is the rest of the code in the activity ( I use a separate activity to display the countdown)
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.AppCompatActivity;
import android.os.*;
import android.widget.*;
import java.util.*;
import java.lang.*;
public class TimerActivity extends AppCompatActivity{
private int alarmHour = MainActivity.alarmHour;
private int alarmMinute = MainActivity.alarmMinute;
private Calendar alarmTime;
private Calendar currentTime;
private TextView timerText;
private TextView lateText;
private int hoursLeft;
private int minutesLeft;
private long difference;
private long calculatedMinutes;
private boolean late = false;
private String lateMessageString = "LATE!";
private String timeRemainingString = "remaining";
private Handler handler = new Handler();
private TextToSpeech tts;
private double pitch = 1;
private double speed = 1;
private int MY_DATA_CHECK_CODE = 0;
private Voice voice;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
voice = new Voice();
voice.say("This is some bullshit.");
initializeTimer();
}
private void initializeTimer () {
voice.say("Yes, hello. Is it me you're looking for?");
timerText = (TextView) findViewById(R.id.timerText);
lateText = (TextView) findViewById(R.id.lateText);
setAlarm();
calculateTimeLeft();
String timerString = getTimerString();
timerText.setText(timerString);
if (late) {
lateText.setText(lateMessageString);
}
else {
lateText.setText(timeRemainingString);
}
Timer timer = new Timer();
timer.schedule(new UpdateTimer(),100,60000);
}
private class UpdateTimer extends TimerTask {
public void run() {
handler.post(new Runnable() {
public void run() {
calculateTimeLeft();
String timerString = getTimerString();
timerText.setText(timerString);
if (late) {
lateText.setText(lateMessageString);
}
else {
lateText.setText(timeRemainingString);
}
}
});
}
}
private void setAlarm() {
alarmTime = Calendar.getInstance();
currentTime = Calendar.getInstance();
alarmTime.setTimeInMillis(System.currentTimeMillis());
alarmTime.set(Calendar.HOUR_OF_DAY, alarmHour);
alarmTime.set(Calendar.MINUTE, alarmMinute);
// If alarm is set for the past, then set the alarm for the next day at the specified time
if (alarmTime.getTimeInMillis() - System.currentTimeMillis() < 0) {
alarmTime.set(Calendar.DAY_OF_YEAR, alarmTime.get(Calendar.DAY_OF_YEAR) + 1);
}
}
private void calculateTimeLeft() {
currentTime.setTimeInMillis(System.currentTimeMillis());
difference = alarmTime.getTimeInMillis() - System.currentTimeMillis();
long seconds = difference/1000; // convert to seconds
long calculatedHours = seconds / 3600; // Find the number of hours until alarm
calculatedMinutes = (seconds % 3600) / 60; // Use mod to remove the number of hours, leaving only seconds since the last hour, then divide by 60 to get minutes
hoursLeft = (int)Math.abs(calculatedHours); // Get the absolute value of the time left for the string
minutesLeft = (int)Math.abs(calculatedMinutes); // Absolute value of the minutes for string use
}
private String getTimerString() {
// Format the string showing the time remaining
String timeLeftString;
if (hoursLeft == 0) {
timeLeftString = "";
}
else if (hoursLeft == 1) {
timeLeftString = hoursLeft + "hr ";
}
else {
timeLeftString = hoursLeft +"hrs ";
}
if (hoursLeft == 0) {
timeLeftString += minutesLeft;
}
/*
else if (minutesLeft < 10 && calculatedMinutes > 0) {
timeLeftString += "0" + minutesLeft;
}
*/
else {
timeLeftString += minutesLeft;
}
if (calculatedMinutes >= 0 && hoursLeft > 0) {
timeLeftString += " mins";
}
else if (calculatedMinutes > 0) {
timeLeftString += " mins";
}
else if (difference <= 0) {
late = true;
}
return timeLeftString;
}
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
I think you can't hear any voices that you want.
Because TextToSpeech class can't say immediately after you invoke constructor.
TextToSpeech class instance need to connect to system TTS service when it is initializing.
And if the instance is success to connect to service, onInit of TextToSpeech.OnInitListener will be activated!
So, you can hear the voice after onInit function is done. Try to move your voice.say functions at onInit function.
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
// try it!
voice.say("Can you hear this sentence?");
// If you want to another "say", check this log.
// Your voice will say after you see this log at logcat.
Log.i("TAG", "TextToSpeech instance initialization is finished.");
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}
I am developing a mobile app to integrate with ZbarScanner. However, I am meet with error "ZBarScannerActivity cannot be resolved to a type" and "ZBarConstants cannot be resolved to a variable". please assist to help with the following code:
MainActivity.java:
package com.example.vscanner;
import net.sourceforge.zbar.Symbol;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
private static final int ZBAR_SCANNER_REQUEST = 0;
private static final int ZBAR_QR_SCANNER_REQUEST = 1;
public void launchScanner(View v) {
if (isCameraAvailable()) {
Intent intent = new Intent(this, ZBarScannerActivity.class);
startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
} else {
Toast.makeText(this, "Rear Facing Camera Unavailable", Toast.LENGTH_SHORT).show();
}
}
public void launchQRScanner(View v) {
if (isCameraAvailable()) {
Intent intent = new Intent(this, ZBarScannerActivity.class);
intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{Symbol.QRCODE});
startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
} else {
Toast.makeText(this, "Rear Facing Camera Unavailable", Toast.LENGTH_SHORT).show();
}
}
public boolean isCameraAvailable() {
PackageManager pm = getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == RESULT_OK)
{
// Scan result is available by making a call to data.getStringExtra(ZBarConstants.SCAN_RESULT)
// Type of the scan result is available by making a call to data.getStringExtra(ZBarConstants.SCAN_RESULT_TYPE)
Toast.makeText(this, "Scan Result = " + data.getStringExtra(ZBarConstants.SCAN_RESULT), Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Scan Result Type = " + data.getStringExtra(ZBarConstants.SCAN_RESULT_TYPE), Toast.LENGTH_SHORT).show();
// The value of type indicates one of the symbols listed in Advanced Options below.
} else if(resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Camera unavailable", Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Paste these 3 classes into your source folder.
ZBarConstants.java
package com.example.vscanner;
public interface ZBarConstants {
public static final String SCAN_MODES = "SCAN_MODES";
public static final String SCAN_RESULT = "SCAN_RESULT";
public static final String SCAN_RESULT_TYPE = "SCAN_RESULT_TYPE";
public static final String ERROR_INFO = "ERROR_INFO";
}
ZBarScannerActivity.java
package com.example.vscanner;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.view.Window;
import android.view.WindowManager;
import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
public class ZBarScannerActivity extends Activity implements Camera.PreviewCallback, ZBarConstants {
private static final String TAG = "ZBarScannerActivity";
private CameraPreview mPreview;
private Camera mCamera;
private ImageScanner mScanner;
private Handler mAutoFocusHandler;
private boolean mPreviewing = true;
static {
System.loadLibrary("iconv");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!isCameraAvailable()) {
// Cancel request if there is no rear-facing camera.
cancelRequest();
return;
}
// Hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
mAutoFocusHandler = new Handler();
// Create and configure the ImageScanner;
setupScanner();
// Create a RelativeLayout container that will hold a SurfaceView,
// and set it as the content of our activity.
mPreview = new CameraPreview(this, this, autoFocusCB);
setContentView(mPreview);
}
public void setupScanner() {
mScanner = new ImageScanner();
mScanner.setConfig(0, Config.X_DENSITY, 3);
mScanner.setConfig(0, Config.Y_DENSITY, 3);
int[] symbols = getIntent().getIntArrayExtra(SCAN_MODES);
if (symbols != null) {
mScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
for (int symbol : symbols) {
mScanner.setConfig(symbol, Config.ENABLE, 1);
}
}
}
#Override
protected void onResume() {
super.onResume();
// Open the default i.e. the first rear facing camera.
mCamera = Camera.open();
if(mCamera == null) {
// Cancel request if mCamera is null.
cancelRequest();
return;
}
mPreview.setCamera(mCamera);
mPreview.showSurfaceView();
mPreviewing = true;
}
#Override
protected void onPause() {
super.onPause();
// Because the Camera object is a shared resource, it's very
// important to release it when the activity is paused.
if (mCamera != null) {
mPreview.setCamera(null);
mCamera.cancelAutoFocus();
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
// According to Jason Kuang on http://stackoverflow.com/questions/6519120/how-to-recover-camera-preview-from-sleep,
// there might be surface recreation problems when the device goes to sleep. So lets just hide it and
// recreate on resume
mPreview.hideSurfaceView();
mPreviewing = false;
mCamera = null;
}
}
public boolean isCameraAvailable() {
PackageManager pm = getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
public void cancelRequest() {
Intent dataIntent = new Intent();
dataIntent.putExtra(ERROR_INFO, "Camera unavailable");
setResult(Activity.RESULT_CANCELED, dataIntent);
finish();
}
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
Image barcode = new Image(size.width, size.height, "Y800");
barcode.setData(data);
int result = mScanner.scanImage(barcode);
if (result != 0) {
mCamera.cancelAutoFocus();
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mPreviewing = false;
SymbolSet syms = mScanner.getResults();
for (Symbol sym : syms) {
String symData = sym.getData();
if (!TextUtils.isEmpty(symData)) {
Intent dataIntent = new Intent();
dataIntent.putExtra(SCAN_RESULT, symData);
dataIntent.putExtra(SCAN_RESULT_TYPE, sym.getType());
setResult(Activity.RESULT_OK, dataIntent);
finish();
break;
}
}
}
}
private Runnable doAutoFocus = new Runnable() {
public void run() {
if(mCamera != null && mPreviewing) {
mCamera.autoFocus(autoFocusCB);
}
}
};
// Mimic continuous auto-focusing
Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
}
};
}
CameraPreview.java
package com.example.vscanner;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import java.io.IOException;
import java.util.List;
class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "CameraPreview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
PreviewCallback mPreviewCallback;
AutoFocusCallback mAutoFocusCallback;
CameraPreview(Context context, PreviewCallback previewCallback, AutoFocusCallback autoFocusCb) {
super(context);
mPreviewCallback = previewCallback;
mAutoFocusCallback = autoFocusCb;
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
requestLayout();
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
// Center the child SurfaceView within the parent.
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void hideSurfaceView() {
mSurfaceView.setVisibility(View.INVISIBLE);
}
public void showSurfaceView() {
mSurfaceView.setVisibility(View.VISIBLE);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null) {
mCamera.cancelAutoFocus();
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (holder.getSurface() == null){
// preview surface does not exist
return;
}
if (mCamera != null) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.setPreviewCallback(mPreviewCallback);
mCamera.startPreview();
mCamera.autoFocus(mAutoFocusCallback);
}
}
}
I Would like to make one sample code for paypal integration.
It have done but i Cant't Understand Where i need to put Merchant account Id in Code.I have Saler Id and Merchant Id both But i do't know Where i want to put this
Merchant Id. So can any budy help me please.
package com.paypal.android.pizza;
import java.util.Vector;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import com.paypal.android.MECL.PayPal;
public class Pizza extends Activity {
// The instance of our activity
private static Pizza _instance;
// The reference token that we get from initializing the MECL library
public static String _deviceReferenceToken;
// The PayPal server to be used - can also be ENV_NONE and ENV_LIVE
private static final int server = PayPal.ENV_SANDBOX;
// The ID of your application that you received from PayPal
private static final String appID = "APP-80W284485P519543T";
public static final String build = "11.01.04.8174";
// The possible results from initializing MECL
protected static final int INITIALIZE_SUCCESS = 0;
protected static final int INITIALIZE_FAILURE = 1;
// The pages of our application
public static final int PAGE_HOME = 0;
public static final int PAGE_CUSTOMIZE = 1;
public static final int PAGE_FINALIZE = 2;
public static final int PAGE_WEB = 3;
// The currently shown page
private BasePage currentPage;
// The pizza sizes
public static final int SIZE_SMALL = 0;
public static final int SIZE_MEDIUM = 1;
public static final int SIZE_LARGE = 2;
// The pizza toppings
public static final int TOPPING_EXTRA_CHEESE = 0;
public static final int TOPPING_PEPPERONI = 1;
public static final int TOPPING_MUSHROOMS = 2;
public static final int TOPPING_ONIONS = 3;
// The pizza acquiring methods
public static final int METHOD_PICKUP = 0;
public static final int METHOD_DELIVERY = 1;
// Our current selections that are given defaults to start
private int currentSize = SIZE_SMALL;
private Vector<Integer> currentToppings = new Vector<Integer>();
private int currentCount = 1;
private int currentMethod = METHOD_PICKUP;
// The WebView that we'll use to display MECL
private WebView _webView;
// The popup we'll use to show loading when initializing the library
private ProgressDialog mProgDialog;
// This handler will allow us to properly update the UI. You cannot touch
// Views from a non-UI thread.
Handler hRefresh = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case INITIALIZE_SUCCESS:
// We have initialized the application, close the dialog and
// launch the WebView
mProgDialog.cancel();
launchWeb();
break;
case INITIALIZE_FAILURE:
// Initialization failure, close the dialog, update the page and
// show a toast
mProgDialog.cancel();
currentPage.update();
Toast.makeText(Pizza.getInstance(),
"Failed to initialize PayPal", Toast.LENGTH_SHORT)
.show();
break;
}
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the instance
_instance = this;
// Set our defaults
currentSize = SIZE_SMALL;
currentToppings = new Vector<Integer>();
currentCount = 1;
currentMethod = METHOD_PICKUP;
// Set our page
currentPage = new HomePage(this);
setContentView(currentPage);
}
/*
* This method will be used every time we want to change the page
*/
public void changePage(int page) {
switch (page) {
case PAGE_HOME:
// Change to the home page
currentPage = new HomePage(this);
setContentView(currentPage);
break;
case PAGE_CUSTOMIZE:
// Change to the customize page
currentPage = new CustomizePage(this);
setContentView(currentPage);
break;
case PAGE_FINALIZE:
// Change to the finalize page
currentPage = new FinalizePage(this);
setContentView(currentPage);
break;
case PAGE_WEB:
// Time to launch the library but first we need to initialize
// Show the loading popup
mProgDialog = ProgressDialog.show(this, "", "Loading");
// Create a separate thread to do the initialization
Thread libraryInitializationThread = new Thread() {
public void run() {
// Initialize the library
initLibrary();
// The library is initialized so let's launch it by
// notifying our handler
if (PayPal.getInstance().isLibraryInitialized()) {
hRefresh.sendEmptyMessage(INITIALIZE_SUCCESS);
} else {
hRefresh.sendEmptyMessage(INITIALIZE_FAILURE);
}
}
};
libraryInitializationThread.start();
break;
}
}
private void initLibrary() {
// This is the main initialization call that takes in your Context, the
// Application ID, the server you would like to connect to, and your
// PayPalListener
PayPal.fetchDeviceReferenceTokenWithAppID(this, appID, server,
new ResultDelegate());
// -- These are required settings.
PayPal.getInstance().setLanguage("en_US"); // Sets the language for the
// library.
}
private void launchWeb() {
// Setup the url for our pizza app to connect to
String buf = new String(
"http://paydemo.sms4me.com/ECDemo-server/cart.jsp?");
buf += "delivery="
+ (currentMethod == METHOD_PICKUP ? "false" : "true");
buf += "&count=" + currentCount;
String size = new String("Small");
if (currentSize == SIZE_MEDIUM)
size = "Medium";
else if (currentSize == SIZE_LARGE)
size = "Large";
buf += "&size=" + size;
if (currentToppings.size() > 0) {
buf += "&toppings=";
for (int i = 0; i < currentToppings.size(); i++) {
if (i != 0)
buf += ",";
String topping = "Extra%20Cheese";
if (currentToppings.elementAt(i) == TOPPING_PEPPERONI)
topping = "Pepperoni";
else if (currentToppings.elementAt(i) == TOPPING_MUSHROOMS)
topping = "Mushrooms";
else if (currentToppings.elementAt(i) == TOPPING_ONIONS)
topping = "Onions";
buf += topping;
}
}
buf += "&drt=" + _deviceReferenceToken;
android.util.Log.d("PIZZA_REQUEST", buf.replaceAll("&", "\n&"));
// Construct the WebView
_webView = new WebView(this);
// Set our view to the WebView
_webView.getSettings().setJavaScriptEnabled(true);
setContentView(_webView);
// Setup a WebViewClient so we know when the url changes
_webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Our servlet only uses one url for both success or failure
if (url.equals("http://paydemo.sms4me.com/ECDemo-server/cancel.html")) {
// The url was hit so it's time to go back to our home page
changePage(PAGE_HOME);
return true;
}
return false;
}
});
// Load our url
_webView.loadUrl(buf);
// The android WebView sometimes does not have focus and this affects
// different UI elements so we'll force the focus to work around this
_webView.requestFocus(View.FOCUS_DOWN);
}
public static Pizza getInstance() {
return _instance;
}
public int getCurrentSize() {
return currentSize;
}
public void setCurrentSize(int currentSize) {
this.currentSize = currentSize;
}
public Vector<Integer> getCurrentToppings() {
return currentToppings;
}
public void setCurrentToppings(Vector<Integer> currentToppings) {
this.currentToppings = currentToppings;
}
public int getCurrentCount() {
return currentCount;
}
public void setCurrentCount(int currentCount) {
this.currentCount = currentCount;
}
public int getCurrentMethod() {
return currentMethod;
}
public void setCurrentMethod(int currentMethod) {
this.currentMethod = currentMethod;
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// We need to manually handle the back key for WebView
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (_webView != null && _webView.canGoBack()) {
// It's the WebView and we can navigate back with it so let's do
// so
_webView.goBack();
return true;
} else if (_webView != null) {
// It's the WebView but we can't navigate back, so let's go to
// the pizza home page
changePage(PAGE_HOME);
_webView = null;
return true;
} else {
// It's not the WebView so let's save the values and move back a
// page
if (currentPage instanceof CustomizePage) {
currentPage.saveValues();
changePage(PAGE_HOME);
} else if (currentPage instanceof FinalizePage) {
currentPage.saveValues();
changePage(PAGE_CUSTOMIZE);
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
}