Android ViewPager and Camera Preview issue on Gingerbread - camera

I did extensive documentation study on ViewPagers and on Camera apps, infact everything works quite fine, except for a major issue on GingerBread, which I haven't found any question about on S.O. so I'll try asking this one...
In my application there is a ViewPager (support library v4) which shows two fragments:
One, will call it the main fragment, the one showing when the activity starts, certain information are shown to the user, including an imageview, which is initially empty and hidden.
By swyping to the next fragment, the user sees the camera preview, which gets created when the activity is created (even if it not showing until the swype) and the button to take a picture.
When the picture is taken, the view is programmatically taken back to the main fragment, the
imageview is loaded with the new photo and unhidden so the user can see the image mixed with the other preexisting information.
If the user does not like picture, he can swype back again to the camera fragment and take another one, and so all over until he is satisfied with the result.
For this reason, before flipping back to the main fragment, I call mCamera.restartPreview() and ensure the camera is ready should the user swype back.
Everything works smoothly and fine on Android 4.x, but when I test this on a 2.3.3 (API Level 10) the camera preview remains in foreground when the main fragment is called back, and hides the view. You can see, and even scroll, the remainder of the view, in the portion of teh screen where the camerafragment shows the buttons, but the rest is overlapped by the camera preview.
Here is the code of the relevant functions:
CameraFragment onPictureTaken()
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
Log.e(TAG, "FILE " +pictureFile.getAbsoluteFile().toString());
Bitmap bitmap = rotated(data);
bitmap.compress(CompressFormat.JPEG, PICTURE_QUALITY, fos);
bitmap.recycle(); //devo davvero chiamarla esplicitamente ??
mediaFile = pictureFile;
mPreview.restartPreview();
// go back to newpin activity to show it
((NewPinActivity) myActivity).newPin.setMedia(mediaFile.getAbsoluteFile().toString());
((NewPinActivity) myActivity).takeBack();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
}
}
};
and the mainfragment takeBack() method
public void takeBack(){
mViewPager.setCurrentItem(0, true);
String mainFragTag = "android:switcher:"+R.id.newpinpager+":0";
Fragment fragMain = this.getSupportFragmentManager().findFragmentByTag(mainFragTag);
try {
((NewPinMainFragment)fragMain).showPhoto(newPin.getMedia());
} catch (NullPointerException e){
}
}
Does anybody have a clue if this is an issue with the ViewPager and GingerBread or with the CameraPreview and Gingerbread or what ?

I found the answer by myself, I'll post it here in case it's going to be useful to others.
Apparently the problem was cause by the smoothscroll option of setCurrentItem method.
The issue was fixed by changing
mViewPager.setCurrentItem(0, true);
to
mViewPager.setCurrentItem(0, false);

Related

talkback not focusing by default on any view on start of inner fragment

I am using accessibility talkback functionality and I am facing one problem I have one bottom navigation in the parent activity and from the setting tab I am opening another fragment(inner fragment) using .add but the inner fragment view not getting focus by default
I also tried with . replace but it's not focusing by default on fragment creation.
open fragment code
val details = DetailsFragment.newInstance();
getSupportFragmentManager().setupForAccessibility()
getSupportFragmentManager().beginTransaction().add(android.R.id.content, details).commit()
and I used this extension function to not get focus on the previous fragment from this source
fun FragmentManager.setupForAccessibility() {
addOnBackStackChangedListener {
val lastFragmentWithView = fragments.lastOrNull { it.view != null }
for (fragment in fragments) {
if (fragment == lastFragmentWithView) {
fragment.view?.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_YES
} else {
fragment.view?.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
}
}
}
}
in normal I show that at the start of the first fragment it's focusing top first Textview and speaking automatic but in the inner fragment it's not focusing by default so what should I do to get focus by default on the first view by default
I already try
android:focusable="true"
android:focusableInTouchMode="true"
and request focus but it's not working
Please suggest me any help would be highly appriciated
I've had the best luck using
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
on the view you want to focus, or maybe
Handler().postDelayed({
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
}, someDelayMillis)
to let the system do whatever it does, and then jump in after a moment and force a focus change.
But this might be considered bad accessibility, if it's interfering with the usual navigation, and that might be why it's so hard to get focus working consistently! It might be better to just announce the new fragment (with something like view.announceForAccessibility("new fragment")) and let the user start navigating from the top. It depends on your app, it's your call
Also you probably want to use replace for your fragment instead of add, if you add a fragment on top of an old one, TalkBack can get stuck looking at the "invisible" views on the old fragment
this is my improved code that extends from #cactustictacs
//target to specific a view
binding.getRoot().postDelayed(new Runnable() {
#Override
public void run() {
binding.textView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
}, 300);
full: https://github.com/dotrinh-PM/AndroidTalkback

Using front camera on wp8 code

I was using this Microsoft sample http://code.msdn.microsoft.com/wpapps/Basic-Camera-Sample-52dae359#content because I needed to implement camera functionality in my application. Ans this is working fine until I try to switch to front camera then the app just closes and I get this
The program '[3032] TaskHost.exe' has exited with code -532265403 (0xe0464645)
I was going through the code and I found out that this part of code causes the problem
public FlashState FlashState
{
get { return (FlashState) (uint) PhotoCaptureDevice.GetProperty(KnownCameraPhotoProperties.FlashMode); }
set
{
try
{
PhotoCaptureDevice.SetProperty(KnownCameraPhotoProperties.FlashMode, value);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
}
It doesn't hit catch, just closes the app. The same thing is happening if I set Front Camera as a default one. Did anyone had this problem?
[SOLUTION]
Ok, after trying everything - event posting here, now I have a solution. In the try block above I added this line
if (CameraSensorLocation == CameraSensorLocation.Front)
return;
so now it doesn't crush, and the front camera is working fine. They should change this in official sample.
Ok, after trying everything - even posting here, now I have a solution. In the try block above I added this line
if (CameraSensorLocation == CameraSensorLocation.Front) return;
so now it doesn't crush, and the front camera is working fine.

Eclipse Plug-in:Focus lost after activating a view via (controlSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE));

I have a view which is initialised via OleControlSite and invoked via OleAutomation. It is actually a media player which I call in a view after user right clicks the file and calls Play in the context menu. Whenever I play a file by first right clicking and calling Play, it plays absolutely fine. The problem is when user displays the view before doing a right click(Window->Show View->Other->MyView) and then tries to do a right click and Play, at this point of time ISelection returns null and hence nothing plays.
IWorkbenchPage iwPage=PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
ISelection selection=iwPage.getSelection();
The problem is the selections somehow loses focus if the view has been invoked in the fashion described.
This is how the view is initialised when the plugin is loaded
public void createPartControl(Composite parent) {
frame = new OleFrame(parent, SWT.APPLICATION_MODAL);
// OleControlSite controlSite;
try {
controlSite = new OleControlSite(frame, SWT.APPLICATION_MODAL,"WMPlayer.OCX.7");
controlSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
oleAutomation = new OleAutomation(controlSite);
makeActions();
fillActionBars();
} catch (SWTException ex) {
MessageBox box = new MessageBox(getSite().getShell(),SWT.ICON_INFORMATION);
box.setMessage("Failed to Initialise Media Player.");
box.setText("Error");
box.open();
ex.printStackTrace();
return;
}
}
Is there a way where we can force the focus to the Project Explorer where the current file is selected ?

Windows Phone 7 Control Caching - 'Element is already the child of another element'

I'm trying to speed up my windows phone 7 page load times. I have a 'static' page that has a dynamically created in a Panorama control - static meaning that the content never changes.
On the first load I look at my config file, create the individual PanoramaItem controls and add them to the main Panorama control. I'm trying to keep a List in a static place so that the initial creation would only happen once and I could just add a fully rendered version to my Panorama control when the page was rendered.
Works fine on first load, but when I try to add the cached PanoramaItems to the Panorama control I get the message "Element is already the child of another element". This makes sense since I already added before. But I can see a way to disconnect the PanoramaItems with the first Panorama control...
I could be going about the control caching thing all wrong as well... Let me know if there's another way to do this.
You can use Panorama.Items.Remove(pivotItem) for this
As an example
With the following page fields
PanoramaItem pi;
bool blahShown = false;
On the press of this button, the control is first instantiated and displayed and on subsequent presses removed and readded without instantiation.
private void button1_Click(object sender, RoutedEventArgs e)
{
if (pi == null) {
pi = new PanoramaItem();
pi.Header = "blah";
}
if (blahShown) {
Pano.Items.Remove(pi);
blahShown = false;
} else {
Pano.Items.Add(pi);
blahShown = true;
}
}

Silverlight Navigation and Authentication service

I am creating a silver light application using Navigation app template. It is for internal use and hence uses windows authenticatoin. There is a dashboard page which shows couple of records filtered by logged in users id. To get the user id (which is an int) I call a web service by overriding the GetAuthenticatedUser and pass the username (from IPrincipal). This service takes some time to return the details.
When I navigate to dashboard app, it renders completely with no data because the user service is a async operation and I am not able to make the rendering wait till my GetAuthenticatedUser finishes completely. So I created a Login page which just shows a progress bar till I get the user object and then navigate to dashboard. If someone tries to access the dashboard directly by using the URL, i want them to navigate back to Login page.
So in the dashboard constructor I added the following code
if (!UserService.Current.User.IsAuthenticated)
{
MessageBox.Show("Navigating away");
Frame objContainer = this.Parent as Frame;
objContainer.Navigate(new Uri("/Views/Login.xaml", UriKind.Relative));
}
Thogh I get the message box prompt, it does not actually take me to Login page but stays in dashboard page. I also tried putting this code in OnNavigatedTo override with no luck.
I also tried using NavigationService instead of Frame as below, with no luck
if (!UserService.Current.User.IsAuthenticated)
{
MessageBox.Show("Navigating away");
this.NavigationService.Navigate(new Uri("/Views/Login.xaml", UriKind.Relative));
}
it still does not work. Does anyone know how to make some page accessible only if I have fully valid user object? if they try to access the restricted page without this, I want them to be able to redirected to Login page, how can this be achieved?
I am using Silverlight 3 Beta
Shreedhar
I finally found a way around this. In the Constructo i Hooked up the Loaded event handler and in the event handler I am navigating to a different page and it works fine now.
public Dashboard()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Dashboard_Loaded);
}
void Dashboard_Loaded(object sender, RoutedEventArgs e)
{
if (!UserService.Current.User.IsAuthenticated)
{
Frame objContainer = this.Parent as Frame;
if (objContainer != null)
{
objContainer.Navigate(new Uri("/Views/Login.xaml", UriKind.Relative));
}
}
}
This piece of code works just fine!
Shreedhar