How to override/ modify a value or method from the sdk? - android

I would like to modify the value of a int in the Notification.class in the SDK. Is this possible? Can this be achieved ?
This is the int I'd like to modify, override:
public class Notification implements Parcelable {
.......
/**
* Maximum length of CharSequences accepted by Builder and friends.
*
* <p>
* Avoids spamming the system with overly large strings such as full e-mails.
*/
private static final int MAX_CHARSEQUENCE_LENGTH = 10 * 1024;
/**
...
or alternatively, I'd like to override this method from the same class:
/**
* Make sure this CharSequence is safe to put into a bundle, which basically
* means it had better not be some custom Parcelable implementation.
* #hide
*/
public static CharSequence safeCharSequence(CharSequence cs) {
if (cs == null) return cs;
if (cs.length() > MAX_CHARSEQUENCE_LENGTH) {
cs = cs.subSequence(0, MAX_CHARSEQUENCE_LENGTH);
}
if (cs instanceof Parcelable) {
Log.e(TAG, "warning: " + cs.getClass().getCanonicalName()
+ " instance is a custom Parcelable and not allowed in Notification");
return cs.toString();
}
return removeTextSizeSpans(cs);
}

Is this possible?
In your own custom ROM? Yes.
In an Android app? No. More accurately, you have no means of affecting safeCharSequence() from your app, except perhaps on a rooted device.

Related

Mockito - Set default return string value for all mocked methods

I have a class that has over 20 methods that return string values. These strings are not relevant for my test, but it's pretty time consuming to set a when->thenReturn case for each of the functions, specially because there are several of these classes.
Is there a way to tell mockito to default empty string instead of null, or any string value that I wish for that matter?
I created a class to perform this on your project whenever needed, simply init the mock (usually in #Before function)
myClassMock = mock(MyClass::class.java, NonNullStringAnswer())
NonNullStringAnswer.kt
/** Used to return a non-null string for class mocks.
*
* When the method called in the Mock will return a String, it will return the name of the
* method instead of null.
*
* For all other methods the default mocking value will be returned.
*
* If you want to mock additional methods, it is recommended to use doReturn().when instead on
* when().thenReturn
*
* Example of usage:
*
* myClassMock = mock(MyClass::class.java, NonNullStringAnswer())
*
**/
class NonNullStringAnswer : Answer<Any> {
#Throws(Throwable::class)
override fun answer(invocation: InvocationOnMock): Any {
return if (invocation.method.returnType == String::class.java) {
invocation.toString()
} else {
Mockito.RETURNS_DEFAULTS.answer(invocation)
}
}
}

How to keep certain part of my app common in entire application

I want to have a list of certain important things(which I am fetching from server every 15 seconds) which I want to have constant(or common) in my entire application. So when I move to next activity by Intents(or any other methods) I should have the list all the time. Is it possible in android ??
I want different solutions which requires as less work as possible.
Please Help..
EDIT: I think I havent made myself clear. I am not worried about how to store data..I am asking as to how can I achieve a view in which only half of the screen changes(as we move from activity to activity) while other half remains constant(doesnt move). Can it be possible ??
Your application class instance is always accesible from any activity.
All you need to do is create the application class like this:
public class YourApp extends Application {
....
}
And then modify the following line in your app AndroidManifest.xml :
<application
android:name="your.package.YourApp"
Now you can access this class everywhere:
YourApp appInstance = (YourApp)getApplication();
Use the PreferencesManager like the one below, create your POJO to access the PreferencesManager.
// TODO: Auto-generated Javadoc
/**
* The Class PreferenceManager.
*/
public class PreferenceManager {
/** The Constant TAG. */
private static final String TAG = PreferenceManager.class.getSimpleName();
/** The default shared preferences. */
private static SharedPreferences defaultSharedPreferences = null;
/**
* Inits the.
*
* #param context the context
*/
public static final void init(Context context){
defaultSharedPreferences = android.preference.PreferenceManager.getDefaultSharedPreferences(context);
log("Initialize PreferenceManager!");
UserSettings.init(context);
}
/**
* Save.
*
* #param name the name
* #param value the value
*/
static final void save(String name,String value){
if( value != null ){
Editor edit = defaultSharedPreferences.edit();
edit.remove(name);
edit.putString(name, value);
edit.commit();
}else{
Editor edit = defaultSharedPreferences.edit();
edit.remove(name);
edit.commit();
}
}
/**
* Gets the.
*
* #param name the name
* #param defaultValue the default value
* #return the string
*/
public static final String get(String name,String defaultValue){
return defaultSharedPreferences.getString(name, defaultValue);
}
/**
* Save state.
*
* #param name the name
* #param state the state
*/
public static final void saveState(String name,Bundle state){
if( state != null && state.size() > 0 ){
Parcel parcel = Parcel.obtain();
parcel.writeBundle(state);
String encodeToString = Base64.encodeToString(parcel.marshall(), Base64.DEFAULT);
PreferenceManager.save(name, encodeToString);
}else{
PreferenceManager.save(name, null);
}
log("Saved state "+name);
}
/**
* Gets the state.
*
* #param name the name
* #return the state
*/
public static final Bundle getState(String name){
log("Get state "+name);
String encryptedValue = "";
try {
encryptedValue = PreferenceManager.get(name, "");
} catch (NullPointerException e) {
return new Bundle();
}
if( "".equals(encryptedValue) ){
return new Bundle();
}else{
byte[] decode = Base64.decode(encryptedValue, Base64.DEFAULT);
Parcel parcel = Parcel.obtain();
parcel.unmarshall(decode, 0, decode.length);
parcel.setDataPosition(0);
return parcel.readBundle();
}
}
/**
* Log.
*
* #param msg the msg
*/
private static final void log(String msg){
Log.d(TAG, msg);
}
}
/**
* The Class Settings.
*/
public class UserSettings {
/** The settings bundle. */
private final Bundle settingsBundle = new Bundle(1);
/**
* Save.
*/
public final void save() {
PreferenceManager.saveState(SETTINGS_STATE_NAME, settingsBundle);
}
/**
* Restore.
*/
final public void restore() {
settingsBundle.clear();
Bundle state = PreferenceManager.getState(SETTINGS_STATE_NAME);
if (state.size() == 0) {
settingsBundle.putAll(getDefaultValuesSettings());
} else {
settingsBundle.putAll(state);
}
}
final void reset() {
settingsBundle.clear();
}
/**
* Gets the settings.
*
* #return the settings
*/
public static UserSettings getSettings() {
return settings;
}
/**
* Inits the.
*
* #param ctx the ctx
*/
public static final void init(Context ctx) {
settings.restore();
setDeviceUniqueId(ctx, settings);
}
}
Example usage:
public class YourApplication extends Application {
....
onCreate(){
....
PreferenceManager.init(getBaseContext());
}
}
Where you need your data to be stored and retrieved use the methods like below.
UserSettings.getSettings().setUser(responseVal);
UserSettings.getSettings().save();
String response = UserSettings.getSettings().getUser();
If it's large amount of data, you can store your data using Shared Preferences or SQLite DB. If it is less amount of data then you can go for static variables. If you use static variables, when any crash occurs in the app that data may lost. Hence static variables usage is less preferable.
There are lot of ways to do this :
You can store them and put in your application's SQLite database (Data is Persistent till you delete the application or delete through your application code )
See the SQLite usage here
You use Cache them in the phone memory till the time your app runs.
See Cache usage here here
You can use SQLite database to store this data and then create singleton helper to read it.
Or you can use save your data in XML or JSON format as files, then parse them to read.
Or you can create class-container for one entity of your data, make it serializable and store in SharedPreferences as ArrayList<YourDataContainer>

Android Get the next or previous Enum

I need a way to get the next/previous enum.
My problem is that I cannot iterate the normal way:
for( Mode m: Mode.values() ) {
. . .
}
I need to get the next enum inside a method, each time it is called:
Note that Mode is a system Enum, therefore I cannot define methods, unless I create my own Enum, which is a solution, but a less preferred one.
public class A {
private Mode m;
A() {
m = Mode.CLEAR;
}
...
protected onClick(View v) {
...
v.getBackground().SetColorFilter(R.color.azure, m);
m = m.next(); // <-- I need something like this
...
}
//Store these somewhere in your class
Mode[] modes = Mode.values();
int modeCount = modes.length;
protected void onClick(View v) {
//Get the next mode, wrapping around if you reach the end
int nextModeOrdinal = (m.ordinal() + 1) % modeCount;
m = modes[nextModeOrdinal];
}
For Kotlin, you can declare an extension function on all enum types that would allow you to define a next() function on all enum instances:
/**
* Returns the next enum value as declared in the class. If this is the last enum declared,
this will wrap around to return the first declared enum.
*
* #param values an optional array of enum values to be used; this can be used in order to
* cache access to the values() array of the enum type and reduce allocations if this is
* called frequently.
*/
inline fun <reified T : Enum<T>> Enum<T>.next(values: Array<T> = enumValues()) =
values[(ordinal + 1) % values.size]
Then you can have something like:
enum class MyEnum {
ONE, TWO, THREE
}
Then you can just use val two = MyEnum.ONE.next()
Implement this method:
public static Mode nextMode(Mode mode) {
return (mode.ordinal() < Mode.values().length - 1) ? Mode.values()[mode.ordinal() + 1] : null;
}

How to prevent Multiple Toast Overlaps

I've been using a common "myToast" which I use "myToast.cancel() prior to issuing a new toast. For Android v2.3 and older, this works great. When a new toast needs to be sent, the old one, if still on-screen, is canceled (and disappears immediately) to be replaced with the new toast. This avoids stacking up a bunch of toasts if the user presses a key multiple times that needs the alert (and other conditions). My actual case is one toast appears when a wrong key is pressed, and another appears if the Clear key is not pressed.
For Android 4.0 and 4.1, issuing a myToast.cancel() before the next toast kills both the current and the next toast. The current cancel() API does indicate it cancels the current AND the next toast (which seems rather stupid). Why cancel a toast you want to put up?
Any ideas on making cancel work consistently across Android versions (and the way it works in v2.3 and older)?
I'll try some inelegant dual toast system with tracking for which toast is in use, but it seems such a pain work around this bad behavior in 4.x to get what works perfectly and logically in older Android versions.
Ok, I solved it, but it's not nearly as clean as I would have liked. I implemented a dual toast approach, where it alternates between two toasts. First we define the toasts for the activity prior to the OnCreate:
Toast toast0;
Toast toast1;
private static boolean lastToast0 = true;
In the OnCreate:
toast0 = new Toast(getApplicationContext());
toast0.cancel();
toast1 = new Toast(getApplicationContext());
toast1.cancel();
And finally, when I need to display the toast and cancel the prior toast at the same time I use something similar to:
if (lastToast0) {
toast0.cancel();
toast1.setDuration(Toast.LENGTH_LONG);
toast1.setText("new message");
toast1.show();
lastToast0 = false;
} else {
toast1.cancel();
toast0.setDuration(Toast.LENGTH_LONG);
toast0.setText("new message");
toast0.show();
lastToast0 = true;
}
If you need to just cancel an existing toast (before it times out) use:
toast0.cancel();
toast1.cancel();
Tested on Nexus 7 (4.1), Emulator 4.0, and several devices with Android 2.2, 2.3.
Instead of calling cancel(). Try resetting the text and call show(). This should cancel the last toast by itself
myToast.setText("wrong key")
myToast.show();
If you keep using the same myToast instead of creating one every time I guess they won't stack up.
Did nandeesh's solution not work for you?
His solution would be cleaner than using two different toasts.
For example, (expanding on his/her answer) prior to onCreate we'd declare the toast:
private Toast myToast;
and in onCreate we'd have to initialize it using makeToast (otherwise we'd get an error):
myToast = Toast.makeText(getApplicationContext(), null, Toast.LENGTH_SHORT);
and whenever we want a toast to be shown we'd simply call:
myToast.setText("some text");
myToast.show();
and this would replace the previous toast properly.
Here is my answer copied from another similar question here:
Android cancel Toast when exiting the app and when toast is being shown
The Boast class accomplishes exactly what you need.
The trick is to keep track of the last Toast that was shown, and to cancel that one.
What I have done is to create a Toast wrapper, that contains a static reference to the last Toast displayed.
When I need to show a new one, I first cancel the static reference, before showing the new one (and saving it in the static).
Here's full code of the Boast wrapper I made - it mimics enough of the Toast methods for me to use it. By default the Boast will cancel the previous one, so you don't build up a queue of Toasts waiting to be displayed.
If you just want to know how to cancel the notifications when exiting your app, you will find lots of help in there.
package mobi.glowworm.lib.ui.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.Nullable;
import android.widget.Toast;
import java.lang.ref.WeakReference;
/**
* {#link Toast} decorator allowing for easy cancellation of notifications. Use this class if you
* want subsequent Toast notifications to overwrite current ones. </p>
* <p/>
* By default, a current {#link Boast} notification will be cancelled by a subsequent notification.
* This default behaviour can be changed by calling certain methods like {#link #show(boolean)}.
*/
public class Boast {
/**
* Keeps track of certain Boast notifications that may need to be cancelled. This functionality
* is only offered by some of the methods in this class.
* <p>
* Uses a {#link WeakReference} to avoid leaking the activity context used to show the original {#link Toast}.
*/
#Nullable
private volatile static WeakReference<Boast> weakBoast = null;
#Nullable
private static Boast getGlobalBoast() {
if (weakBoast == null) {
return null;
}
return weakBoast.get();
}
private static void setGlobalBoast(#Nullable Boast globalBoast) {
Boast.weakBoast = new WeakReference<>(globalBoast);
}
// ////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Internal reference to the {#link Toast} object that will be displayed.
*/
private Toast internalToast;
// ////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Private constructor creates a new {#link Boast} from a given {#link Toast}.
*
* #throws NullPointerException if the parameter is <code>null</code>.
*/
private Boast(Toast toast) {
// null check
if (toast == null) {
throw new NullPointerException("Boast.Boast(Toast) requires a non-null parameter.");
}
internalToast = toast;
}
// ////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Make a standard {#link Boast} that just contains a text view.
*
* #param context The context to use. Usually your {#link android.app.Application} or
* {#link android.app.Activity} object.
* #param text The text to show. Can be formatted text.
* #param duration How long to display the message. Either {#link Toast#LENGTH_SHORT} or
* {#link Toast#LENGTH_LONG}
*/
#SuppressLint("ShowToast")
public static Boast makeText(Context context, CharSequence text, int duration) {
return new Boast(Toast.makeText(context, text, duration));
}
/**
* Make a standard {#link Boast} that just contains a text view with the text from a resource.
*
* #param context The context to use. Usually your {#link android.app.Application} or
* {#link android.app.Activity} object.
* #param resId The resource id of the string resource to use. Can be formatted text.
* #param duration How long to display the message. Either {#link Toast#LENGTH_SHORT} or
* {#link Toast#LENGTH_LONG}
* #throws Resources.NotFoundException if the resource can't be found.
*/
#SuppressLint("ShowToast")
public static Boast makeText(Context context, int resId, int duration)
throws Resources.NotFoundException {
return new Boast(Toast.makeText(context, resId, duration));
}
/**
* Make a standard {#link Boast} that just contains a text view. Duration defaults to
* {#link Toast#LENGTH_SHORT}.
*
* #param context The context to use. Usually your {#link android.app.Application} or
* {#link android.app.Activity} object.
* #param text The text to show. Can be formatted text.
*/
#SuppressLint("ShowToast")
public static Boast makeText(Context context, CharSequence text) {
return new Boast(Toast.makeText(context, text, Toast.LENGTH_SHORT));
}
/**
* Make a standard {#link Boast} that just contains a text view with the text from a resource.
* Duration defaults to {#link Toast#LENGTH_SHORT}.
*
* #param context The context to use. Usually your {#link android.app.Application} or
* {#link android.app.Activity} object.
* #param resId The resource id of the string resource to use. Can be formatted text.
* #throws Resources.NotFoundException if the resource can't be found.
*/
#SuppressLint("ShowToast")
public static Boast makeText(Context context, int resId) throws Resources.NotFoundException {
return new Boast(Toast.makeText(context, resId, Toast.LENGTH_SHORT));
}
// ////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Show a standard {#link Boast} that just contains a text view.
*
* #param context The context to use. Usually your {#link android.app.Application} or
* {#link android.app.Activity} object.
* #param text The text to show. Can be formatted text.
* #param duration How long to display the message. Either {#link Toast#LENGTH_SHORT} or
* {#link Toast#LENGTH_LONG}
*/
public static void showText(Context context, CharSequence text, int duration) {
Boast.makeText(context, text, duration).show();
}
/**
* Show a standard {#link Boast} that just contains a text view with the text from a resource.
*
* #param context The context to use. Usually your {#link android.app.Application} or
* {#link android.app.Activity} object.
* #param resId The resource id of the string resource to use. Can be formatted text.
* #param duration How long to display the message. Either {#link Toast#LENGTH_SHORT} or
* {#link Toast#LENGTH_LONG}
* #throws Resources.NotFoundException if the resource can't be found.
*/
public static void showText(Context context, int resId, int duration)
throws Resources.NotFoundException {
Boast.makeText(context, resId, duration).show();
}
/**
* Show a standard {#link Boast} that just contains a text view. Duration defaults to
* {#link Toast#LENGTH_SHORT}.
*
* #param context The context to use. Usually your {#link android.app.Application} or
* {#link android.app.Activity} object.
* #param text The text to show. Can be formatted text.
*/
public static void showText(Context context, CharSequence text) {
Boast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
/**
* Show a standard {#link Boast} that just contains a text view with the text from a resource.
* Duration defaults to {#link Toast#LENGTH_SHORT}.
*
* #param context The context to use. Usually your {#link android.app.Application} or
* {#link android.app.Activity} object.
* #param resId The resource id of the string resource to use. Can be formatted text.
* #throws Resources.NotFoundException if the resource can't be found.
*/
public static void showText(Context context, int resId) throws Resources.NotFoundException {
Boast.makeText(context, resId, Toast.LENGTH_SHORT).show();
}
// ////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Close the view if it's showing, or don't show it if it isn't showing yet. You do not normally
* have to call this. Normally view will disappear on its own after the appropriate duration.
*/
public void cancel() {
internalToast.cancel();
}
/**
* Show the view for the specified duration. By default, this method cancels any current
* notification to immediately display the new one. For conventional {#link Toast#show()}
* queueing behaviour, use method {#link #show(boolean)}.
*
* #see #show(boolean)
*/
public void show() {
show(true);
}
/**
* Show the view for the specified duration. This method can be used to cancel the current
* notification, or to queue up notifications.
*
* #param cancelCurrent <code>true</code> to cancel any current notification and replace it with this new
* one
* #see #show()
*/
public void show(boolean cancelCurrent) {
// cancel current
if (cancelCurrent) {
final Boast cachedGlobalBoast = getGlobalBoast();
if ((cachedGlobalBoast != null)) {
cachedGlobalBoast.cancel();
}
}
// save an instance of this current notification
setGlobalBoast(this);
internalToast.show();
}
}
Make a java class as ShowToast.java like below
public class ShowToast {
private static Toast toast;
public static void show(Context mcontext, String text) {
if (toast != null)
toast.cancel();
toast = Toast.makeText(mcontext, text, Toast.LENGTH_SHORT);
toast.show();
}
}
Then call it as
ShowToast.show(getApplicationContext(),"YOUR_TOAST_TEXT");
cancel() doesn't do anything I'm afraid.
I would suggest using Crouton https://github.com/keyboardsurfer/Crouton
This my solution works perfect both for 4.* and 2.3 Android versions
static Toast toast;
.....
if (toast != null)
toast.cancel();
boolean condition = Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB;
if ((toast == null && condition) || !condition)
toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
if ((toast != null && condition))
toast.setText(text);
toast.show();
Create an Toast Object:
Toast toastobject=null;
Now use the below code to display the toast. This will work find for me
int index = clickCounter-1;
if(toastobject!= null)
{
toastobject.cancel();
}
toastobject = Toast.makeText(this,"Toast Text" , Toast.LENGTH_SHORT);
listItems.remove(index);
toastobject.show();
create new function and call this.
ImageButton ABtn = (ImageButton) findViewById(R.id.Btn);
ABtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
SETToast("mytext");
}
});
private Toast toast = null;
public void SETToast( String text)
{
if(toast==null)
{
toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
toast.show();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toast=null;
}
}, 2000);
}
else
{
toast.setText(text);
}
}
Kotlin approach:
class MyActivity: Activity {
private var toast: Toast? = null
fun yourFunction() {
toast?.cancel()
toast = if(documentWasSaved) {
makeText(this, "Document was saved"), Toast.LENGTH_LONG)
} else {
makeText(this, "Failed to save your document", Toast.LENGTH_LONG)
}
toast?.show()
}
}

What does "Hidden constructor called more than once per process" mean?

In my LogCat while debugging my app, I often get:
E/TelephonyManager(5382): Hidden constructor called more than once per process!
I've been Googling around a bit, and while I noticed other mentions of the error (in other logs), I cannot identify what it means.
So what is this error? Why am I getting it? And what is its significance?
This is from the Android source code:
/**
* Provides access to information about the telephony services on
* the device. Applications can use the methods in this class to
* determine telephony services and states, as well as to access some
* types of subscriber information. Applications can also register
* a listener to receive notification of telephony state changes.
*
* You do not instantiate this class directly; instead, you retrieve
* a reference to an instance through
* {#link android.content.Context#getSystemService
* Context.getSystemService(Context.TELEPHONY_SERVICE)}.
*
* Note that access to some telephony information is
* permission-protected. Your application cannot access the protected
* information unless it has the appropriate permissions declared in
* its manifest file. Where permissions apply, they are noted in the
* the methods through which you access the protected information.
*/
public class TelephonyManager {
private static final String TAG = "TelephonyManager";
private static Context sContext;
private static ITelephonyRegistry sRegistry;
/** #hide */
public TelephonyManager(Context context) {
context = context.getApplicationContext();
if (sContext == null) {
sContext = context;
sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
} else if (sContext != context) {
Log.e(TAG, "Hidden constructor called more than once per process!");
Log.e(TAG, "Original: " + sContext.getPackageName() + ", new: " +
context.getPackageName());
}
}
The TelephonyManager seems to put the "Hidden constructor called more than once per process!" into the Log when your application calls the constructor more than once, as the message suggests. The constructor is called using the getSystemService as per the comments on the constructor.
Do you have more than one instance of:
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
or something similar in your code? This could possibly be causing the error.
EDIT: If it's not your code causing the message then it's the program running with PID 5382 I think.

Categories

Resources