How to stop an app until a button is pressed? - wait

First sorry for my english!! =)
I'm doing a cards game for android and i have some troubles or questions better said.
I tried this code to implements an ActionListener to my ImageButtons (cards)
But i need that my app waits until some card were pressed. I thought using threads but i don't know how to do in my app. Can anyone help me?
Let my code in the following
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_juego);
ll = (LinearLayout)findViewById(R.id.ll);
this.cartaenmesa = (ImageView)findViewById(R.id.imageView1);
this.numcartasbaraja = (TextView)findViewById(R.id.textView1);
this.numbar =2;
this.numcartas = 20;
this.numjug = 3;
for(int i=0;i<=this.numjug-1;i++){
this.jugadores.add(new Jugador("Jugador "+ i));
}
this.pilaInicial();
this.desordenarPila();
this.repartirInicial();
// this.DibujarCartaEnMesa(this.pila.get(0));
// this.DibujarCartas(this.jugadores.get(0).DevolverCartas());
// this.numcartasbaraja.setText(""+this.pila.size());
this.iniciarJuego();
}
Here's the loop that set Listeners to all the buttons.
for (int i = 0; i < this.imgbt_cartas_act.size();i++){
this.imgbt_cartas_act.get(i).setOnClickListener(listener); // AGREGAMOS LOS LISTENERS A CADA BOTON
}
Here's where I assign an image and ID to the buttons
private void DibujarCartas (ArrayList<Carta> c){
int i = 0;
for (Carta c1 : c){
this.imgbt_cartas_act.add(i, new ImageButton(Juego.this));
//OROS
if (c1.getValor()== 1 && c1.getPalo()=="Oros"){
this.imgbt_cartas_act.get(i).setImageResource(R.drawable.oros_1);
this.imgbt_cartas_act.get(i).setId(1);
}
if (c1.getValor()== 2 && c1.getPalo()=="Oros"){
this.imgbt_cartas_act.get(i).setImageResource(R.drawable.oros_2);
this.imgbt_cartas_act.get(i).setId(2);
}
.......
}
and finally the OnClick
OnClickListener listener = new OnClickListener() {
public void onClick(View v) {
//OROS
if (v.getId()==1){ // 1 de oros
carteleg = new Carta(1,"Oros");
}
if (v.getId()==2){ // 1 de oros
carteleg = new Carta(2,"Oros");
}
if (v.getId()==3){ // 1 de oros
carteleg = new Carta(3,"Oros");
}
if (v.getId()==4){ // 1 de oros
carteleg = new Carta(4,"Oros");
}
.....
}
};

Related

Xamarin Forms: Different time is showing on the UI after clock pop is closed in TimePicker?

I am using the below thread for setting the time in multiples of 5 in the time picker. Using the custom renderers I am able to select the time in multiples of 5. But after selecting a time, when the clock-Pop up closed, a different time is showing on the UI. The issue is only in the android platform, for the ios everything is working as excepted.
My code:
public class CustomTimePickerRenderer : TimePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TimePicker> e)
{
base.OnElementChanged(e);
TimePickerDialogIntervals timePickerDlg = new TimePickerDialogIntervals(this.Context, new EventHandler<TimePickerDialogIntervals.TimeSetEventArgs>(UpdateDuration),
Element.Time.Hours, Element.Time.Minutes, true);
var control = new EditText(this.Context);
control.Focusable = false;
control.FocusableInTouchMode = false;
control.Clickable = false;
control.Click += (sender, ea) => timePickerDlg.Show();
control.Text = Element.Time.Hours.ToString("00") + ":" + Element.Time.Minutes.ToString("00");
SetNativeControl(control);
}
void UpdateDuration(object sender, Android.App.TimePickerDialog.TimeSetEventArgs e)
{
Element.Time = new TimeSpan(e.HourOfDay, e.Minute, 0);
Control.Text = Element.Time.Hours.ToString("00") + ":" + Element.Time.Minutes.ToString("00");
}
}
public class TimePickerDialogIntervals : TimePickerDialog
{
public const int TimePickerInterval = 05;
private bool _ignoreEvent = false;
public TimePickerDialogIntervals(Context context, EventHandler<TimePickerDialog.TimeSetEventArgs> callBack, int hourOfDay, int minute, bool is24HourView)
: base(context, (sender, e) =>
{
callBack(sender, new TimePickerDialog.TimeSetEventArgs(e.HourOfDay, e.Minute * TimePickerInterval));
}, hourOfDay, minute / TimePickerInterval, is24HourView)
{
}
public override void OnTimeChanged(Android.Widget.TimePicker view, int hourOfDay, int minute)
{
base.OnTimeChanged(view, hourOfDay, minute);
if (_ignoreEvent) return;
if (minute % TimePickerInterval != 0)
{
int minuteFloor = minute - (minute % TimePickerInterval);
minute = minuteFloor + (minute == minuteFloor + 1 ? TimePickerInterval : 0);
if (minute == 60)
minute = 0;
_ignoreEvent = true;
view.CurrentMinute = (Java.Lang.Integer)minute;
_ignoreEvent = false;
}
}
}
Why a different time is showing on the UI when the clock pop-up closed?
The problem is because the minute has been multiplied by 'TimePickerInterval' (05). Changing the parameter to 'e.Minute' will work as expected.
Code:
public class TimePickerDialogIntervals : TimePickerDialog
{
public const int TimePickerInterval = 15;
private bool _ignoreEvent = false;
public TimePickerDialogIntervals(Context context, EventHandler<TimePickerDialog.TimeSetEventArgs> callBack, int hourOfDay, int minute, bool is24HourView) :
base(context, (sender, e) =>
{
callBack(sender, new TimePickerDialog.TimeSetEventArgs(e.HourOfDay, e.Minute));//remove '* TimePickerInterval'
}, hourOfDay, minute / TimePickerInterval, is24HourView)
{
}
...
}

Long tap and drop pin in xamarin forms maps

I used Xamarin.Forms.Maps nuget package and displayed map on the device. I am able to show the pin on external button tap with the help of following code, but unable to achieve same on map tap to drop a pin on a specific location.
public void addPin(double latitude, double longitude, string labelName)
{
Position position = new Position(latitude, longitude);
_assignedPin = new Pin
{
Type = PinType.Place,
Position = position,
Label = labelName,
Address = "custom detail info"
};
map.Pins.Add(_assignedPin);
}
I followed this blog to get lat long on map, but map does not display the pin on the map.
We need to add the code in renderer itself to drop pin using xamarin.forms.maps
In Android: Renderer class:
private void googleMap_MapClick(object sender, GoogleMap.MapClickEventArgs e)
{
Map.Pins.Add(new Pin
{
Label = "Pin from tap",
Position = new Position(e.Point.Latitude, e.Point.Longitude))
}
}
And in iOS Renderer class:
[assembly: ExportRenderer(typeof(ExtMap), typeof(ExtMapRenderer))]
namespace Xamarin.iOS.CustomRenderers
{
/// <summary>
/// Renderer for the xamarin ios map control
/// </summary>
public class ExtMapRenderer : MapRenderer
{
private readonly UITapGestureRecognizer _tapRecogniser;
public ExtMapRenderer()
{
_tapRecogniser = new UITapGestureRecognizer(OnTap)
{
NumberOfTapsRequired = 1,
NumberOfTouchesRequired = 1
};
}
protected override IMKAnnotation CreateAnnotation(Pin pin)
{
return base.CreateAnnotation(pin);
}
class BasicMapAnnotation : MKAnnotation
{
CLLocationCoordinate2D coord;
string title, subtitle;
public override CLLocationCoordinate2D Coordinate { get { return coord; } }
public override void SetCoordinate(CLLocationCoordinate2D value)
{
coord = value;
}
public override string Title { get { return title; } }
public override string Subtitle { get { return subtitle; } }
public BasicMapAnnotation(CLLocationCoordinate2D coordinate, string title, string subtitle)
{
this.coord = coordinate;
this.title = title;
this.subtitle = subtitle;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
}
private async void OnTap(UITapGestureRecognizer recognizer)
{
var cgPoint = recognizer.LocationInView(Control);
var nativeMap = Control as MKMapView;
var location = ((MKMapView)Control).ConvertPoint(cgPoint, Control);
((ExtMap)Element).OnTap(new Position(location.Latitude, location.Longitude));
try
{
var lat = location.Latitude;
var lon = location.Longitude;
var placemarks = await Geocoding.GetPlacemarksAsync(lat, lon);
var placemark = placemarks?.FirstOrDefault();
if (placemark != null)
{
var geocodeAddress =
$"AdminArea: {placemark.AdminArea}\n" +
$"CountryCode: {placemark.CountryCode}\n" +
$"CountryName: {placemark.CountryName}\n" +
$"FeatureName: {placemark.FeatureName}\n" +
$"Locality: {placemark.Locality}\n" +
$"PostalCode: {placemark.PostalCode}\n" +
$"SubAdminArea: {placemark.SubAdminArea}\n" +
$"SubLocality: {placemark.SubLocality}\n" +
$"SubThoroughfare: {placemark.SubThoroughfare}\n" +
$"Thoroughfare: {placemark.Thoroughfare}\n";
Console.WriteLine(geocodeAddress);
var annotation = new BasicMapAnnotation(new CLLocationCoordinate2D(lat, lon), placemark.Thoroughfare, placemark.SubThoroughfare);
nativeMap.AddAnnotation(annotation);
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
Console.WriteLine(fnsEx);
}
catch (Exception ex)
{
// Handle exception that may have occurred in geocoding
Console.WriteLine(ex);
}
}
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
if (Control != null)
Control.RemoveGestureRecognizer(_tapRecogniser);
base.OnElementChanged(e);
if (Control != null)
Control.AddGestureRecognizer(_tapRecogniser);
}
}
}

Task: how to be notified when the task is "finished"

... that is after all its properties - including its value - are updated?
The use-case is a Task that
"collects" items into an ObservableList which is the result of the call method
the list should be set as value when the task is "finished", no matter if normally or cancelled
A snippet of the Task implementation (complete example at end):
#Override
protected ObservableList<Rectangle> call() throws Exception {
ObservableList<Rectangle> results = FXCollections.observableArrayList();
for (int i=0; i<=count; i++) {
// do fill list
//...
try {
Thread.sleep(200);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
// do update value on cancelled
updateValue(results);
break;
}
}
}
return results;
}
It's intended usage:
bind the itemsProperty of a tableView to the valueProperty
unbind on "finished"
My approach was to listen to its state property and unbind on state changes to SUCCEEDED or CANCELLED. The former works just fine, the latter doesn't because at the time of receiving the cancelled, the value is not yet updated and consequently the items not set.
// working ... but when to unbind?
table.itemsProperty().bind(task.valueProperty());
task.stateProperty().addListener((src, ov, nv) -> {
if (Worker.State.SUCCEEDED == nv ) {
// this is fine because implementation in TaskCallable first
// updates the value (with the result it got from T call())
// then updates state
LOG.info("succeeded" + task.getValue());
table.itemsProperty().unbind();
} else if (Worker.State.CANCELLED == nv) {
LOG.info("receiving cancelled " + task.getValue());
// can't unbind here, value not yet updated
// table.itemsProperty().unbind();
}
});
So in case of cancelled, this leaves me with either a property that's still bound or an empty table. Feels like I'm doing something wrong. Or core Task impl is not as useful as expected? It would mean that we simply can't bind to the value property (nor any of the others like progress) due to being unable to safely cleanup (using table items here is just an example, because it's easy to see, same for all types of properties).
Question is, how to do it correctly/overcome the limitation?
The complete example:
public class TaskValueBinding extends Application {
private Parent createListPane() {
Task<ObservableList<Rectangle>> task = createListTask();
Thread thread = new Thread(task);
thread.setDaemon(true);
TableView<Rectangle> table = new TableView<>();
TableColumn<Rectangle, Double> xCol = new TableColumn<>("X");
xCol.setCellValueFactory(new PropertyValueFactory<>("x"));
TableColumn<Rectangle, Double> yCol = new TableColumn<>("Y");
yCol.setCellValueFactory(new PropertyValueFactory<>("y"));
table.getColumns().addAll(xCol, yCol);
// working ... but when to unbind?
table.itemsProperty().bind(task.valueProperty());
task.stateProperty().addListener((src, ov, nv) -> {
if (Worker.State.SUCCEEDED == nv ) {
// this is fine because implementation in TaskCallable first
// updates the value (with the result it got from T call())
// then updates state
LOG.info("succeeded" + task.getValue());
table.itemsProperty().unbind();
} else if (Worker.State.CANCELLED == nv) {
LOG.info("receiving cancelled " + task.getValue());
// can't unbind here, value not yet updated
// table.itemsProperty().unbind();
}
});
Label messageLabel = new Label("Message: ");
Label message = new Label();
message.textProperty().bind(task.messageProperty());
Label progressAsText = new Label();
Label progressLabel = new Label("Progress: ");
progressAsText.textProperty().bind(task.progressProperty().asString());
ProgressBar progress = new ProgressBar();
progress.progressProperty().bind(task.progressProperty());
Button start = new Button("Start");
start.setOnAction(e -> {
start.setDisable(true);
thread.start();
});
Button cancel = new Button("Cancel");
cancel.setOnAction(e -> task.cancel());
cancel.disableProperty().bind(task.runningProperty().not());
int row = 0;
GridPane grid = new GridPane();
grid.add(table, 0, row++, 20, 1);
grid.add(messageLabel, 0, row);
grid.add(message, 1, row++);
grid.add(progressLabel, 0, row);
grid.add(progressAsText, 1, row++);
grid.add(progress, 0, row++, 2, 1);
grid.add(start, 0, row);
grid.add(cancel, 1, row++);
return grid;
}
private Task<ObservableList<Rectangle>> createListTask() {
Task<ObservableList<Rectangle>> task = new Task<ObservableList<Rectangle>>() {
#Override
protected ObservableList<Rectangle> call() throws Exception {
updateMessage("Creating Rectangles ...");
ObservableList<Rectangle> results = FXCollections.observableArrayList();
String message = "finished";
int count = 10;
for (int i=0; i<=count; i++) {
if (isCancelled()) {
updateValue(results);
// when do we get here?
message = "cancelled";
break;
}
Rectangle r = new Rectangle(10, 10);
r.setX(10 * i);
results.add(r);
updateProgress(i, count);
// Now block the thread for a short time, but be sure
// to check the interrupted exception for cancellation!
try {
Thread.sleep(200);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
updateValue(results);
message = "interrupted";
break;
}
}
}
updateMessage(message);
return results;
}
};
return task;
}
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createListPane()));
stage.setTitle(FXUtils.version());
stage.show();
}
public static void main(String[] args) {
launch(args);
}
#SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(TaskValueBinding.class.getName());
}
Cancelling the task immediately triggers an update of the state property. If canceled from the application thread Platfrom.runLater is not used for this purpose but the call of the cancel method updates the state immediately. This results in the state being changed before any updateValue call updates the value property using Platform.runLater.
Task is not designed to allow partial results so you need to implement custom logic to accommodate for this. Depending on your needs you could subclass Task to trigger a custom event when the task completes in any way.
public abstract class PartialResultTask<T> extends Task<T> {
// handler triggered after last change of value
private Runnable onDone;
public Runnable getOnDone() {
return onDone;
}
public void setOnDone(Runnable onDone) {
this.onDone = onDone;
}
protected abstract T calculateResult() throws Exception;
private void onDone() {
if (onDone != null) {
Platform.runLater(onDone);
}
}
#Override
protected final T call() throws Exception {
try {
T result = calculateResult();
updateValue(result); // update value to the final value
onDone();
return result;
} catch (Exception ex) {
onDone();
throw ex;
}
}
}
private PartialResultTask<ObservableList<Rectangle>> createListTask() {
PartialResultTask<ObservableList<Rectangle>> task = new PartialResultTask<ObservableList<Rectangle>>() {
#Override
protected ObservableList<Rectangle> calculateResult() throws Exception {updateMessage("Creating Rectangles ...");
ObservableList<Rectangle> results = FXCollections.observableArrayList();
int count = 10;
for (int i = 0; !isCancelled() && i <= count; i++) {
Rectangle r = new Rectangle(10, 10);
r.setX(10 * i);
results.add(r);
updateProgress(i, count);
// Now block the thread for a short time, but be sure
// to check the interrupted exception for cancellation!
try {
Thread.sleep(200);
} catch (InterruptedException interrupted) {
}
}
updateMessage(isCancelled() ? "canceled" : "finished");
return results;
}
};
return task;
}
task.setOnDone(() -> {
table.itemsProperty().unbind();
});
task.stateProperty().addListener((src, ov, nv) -> {
if (Worker.State.SUCCEEDED == nv) {
// this is fine because implementation in TaskCallable first
// updates the value (with the result it got from T call())
// then updates state
LOG.info("succeeded" + task.getValue());
} else if (Worker.State.CANCELLED == nv) {
LOG.info("receiving cancelled " + task.getValue());
}
});

Custom Keyboard in Xamarin forms

I've read the many posts on the forum and on StackOverflow and other places on making custom keyboards, but have not found an approach that will work for my Xamarin forms cross-platform project. It is programmatically generated.
For example, I built this keyboard that was recommended in several places:
I try to integrate this into my Xamarin forms app but not able to do this
https://github.com/Vaikesh/CustomKeyboard/blob/master/CustomKeyboard/Activity1.cs
It works fine as a standalone
I want Hebrew language keyboard in my application Like this
I would appreciate any help.
Thank you.
Custom Keyboard in Xamarin forms
You could create a PageRenderer and use native .axml layout file to create the custom Keyboard.
For example, my KeyboardPageRenderer :
[assembly: ExportRenderer(typeof(MyKeyboardPage), typeof(KeyboardPageRenderer))]
...
public class KeyboardPageRenderer : PageRenderer
{
public CustomKeyboardView mKeyboardView;
public EditText mTargetView;
public Android.InputMethodServices.Keyboard mKeyboard;
Activity activity;
global::Android.Views.View view;
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
SetupUserInterface();
SetupEventHandlers();
this.AddView(view);
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(#" ERROR: ", ex.Message);
}
}
void SetupUserInterface()
{
activity = this.Context as Activity;
view = activity.LayoutInflater.Inflate(Resource.Layout.activity_keyboard, this, false);
mKeyboard = new Android.InputMethodServices.Keyboard(Context, Resource.Xml.keyboard);
mTargetView = view.FindViewById<EditText>(Resource.Id.target);
mKeyboardView = view.FindViewById<CustomKeyboardView>(Resource.Id.keyboard_view);
mKeyboardView.Keyboard = mKeyboard;
}
void SetupEventHandlers()
{
mTargetView.Touch += (sender, e) =>
{
ShowKeyboardWithAnimation();
e.Handled = false;
mTargetView.ShowSoftInputOnFocus = false;
};
mKeyboardView.Key += async (sender, e) =>
{
long eventTime = JavaSystem.CurrentTimeMillis();
KeyEvent ev = new KeyEvent(eventTime, eventTime, KeyEventActions.Down, e.PrimaryCode, 0, 0, 0, 0, KeyEventFlags.SoftKeyboard | KeyEventFlags.KeepTouchMode);
DispatchKeyEvent(ev);
await Task.Delay(1);
mTargetView.RequestFocus();
};
}
public void ShowKeyboardWithAnimation()
{
if (mKeyboardView.Visibility == ViewStates.Gone)
{
mKeyboardView.Visibility = ViewStates.Visible;
Android.Views.Animations.Animation animation = AnimationUtils.LoadAnimation(
Context,
Resource.Animation.slide_in_bottom
);
mKeyboardView.ShowWithAnimation(animation);
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
view.Measure(msw, msh);
view.Layout(0, 0, r - l, b - t);
}
}
Effect:
.
I wrote up a simple demo about how to implement this feature, you can see it in this GitHub Repository.
I don't know Hebrew, if you need to achieve the effect like the picture you have post, you need custom the layout in keyboard.xml file.
Update :
I am done iOS portion using entry render so only try to do for android portion
I write a EntryRenderer to implement this feature, effect like this, hope this can help you.
public class MyEntry2Renderer : ViewRenderer<MyEntry, TextInputLayout>,
ITextWatcher,
TextView.IOnEditorActionListener
{
private bool _hasFocus;
public CustomKeyboardView mKeyboardView;
public Android.InputMethodServices.Keyboard mKeyboard;
ViewGroup activityRootView;
protected EditText EditText => Control.EditText;
public bool OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
{
if ((actionId == ImeAction.Done) || ((actionId == ImeAction.ImeNull) && (e.KeyCode == Keycode.Enter)))
{
Control.ClearFocus();
//HideKeyboard();
((IEntryController)Element).SendCompleted();
}
return true;
}
public virtual void AfterTextChanged(IEditable s)
{
}
public virtual void BeforeTextChanged(ICharSequence s, int start, int count, int after)
{
}
public virtual void OnTextChanged(ICharSequence s, int start, int before, int count)
{
if (string.IsNullOrWhiteSpace(Element.Text) && (s.Length() == 0)) return;
((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, s.ToString());
}
protected override TextInputLayout CreateNativeControl()
{
var textInputLayout = new TextInputLayout(Context);
var editText = new EditText(Context);
#region Add the custom Keyboard in your Page
var activity = Forms.Context as Activity;
var rootView = activity.Window.DecorView.FindViewById(Android.Resource.Id.Content);
activity.Window.SetSoftInputMode(SoftInput.StateAlwaysHidden);
activityRootView = ((ViewGroup)rootView).GetChildAt(0) as ViewGroup;
mKeyboardView = new CustomKeyboardView(Forms.Context, null);
Android.Widget.RelativeLayout.LayoutParams layoutParams =
new Android.Widget.RelativeLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.WrapContent); // or wrap_content
layoutParams.AddRule(LayoutRules.AlignParentBottom);
activityRootView.AddView(mKeyboardView, layoutParams);
#endregion
//First open the current page, hide the Keyboard
mKeyboardView.Visibility = ViewStates.Gone;
//Use the custom Keyboard
mKeyboard = new Android.InputMethodServices.Keyboard(Context, Resource.Xml.keyboard2);
mKeyboardView.Keyboard = mKeyboard;
mKeyboardView.Key += async (sender, e) =>
{
long eventTime = JavaSystem.CurrentTimeMillis();
KeyEvent ev = new KeyEvent(eventTime, eventTime, KeyEventActions.Down, e.PrimaryCode, 0, 0, 0, 0, KeyEventFlags.SoftKeyboard | KeyEventFlags.KeepTouchMode);
DispatchKeyEvent(ev);
await Task.Delay(1);
};
textInputLayout.AddView(editText);
return textInputLayout;
}
protected override void OnElementChanged(ElementChangedEventArgs<MyEntry> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
if (Control != null)
EditText.FocusChange -= ControlOnFocusChange;
if (e.NewElement != null)
{
var ctrl = CreateNativeControl();
SetNativeControl(ctrl);
EditText.ShowSoftInputOnFocus = false;
EditText.FocusChange += ControlOnFocusChange;
}
}
private void ControlOnFocusChange(object sender, FocusChangeEventArgs args)
{
_hasFocus = args.HasFocus;
if (_hasFocus)
{
EditText.Post(() =>
{
EditText.RequestFocus();
ShowKeyboardWithAnimation();
});
}
else
{
//Hide the Keyboard
mKeyboardView.Visibility = ViewStates.Gone;
}
}
public void ShowKeyboardWithAnimation()
{
if (mKeyboardView.Visibility == ViewStates.Gone)
{
mKeyboardView.Visibility = ViewStates.Visible;
Android.Views.Animations.Animation animation = AnimationUtils.LoadAnimation(
Context,
Resource.Animation.slide_in_bottom
);
mKeyboardView.ShowWithAnimation(animation);
}
}
}

Fail to connect to camera service at sometimes

Am calling my camera function as separate fragment during first 2 times of calling the class camera is opening but if am calling the class third time app is crashing.
private int findFrontFacingCamera() {
int cameraId = 0;
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
cameraFront = true;
break;
}
}
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1;
//Search for the back facing camera
//get the number of cameras
int numberOfCameras = Camera.getNumberOfCameras();
//for every camera check
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
cameraFront = false;
break;
}
}
return cameraId;
}
public void onResume() {
super.onResume();
if (!hasCamera(myContext)) {
Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
toast.show();
finish();
}
if (mCamera == null) {
//if the front facing camera does not exist
if (findFrontFacingCamera() < 0) {
Toast.makeText(getActivity().getApplicationContext(), "No front facing camera found.", Toast.LENGTH_LONG).show();
switchCamera.setVisibility(View.GONE);
}
mCamera = Camera.open(findFrontFacingCamera());
mPicture = getPictureCallback();
mPreview.refreshCamera(mCamera);
}
}
logcat
01-19 10:56:15.164 11477-11477/com.example.siva.prep E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.siva.prep, PID: 11477
java.lang.RuntimeException: Fail to connect to camera service
at android.hardware.Camera.native_setup(Native Method)
at android.hardware.Camera.<init>(Camera.java:393)
at android.hardware.Camera.open(Camera.java:347)
at com.example.siva.prep.Selfie.onResume(Selfie.java:146)
It's showing error on the following line in "onResume()" method:
mCamera = Camera.open(findFrontFacingCamera());
Here is the full my code am using:
public class Selfie extends Fragment implements OnClickListener {
private Camera mCamera;
private CameraPreview mPreview;
private PictureCallback mPicture;
private Button capture, switchCamera;
private Context myContext;
private LinearLayout cameraPreview;
private boolean cameraFront = false;
Bitmap bmp;
ImageView iv;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_selfie, container, false);
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
iv=(ImageView) view.findViewById(R.id.image);
myContext = getActivity().getApplicationContext();
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
cameraPreview = (LinearLayout) view.findViewById(R.id.camera_preview);
mPreview = new CameraPreview(myContext, mCamera);
cameraPreview.addView(mPreview);
ImageView capture = (ImageView) view.findViewById(R.id.button_capture);
capture.setOnClickListener(captrureListener);
ImageView switchCamera = (ImageView) view.findViewById(R.id.button_ChangeCamera);
switchCamera.setOnClickListener(switchCameraListener);
ImageView button1 = (ImageView) view.findViewById(R.id.back);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FreeFragment fragment2 = new FreeFragment();
FragmentManager fragmentManager = getFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, fragment2);
fragmentTransaction.commit();
}
});
getSupportActionBar().hide();
return view;
}
private ActionBar getSupportActionBar() {
return ((AppCompatActivity) getActivity()).getSupportActionBar();
}
#Override
public void onClick(View v) {
}
private int findFrontFacingCamera() {
int cameraId = 0;
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
cameraFront = true;
break;
}
}
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1;
//Search for the back facing camera
//get the number of cameras
int numberOfCameras = Camera.getNumberOfCameras();
//for every camera check
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
cameraFront = false;
break;
}
}
return cameraId;
}
public void onResume() {
super.onResume();
if (!hasCamera(myContext)) {
Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
toast.show();
finish();
}
if (mCamera == null) {
//if the front facing camera does not exist
if (findFrontFacingCamera() < 0) {
Toast.makeText(getActivity().getApplicationContext(), "No front facing camera found.", Toast.LENGTH_LONG).show();
switchCamera.setVisibility(View.GONE);
}
mCamera = Camera.open(findFrontFacingCamera());
mPicture = getPictureCallback();
mPreview.refreshCamera(mCamera);
}
}
private void finish() {
}
OnClickListener switchCameraListener = new OnClickListener() {
#Override
public void onClick(View v) {
//get the number of cameras
int camerasNumber = Camera.getNumberOfCameras();
if (camerasNumber >= 1) {
//release the old camera instance
//switch camera, from the front and the back and vice versa
releaseCamera();
chooseCamera();
} else {
Toast toast = Toast.makeText(myContext, "Sorry, your phone has only one camera!", Toast.LENGTH_LONG);
toast.show();
}
}
};
public void chooseCamera() {
// if the camera preview is the front
if (cameraFront) {
int cameraId = findBackFacingCamera();
if (cameraId <= 0) {
//open the backFacingCamera
//set a picture callback
//refresh the preview
mCamera = Camera.open(cameraId);
mPicture = getPictureCallback();
mPreview.refreshCamera(mCamera);
}
} else
{
int cameraId = findFrontFacingCamera();
if (cameraId >= 0) {
//open the backFacingCamera
//set a picture callback
//refresh the preview
mCamera = Camera.open(cameraId);
mPicture = getPictureCallback();
mPreview.refreshCamera(mCamera);
}
}
}
#Override
public void onPause() {
super.onPause();
//when on Pause, release camera in order to be used from other applications
releaseCamera();
}
private boolean hasCamera(Context context) {
//check if the device has camera
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
private PictureCallback getPictureCallback() {
PictureCallback picture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//make a new picture file
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
//write the file
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast toast = Toast.makeText(myContext, "Picture saved: " + pictureFile.getName(), Toast.LENGTH_LONG);
iv.setImageURI(Uri.fromFile(pictureFile));
//Intent intent = new Intent(AndroidCameraExample.this,Fina.class);
String stringUri;
stringUri = pictureFile.toString();
//intent.putExtra("imagePath", stringUri);
//startActivity(intent);
FreeFragment ldf = new FreeFragment ();
Bundle args = new Bundle();
args.putString("Image", stringUri);
ldf.setArguments(args);
Log.d("Passing image", String.valueOf(args));
getFragmentManager().beginTransaction().add(R.id.container, ldf).commit();
toast.show();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
//refresh camera to continue preview
mPreview.refreshCamera(mCamera);
}
};
return picture;
}
//make picture and save to a folder
public static File getOutputMediaFile() {
//make a new file directory inside the "sdcard" folder
File mediaStorageDir = new File("/sdcard/", "JCG Camera");
//if this "JCGCamera folder does not exist
if (!mediaStorageDir.exists()) {
//if you cannot make this folder return
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
//take the current timeStamp
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
//and make a media file:
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
OnClickListener captrureListener = new OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
};
private void releaseCamera() {
// stop and release camera
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
}
Irrespective of the reason, not obtaining Camera handle is a case that needs to be handled with proper error handling. In the current case in your Pause handler, is the Camera instance being released ? Check for proper usage at http://developer.android.com/training/basics/activity-lifecycle/pausing.html

Resources