ActivityOptionsCompat not working in android 2.3 - android

I have implemented window animations using ActivityOptionsCompat and ActivityCompat which is recently supported in android support-v4 library.
I have used below code for implement animation:
Intent subActivity = new Intent(WindowAnimations.this,
AnimatedSubActivity.class);
// The enter/exit animations for the two activities are
// specified by xml resources
Bundle translateBundle = ActivityOptionsCompat
.makeCustomAnimation(WindowAnimations.this,
R.anim.slide_in_left, R.anim.slide_out_left)
.toBundle();
ActivityCompat.startActivity(WindowAnimations.this,
subActivity, translateBundle);
Above code is working fine in android 4.3 and 4.0.
Anybody able to make it work in 2.X?Any help is appreciated.

#Luksprog basically already answered this in the first on your question, but here's some more documentation to further support that claim.
First, read the the javadoc for ActivityCompat#startActivity(Activity activity, Intent intent, Bundle options) carefully. I've highlighted some relevant keywords:
Start an activity with additional launch information, if able.
In Android 4.1+ additional options were introduced to allow for more
control on activity launch animations. Applications can use this
method along with ActivityOptionsCompat to use these animations when
available. When run on versions of the platform where this feature
does not exist the activity will be launched normally.
So that basically tells us that the (optional) animations feature will only work on versions of Android that natively support it. On all other platform versions, the Activity will be launched 'normally' - that is, without the optional animation.
The actual proof can easily be found in the source code of ActivityCompat:
public static void startActivity(Activity activity, Intent intent, Bundle options) {
if (Build.VERSION.SDK_INT >= 16) {
ActivityCompatJB.startActivity(activity, intent, options);
} else {
activity.startActivity(intent);
}
}
In other words: if this code is executed on a pre-JB device, a plain old startActivity() call will be mad, where the options parameter gets ignored. Only JB devices will end up using that.
Perhaps redundant to mention, but obviously the same applies to the startActivityForResult() counterpart.
To summarize: Currently the Support Library simply offers a static helper class to execute certain functionality in "a backwards compatible fashion" - it doesn't actually backport that functionality (yet). All it does at this stage is save you having to write the if/else condition in your own app.
That being said, the current implementation does allow for a future backport of the actual functionality. That's possibly also why the ActivityOptionsCompat class exists. Right now the class provides an 'empty' implementation for pre-JB devices, which, in theory, could be 'filled' at a later stage. Any code calling through these compatibility helpers will then automagically start working.
Example of an ActivityOptionsCompat call returning an empty implementation:
public static ActivityOptionsCompat makeCustomAnimation(Context context,
int enterResId, int exitResId) {
if (Build.VERSION.SDK_INT >= 16) {
return new ActivityOptionsImplJB(
ActivityOptionsCompatJB.makeCustomAnimation(context, enterResId, exitResId));
}
return new ActivityOptionsCompat();
}

Related

Activity Background change dynamic

I have just started developing an android weather app and I was wondering how to change activity background automatically. For example, in daytime it should show day time or in the night it should show night photos.
This is the app of Sony which has a feature (mentioned above)
Check the screenshots.
Okay Credit goes to SteD;so for you check this(beginner's guide)
Follow this
//set an ID for Relative Layout in content_main.xml(Android Studio)
RelativeLayout rlayout=(RelativeLayout)findViewById(R.id.rlayout);
if(something){Drawable drawble=getResource().getDrawable(R.drawable.your_image);rlayout.setBackgroundDrawable(drawable);}
//If it works,destroy the upvote
The only automatic way is the newly released (Day/Night theme for android app)
For finer control you check the condition yourself and call the normal Java methods, like this:
if(something) {
getWindow()
.setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.image));
}
of if you don't care about the newly introduced context themed styling, you just call the deprecated method (which will keep working without issues for all the foreseeable future)
if(something) {
getWindow()
.setBackgroundDrawable(
getResources().getDrawable(R.drawable.image));
}

How to add an item to Quick Settings in Android

I was thinking if there is a way to add an item in Quick Settings Panel in android ?
I have an app called Mirror by Koushik Dutta that does the same. It adds an item in Quick Settings panel. I decompiled the app and saw that he's moving the apk to /system/priv-app .
That's it. Nothing's related to adding an item in Quick Settings Toggle.
I know it'll require root access (just a college project). Please if anyone has any idea how it can be done, it would be really helpful.
Use the Android N tile API
Custom quick settings can be created in Android N using the tile API. Just make a class that inherits from TileService and add it to the manifest.
Here's the example given in the TileService documentation:
<service
android:name=".MyQSTileService"
android:label="#string/my_default_tile_label"
android:icon="#drawable/my_default_icon_label"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
Recent versions of CyanogenMod 12.1 support this through the CyanogenMod Platform SDK:
public void publishTile() {
if (supportsCustomTiles()) {
Intent receiver = new Intent(context, TileClickedReceiver.class);
PendingIntent clickIntent = PendingIntent.getBroadcast(
context,
0,
receiver,
PendingIntent.FLAG_CANCEL_CURRENT
);
CustomTile tile = new CustomTile.Builder(context)
.setIcon(R.drawable.tile_icon)
.setLabel("Test Tile")
.setOnClickIntent(clickIntent)
.build();
CMStatusBarManager
.getInstance(context)
.publishTile(1234, tile);
}
}
private boolean supportsCustomTiles() {
try {
Class.forName("cyanogenmod.app.CustomTile");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
The quick settings tiles in Android 4.4 are all hardcoded.
Here's a link to the source.
Even with root, the only way to change this would be patching system jars/apks.
The support for Mirror might be added by Cyanogenmod, have you tried if it works on any other ROM?
Edit: Here's a feature request for a quick settings api: https://code.google.com/p/android/issues/detail?id=42616
Koushik Dutta didn't add a new quick settings tile. The "Cast Screen"-Tile is implemented by the android system and appears sometimes. It's a shortcut to the "cast screen"-menu in system settings. Koush added new options for this menu (i don't know if there's an open api or if he needs the root permission for that) and now, the tile is always displayed because there's always content.
To answer your question: No, without system modifications with root, you can't add tiles to the android quick settings. (Edit: I haven't read that you'd also use root. So, you can't add tiles easily and the mirror application by Koushik Dutta doesn't do that, too.)
PS: It isn't because of CyanogenMod, because I use stock android and the app works, too.
Update 2019-08-08: With Android N, there's an official API to add custom quick setting tiles (see Sam's answer).

Conditional compiling in Android?

Is there any kind of conditional compiling for Android?
I had to make my project for Android 3 (API 11) just because ExifInterface has almost no useful attributes in Android 2.3 (API 10), despite the fact that it appeared in API 5 (!!??). I don't want to restrict my app to ICS users.
Thanks!
You can check dynamically the current API version of the device and do different stuff depending on that:
if(Build.VERSION.SDK_INT < 14) {
// Crappy stuff for old devices
}
else {
// Do awesome stuff on ICS
}
But be careful that if you need to instantiate classes that are not available for all APIs then you should do it in a runnable or in a separate wrapper class, e.g:
if(Build.VERSION.SDK_INT < 14) {
// Crappy stuff for old devices
}
else {
// Do awesome stuff on ICS
new Runnable() {
new AmazingClassAvailableOnICS();
(...)
}.run();
}
import android.annotation.TargetApi;
and then use annotations:
#TargetApi(11)
public void methodUsesAPI11()
{
...
Using this trick does a very simple thing: it allows compiling some code which contains API level 11 calls (classes, methods, etc) and still set android:minSdkVersion="8" in the manifest. Nothing more, nothing else.
The rest is up to you. You must check platform version before you call methodUsesAPI11() or you handle exceptions in order to prevent app crash and perform other action on older platforms.
Checking Build.VERSION.SDK_INT or using annotations should suffice, however, this link I'd bookmarked might be relevant to your case:
http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html?m=1
You can use what they describe there to have classes that may not be compatible, but will never be loaded. It's not conditional compilation, but it may be what you need, however, it is a bit more complex.

PreferenceActivity works properly on Android 2.1, but not 4.1 (padded)

I'm writing an application. It needs to run on old android OS's to be useful. I have written the preferences screen using a PreferencesActivity that populates with a options.xml file that contains PreferenceScreen. It has no submenu for preferences (so PreferenceFragment provides no real benefits).
In Android 2.1 (2.2 and 2.3, haven't tested on ICS yet) the screen displays properly like so in landscape:
But on Jellybean, it looks like this:
It looks terrible. I have nothing defined as a layout, just standard addPreferencesFromResource(). Does anyone know what the cause of this might be? Or a solution?
My onCreate looks like this:
protected void onCreate(Bundle savedInstanceState) { //
super.onCreate(savedInstanceState);
Log.i(TAG, "Options Activity Loaded.");
setTitle(getString(R.string.optionsTitle));
addPreferencesFromResource(R.xml.options);
setupListeners();
}
Everything else just makes Preference objects and assigns methods to do stuff when they get clicked. I don't want to make code for both PreferenceFragment and PreferenceActivity. I do not understand how google expects us to use Fragment APIs if the largest version marketshare doesn't have that API and they will not add it to the compatibility lib.
Your application can support both the old and the new functionality for SharedPreferences. You can provide a Class for the old preferences and a Class for the new. Its not much more code. You can make your app backward compatible like this:
Class spc = Build.VERSION_SDK_INT < Build.VERSION_CODES.HONEYCOMB ?
oldPreferenceActivity.class : newFragmentPreferenceActivity.class;
Intent i = new Intent (this, spc);
startActivityForResult (i, SHOW_PREFERENCES);

Strategies for Honeycomb & backward compatibility

So we've seen the preview sdk and the neat new stuff like ActionBar and Fragments. Making a lot of method calls will be unavoidable to make use of these, so what strategies are there for maintaining 1 version of the app, which will let me use all the snazzy new stuff but also work on devices running 2.3 or below? My app targets 1.5 - 2.3 at the moment.
The same fragment APIs are now available as a static library for use with older versions of Android; it's compatible right back to Android 1.6.
There are a few tricks you can use to see if the various new APIs are available to your app. Generally speaking, you'll probably want to create two alternative sets of Activities, one that uses the fancy new APIs (ActionBar, Animators, etc.) -- and another set that don't.
The following code shows how you can use reflection and exception catching to determine the availability of the Fragment APIs, and version checking to confirm if the other Honeycomb APIs are available.
private static boolean shinyNewAPIsSupported = android.os.Build.VERSION.SDK_INT > 10;
private static boolean fragmentsSupported = false;
private static void checkFragmentsSupported() throws NoClassDefFoundError {
fragmentsSupported = android.app.Fragment.class != null;
}
static {
try {
checkFragmentsSupported();
} catch (NoClassDefFoundError e) {
fragmentsSupported = false;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent startActivityIntent = null;
if (!shinyNewAPIsSupported)
startActivityIntent = new Intent(this, MainNonActionBarActivity.class);
else
startActivityIntent = new Intent(this, MainActionActivity.class);
startActivity(startActivityIntent);
finish();
}
Generally speaking you can use the same layout definitions. Where Fragments are available you'll inflate each layout within a different Fragment, where they aren't you'll probably want to use <include> tags to embed several of them into a more complex Activity layout.
A more detailed work through of how to write the code to support backwards compatibility on Honeycomb can be found here: http://blog.radioactiveyak.com/2011/02/strategies-for-honeycomb-and-backwards.html
Conveniently, Google's Dianne Hackborne has posted a blog entry covering this exact topic. Google say they'll be providing static libraries so older versions of Android will also be able to use fragments.
You might find Reto Meier's article on backwards-compatibility useful, specifically the section headed "Dealing with missing classes".
I've yet to look at the Honeycomb SDK myself but I, like you, am hoping it's pretty easy and hassle-free to make use the new features without jeopardising compatibility with older devices.
Well google just announced honeycomb will be tablet only: http://www.pcmag.com/article2/0,2817,2379271,00.asp
So if your device is meant for mobile only this may not even be an issue.
Official Android sample that will help you achieve ActionBar from 1.6 to 4.x

Categories

Resources