Setting Android Activity screen orientation with values.xml - java

I am trying to setup activity screen orientation with values from XML file in res/values. I would like to do that because, more or less, I need same Activity for both tablet (landscape) and smartphone (portrait).
First try
Manifest:
<activity android:name="..." android:screenOrientation="#string/defaultOrientation"/>
config.xml:
<string name="defaultOrientation">portrait</string>
But with this setting application won't appear on device and it will return this error:
java.lang.NumberFormatException: Invalid int: "portrait"
Second
OK, so I simply changed it to this
Manifest:
<activity android:name="..." android:screenOrientation="#integer/defaultOrientation"/>
config.xml:
<integer name="defaultOrientation">1</integer>
I used 1 because ActivityInfo.SCREEN_ORIENTATION_PORTRAIT == 1.
But this is not working either. It seems that I may modify some values like application / activity name but not screen orientation ?
I know that I may workaround it by code but for some reason it feels that this also should be obtainable by XML values file.
It is somehow possible to achieve it by XML values ?

Same problem for me with your second exlanation and I used a workaround by code which you aren't looking for.
I added 4 values folders under res folder. "values", "values-v11", "values-v14" and "values-sw720dp"
All values folders have "integers.xml".
"values" and "values-v14" have value 1 which is portrait orientation;
<integer name="portrait_if_not_tablet">1</integer>.
"values-v11" and "values-sw720dp" have value 2 which is user orientation;
<integer name="portrait_if_not_tablet">2</integer>.
And in Manifest file, activity has a property like;
android:screenOrientation="#integer/portrait_if_not_tablet".
All "values", "values-v11", "values-v14" are working as expected but "values-sw720dp"!
While debugging I realized that value of portrait_if_not_tablet comes as expected on a sw720dp device(with API 16) with getResources().getInteger(R.integer.portrait_if_not_tablet) but when i checked the value of current orientation by getRequestedOrientation() I got a different value.
int requestedOrientation = getResources().getInteger(R.integer.portrait_if_not_tablet);
int currentOrientation = getRequestedOrientation();
if (currentOrientation != requestedOrientation) {
setRequestedOrientation(requestedOrientation);
}
So I used a code block on onCreate method of my activities to solve this.

Related

Lock screen orientation when targeting Android API 27 with a non-opaque activity

I have an activity that has android:windowIsTranslucent set to true and android:windowBackground set to a translucent background. I just changed my target and compile sdk version to 27, and I get an exception when launching this activity now:
java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
Since this is a new sdk, there isn't anything online about it yet (and it seems to result from this line of code: https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/android/app/Activity.java#987 )
Is there any way to get around this? The app doesn't crash if I take out android:screenOrientation="portrait" from my manifest for this activity, but I would like to be able to keep it like that.
I also faced the same problem.
As others said, If I deleted android:screenOrientation="portrait" or overrided it with android:screenOrientation="unspecified", then the exception was gone.
And it seems that the front activity's orientation follows the behind activity's orientation.
I thought about it.
If the front activity is transparent and the behind activity's orientation is different,
the display becomes strange.
So, I can understand why this check logic was added
However, I wonder that why this problem was not occurred in Developer Preview 8.0.0.
The workaround is to set targetSdk back to 26.
The reason why is your application crashes is here in this commit.
As you can see here, you are not the only one - this behavior has been reported to Google as issue. It has been fixed, but we don't know how and when it will be released.
I can also confirm what "sofakingforever" says in comments, if there is non-translucent activity with fixed orientation behind your translucent, the translucent will not rotate. So you can just remove android:screenOrientation="portrait" from manifest as well.
The solution worked for me is deleting
android:screenOrientation="portrait"
from all the full screen transparent activities which means their theme contains
<item name="android:windowIsTranslucent">true</item>
Also to make sure that orientation works correct for below Oreo I added this to the onCreate() of the activities.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This activity is a fullscreen transparent activity, so after Oreo Android doesn't allow fullscreen
// transparent activities to specify android:screenOrientation="portrait" in the manifest. It will pick up
// from the background activity. But for below Oreo we should make sure that requested orientation is portrait.
if (VERSION.SDK_INT < VERSION_CODES.O) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
I solved this issues by changing this line in NoActionBar styles
In target version 27 only i got this issue and i solved by using below line
<item name="android:windowIsTranslucent">false</item>
So what I did was remove any screenOrientation property from manifest and add it to my BaseActivity (from which all my activities extend), this code
if(!(this instanceof TranslucentActivity)){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
The TranslucentActivity will have the orientation from the Activity behind.
it seems like it's a new feature/bug on API 27.
However, you can delete
android:screenOrientation
Or
android:screenOrientation="unspecified"
I recently faced the issue and here's the solution.
No need to change the screen orientation parameter which you set at the android manifest file.
Just add two folders in
res>values
as res>values-v26
and res>values-v27
Then copy your styles.xml and themes.xml file there.
and change the following parameters from TRUE to FALSE.
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowIsTranslucent">false</item>
It will work.
A common bug of Android 8.0
Thanks #JerabekJakub. My test result - keep sdk 27 and remove the following lines can also solve the crash.
android:configChanges="orientation"
android:screenOrientation="portrait"
1) Remove this
android:screenOrientation="portrait"
from minifiest.xml
2) on Activity add these two lines
protected void onCreate(Bundle savedInstanceState) {
setOrientation(this)
super.onCreate(savedInstanceState);
// other other all code here
}
3) Just copy-paste the code in your Activity
public static void setOrientation(Activity context) {
if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.O)
context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
else
context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
I had this problem on Android 8 using BottomSheetDialogs. It was crashing every time I open some translucent bottom sheet dialog.
I fixed the problem by adding new theme.xml in values-v26, with same theme as default one, but completely removing windowIsTranslucent item from there.
After that, I still had translucent bottom sheet dialogs in my app and it is working perfectly.
Found it interesting. It may help someone using these dialogs.

Calling two different activities on different devices (tablet and phone)

Here, I'm trying to start an activity on different devices (Android Tablet and Android Phone). Is there a way to use if statement to check which activity should to load based on the devices?
Here's my code:
Button buttonGo = (Button) findViewById(R.id.button_goToActivity);
buttonGo.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (tablet device) {
startActivity(new Intent(MainActivity.this, TabletActivity.class));
} else {
startActivity(new Intent(MainActivity.this, AndroidPhoneActivity.class));
}
});
Thanks for your effort...
In order to achieve that you must use Fragment not an Activity. the Design Philosophy of Fragments is exactly what you want. you can take a look at Example to see how it is implemented. This is a master-detail app with two Fragments, when device in a portrait mode or it is not a tablet it just shows master, otherwise it also shows detail beside the master and when you select an item from the list you will see the details without going to other Activity.
Firstly as Android Best Practice it is adviced to use Fragments rather than Activity to achieve your requirement.
But if you are keen on using Activity, then below is the solution to find device type and load different activities.
1) Have 2 values folders: values -> strings.xml and values-sw600dp -> strings.xml
2) Create string value in both the xml
<string name="device_type">PHONE</string> in values -> strings.xml
<string name="device_type">TABLET</string> in values-sw600dp -> strings.xml
3) create a method to check if current device is Phone or not
public boolean isPhone() {
String deviceType = getResource().getString(R.string.device_type);
if (deviceType.equalsIgnoreCase("PHONE") {
return true;
} else {
return false;
}
}
4) Depending on the device load your activity as you have already done in your above code snippet
Let me know if this helps...
Most likely, you should not have two separate activities here. Instead, you should have two different layouts for the same activity. The layout for phones should be in the regular res/layout folder and the layout for tablets should be in the res/layout-large folder. Read Supporting Different Screens for more details.
If you are using same fuctionality for Tablet Activity and Phone activity then you do not need two activities for this purpose. You need to make two different Layout xml for Tablet as well as Phone.
Make a Layout folder named : layout-large and layout-xlarge.
Now copy the xml file from normal layout folder and paste in both new layout folders.
No need to change the name of xml file.
Now Adjust xml file of layout-large and layot-xlarge as you want to make design for tablet.
Now on running application Tablet and phone bot will pick xml according to there size and screen density.
Note : the functionality should be same.
And if: you want to show different screen with different functionality for phone and tablet then. use this code for check.
if ((getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {
}
Hope this wll help you.

Android In App Billing From PreferenceScreen

I have never really had to ask a question here. Almost any question I can think of has already been asked and answered. Thus the reason I have never registered.
However, I have finally run across something that I cannot find an answer for. I assume it would be fairly simple.
I am trying to implement in app billing for an android project I am working on. I typically code in C# and use Unity to build the .APK.
However, this time I have to make modifications in Eclipse to some PreferenceScreens.
I have an xml file with some string-arrays set up for a ListPreference under my PreferenceScreen. These ListPreference values are then passed to UnityPlayer for a method. That's all set up.
I am trying to figure out a way to set up in app billing to trigger on selection of one of my list preference, or preference items.
I can probably figure a lot of it out on my own, but I need help with a function to do something pulling from a string value in the list preferences. Does this make sense?
I don't expect to be spoon fed, so if I can just get help on a few lines for this I would appreciate it. Of course I won't complain if anyone wants to write up a little 20 liner function to do it for me.
Thanks in advance,
John
** edit **
Here is the xml from the preferenceScreen I need to address with android In App Billing from Java
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="wallpaper_settings"
android:title="#string/wallpaper_settings" >
<!-- Ad Placeholder -->
<CheckBoxPreference
android:defaultValue="true"
android:key="rotate"
android:summary="#string/rotateSummary"
android:title="#string/rotateTitle" />
<CheckBoxPreference
android:defaultValue="true"
android:key="doubleTap"
android:summary="#string/doubleTapSummary"
android:title="#string/doubleTapTitle" />
<CheckBoxPreference
android:defaultValue="false"
android:key="swipeEmul"
android:summary="#string/simulateSwipeSummary"
android:title="#string/simulateSwipeTitle" />
<ListPreference
android:entryValues="#array/cameraValues"
android:defaultValue="MainCamera"
android:entries="#array/whichCam"
android:summary="#string/cameraSummary"
android:dialogTitle="#string/cameraTitles"
android:title="#string/cameraTitles"
android:key="whichCam"/>
</PreferenceScreen>'
This question is very generic, on an Android application you might do this by creating an Activity, then starting that activity from your preference "onClick" method and then, once the activity starts, you load all your in app billing stuff (showing a progress dialog) and finally present the "buy" dialog. Is this what you need?

Load a string resource based on selected MenuItem resource ID - Android JAVA

I am writing my first Android app. It will have hundreds of menu links that will change with each version released. I am looking for a way to process the onclicks based on the Resource ID.
Menus are defined in XML like so:
<item android:id="#+id/Spring_2013" android:title="Spring 2013" android:showAsAction="ifRoom|withText" />
The onclicks will load a URL stored in strings.xml:
<string name="Summer_2013">file:///android_asset/catalog/current/genadmissionreq.html</string>
So, seems like all I need is a simple, single onclick method that loads whatever string is needed based on the selected Resource ID. The MenuItem ID is ALWAYS equal to the URL string ID in my code. So, without using hundreds of if() or switch/case statments, cant I just say:
String url = getString("R.string." + menuItem.getItemId());
Obviously that assignment wont work for a number of reasons. But you get the idea right? So, how CAN I make this work?
Im sorry for the newb question. I know it should be simple but I've been reading for days and cannot find any way to do this without an if() statement for EVERY menu item. That method would make the weekly updates a nightmare!
Try using getIdentifier()
String title = menuItem.getTitle().toString().replace(' ', '_');
id = getResources().getIdentifier(title, "string", getPackageName());
String string = getString(id);
The first line fetches Spring 2013 and converts it to Spring_2013.
The second line builds "R.string." with whatever the title is, in this case "R.string.Spring_2013".
The third line simply fetches the String resource.

Android receive images from Gallery in order

I currently have an Android application that has an intent-filter to receive images from the Gallery. It is important that the images are received in the same order that the user selected them in. This seems to be the default behavior on most devices, however on some devices (so far I've seen this on Motorola's running Android 4.x) the order seems undefined. Does anyone know a way to declare in the intent that the images should be received in order? Or a way once the images are recieved to determine the selected order?
Here is relevant code from the manifest
<activity
android:label="#string/app_name"
android:name=".activities.ImportImagesActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
And from ImportImagesActivity
private List<Uri> parseIncomingData() {
List<Uri> uriList = null;
Intent intent = this.getIntent();
if(intent != null) {
String action = intent.getAction();
//Single Image
if (action.equalsIgnoreCase("android.intent.action.SEND")) {
//removed for brevity
}
}
//Multiple Images
else if (action.equalsIgnoreCase("android.intent.action.SEND_MULTIPLE")) {
uriList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
}
}
//more code - at this point images have been recieved
return uriList;
}
EDIT
To give a little context, let me explain the general flow of the app.
The user opens the Gallery and selects images. They choose to 'Share' them with my app. My application receives a list of Uri's which are then displayed using an internal gallery backed by a custom Adapter class. The images display correctly based on the Uri list, the issue is the order of the List<Uri> is sometimes incorrect. It is important to my users that the images appear in the same order they select them in.
Clarification
When I use the term Gallery I am referring to the built in Android app Gallery.
When I use the term 'Share' I am referring to the the Share button within the Gallery app. This allows the user to select from a list of services such as Facebook, Email, and in this case my app.
For Example
imagine a Gallery with 3 images, displayed in an arbitrary order: A, B, and C. The user selects first C then A then B and chooses to share them with my app. On most phones my list will be correctly ordered {C, A, B}, on offending phones this order seems random.
I cannot use the creation timestamp because the creation time is generally irrelevant to the selection order. Adding custom meta data doesn't help either because I don't know the correct initial order.
My observation is that Android gallery displays images in accordance to their recency.
For the devices where you're unable to determine the order, you can import the images from the gallery and check their creation time. Here's a way to do that. Or you could use a metadata extractor app, many jars can be found.
Now, you could just arrange the images in the order of recency and you should be done.
[EDIT]
I have a question. You said they may be selected in any order, so are they "uploading" it onto a server by "sharing"?
If so, then one way is to check which image was uploaded or if you want the order of selection, you could do this. Edit the metadata of the images, there's bound to be a useless tag, select one and edit it on touch. So, if I select image A it changes to 1 and then I select image B it becomes 2. But if I unselect image A now then image B should become 1. So, you could use nodes here. This is the first in first out (FIFO) method. Upon un-selection, A is thrown out of the list and B replaces it.
Is this what you wanted?
EDIT
Sorry, I don't think you can do this without creating your own gallery. Why don't you just import the android gallery into a grid view in your app?
Yeah, I just faced the same problem right now. I am also using Fedor's lazy loading concept.I am not sure how far this will be helpful and whether this is the right approach. But still it solved the problem for me.
I had to do a little modification in the getView(),
#Override
public View getView(int position, View convertView, ViewGroup parent) {
System.gc();
ImageView view;
if(convertView == null) {
view = new ImageView(context);
view.setScaleType(ImageView.ScaleType.FIT_CENTER);
view.setLayoutParams(new GridView.LayoutParams(screenWidth/4, screenHeight/4));
view.setAdjustViewBounds(false);
view.setPadding(2, 2, 2, 2);
System.gc();
}else {
view = (ImageView) convertView;
}
if(view!=null)
{
imageLoader.DisplayImage(urlList.get(position), view);
notifyDataSetChanged(); //Calling this helped to solve the problem.
}
System.gc();
return view;
}

Categories