Categories
discuss

mockito return value based on property of a parameter

Normally when using mockito I will do something like

Mockito.when(myObject.myFunction(myParameter)).thenReturn(myResult);

Is it possible to do something along the lines of

myParameter.setProperty("value");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("myResult");

myParameter.setProperty("otherValue");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("otherResult");

So rather than when just using the parameter to determine the result. It is using a value of a property inside the parameter to determine the result.

so when the code is executed it behaves like so

public void myTestMethod(MyParameter myParameter,MyObject myObject){
    myParameter.setProperty("value");
    System.out.println(myObject.myFunction(myParameter));// outputs myResult

    myParameter.setProperty("otherValue");
    System.out.println(myObject.myFunction(myParameter));// outputs otherResult
}

current solution, hopefully something better can be suggested.

private class MyObjectMatcher extends ArgumentMatcher<MyObject> {

    private final String compareValue;

    public ApplicationContextMatcher(String compareValue) {
        this.compareValue= compareValue;
    }

    @Override
    public boolean matches(Object argument) {
        MyObject item= (MyObject) argument;
        if(compareValue!= null){
            if (item != null) {
                return compareValue.equals(item.getMyParameter());
            }
        }else {
            return item == null || item.getMyParameter() == null;
        }
        return false;
    }
}

public void initMock(MyObject myObject){
    MyObjectMatcher valueMatcher = new MyObjectMatcher("value");
    MyObjectMatcher otherValueMatcher = new MyObjectMatcher("otherValue");
    Mockito.when(myObject.myFunction(Matchers.argThat(valueMatcher))).thenReturn("myResult");
    Mockito.when(myObject.myFunction(Matchers.argThat(otherValueMatcher))).thenReturn("otherResult");
}

Answer

Here’s one way of doing it. This uses an Answer object to check the value of the property.

@RunWith(MockitoJUnitRunner.class)
public class MyTestClass {
    private String theProperty;
    @Mock private MyClass mockObject;

    @Before
    public void setUp() {
        when(mockObject.myMethod(anyString())).thenAnswer(
            new Answer<String>(){
            @Override
            public String answer(InvocationOnMock invocation){
                if ("value".equals(theProperty)){
                    return "result";
                }
                else if("otherValue".equals(theProperty)) {
                    return "otherResult";
                }
                return theProperty;
            }});
    }
}

There’s an alternative syntax, which I actually prefer, which will achieve exactly the same thing. Over to you which one of these you choose. This is just the setUp method – the rest of the test class should be the same as above.

@Before
public void setUp() {
    doAnswer(new Answer<String>(){
        @Override
        public String answer(InvocationOnMock invocation){
            if ("value".equals(theProperty)){
                return "result";
            }
            else if("otherValue".equals(theProperty)) {
                return "otherResult";
            }
            return theProperty;
        }}).when(mockObject).myMethod(anyString());
}
Categories
discuss

Isotope appending doesn’t seem to work

I have a photo gallery powered by Isotope.
Images are requested from external resource on page load and every time a user scrolls to the bottom of the page. New images are to be appended to the current isotope layout. The problem is with Isotope – it doesn’t seem to execute the ‘appended’ method.

Searching for a solution on StackExchange and Google revealed I am not the only one having this problem. I have been tinkering with this for past couple of days and tried almost every solution I could find but so far I have not found anything that could fix my problem.

CodePen: I have created a CodePen here – http://codepen.io/Writech/pen/pBoEt
WebPage: As the custom event ‘resizestop’ is not working in codepen the same code is found as a webpage here – http://writech.net.ee/sandbox/

To see the problem open the CodePen or WebPage provided above and scroll to the bottom of the page which initiates loading of additional images. Then you see the new images are just appended to the container by jQuery. But they are not appended to the isotope layout instance as they are supposed to.

The problematic part lays in a custom function named isotopeAppend(). This function is called on page load and then the second part of ‘if-else’ statement is executed. When initialization is done and first images are added to the container then the next time isotopeAppend() is called (it’s when user reaches to the bottom of the page) the first part of ‘if-else’ statement is executed and this is where the problematic Isotope ‘appended’ method is called.

A code snippet below from problematic javascript code. The results of the ajax request to external resource are applied to the variable newElems. When adding an alert(‘something’) or console.log inside the ‘appended’ callback – nothing happens.

Does the problem lay in Isotope itself or does it have anything to do with my coding error? I would really like to find a solution for this!

var elements = $(newElems).css({ opacity: 1, 'width' : columnWidthVar + 'px' });
$('#photos_section_container').append( elements );

$('#photos_section_container').imagesLoaded(function(){

    $('#photos_section_container').isotope( 'appended', elements, function(){
        hideLoader(function(){
            elements.animate({ opacity: 1 }); 
        });
    }); 

});

Answer

In the initialization change

itemSelector : $('.photos_section_wrap'),

to

itemSelector : '.photos_section_wrap',

I forked your pen.

itemSelector is used by isotope to filter elements to layout and $() returns array of objects. In result there no elements to layout. If you are interested you may look at the _getAtoms method (isotope script) in debug to see what’s goinig on.

Categories
discuss

Monitor All Android Devices events remotely

In Android, I can monitor if certain events are triggered through the use of Broadcast Receivers. Are there any tools which let me view ALL events on an android device I am debugging instead of having to add a broadcast receiver to listen to them?

For example, in a Broadcast receiver, I can monitor for a call forwarding event. Is there a way to debug such events outside of having to write additional Android code? My goal is to test that certain events are triggered after UI state changes, and I am not seeing anything obvious in Logcat that communicates which events are being fired.

For example,

with call forwarding I only see cases like below in Logcat.

START u0 {act=android.intent.action.MAIN cmp=com.android.phone/.GsmUmtsCallForwardOptions}

Answer

The machine where you run an Android remotely can be any system supported by the Android SDK: Windows, Mac OS X, or Linux. The socket connections is forward from a specified local port to a specified remote port on the device instance.

It is recommended that this machine is on the same network as your development PC, for performance and configuration reasons, but it is also possible to use any remotely located machine if firewalls and routing are configured correctly. You have to follow specified steps that provide you with the necessary settings in your environment configuration that will allow you to have remote debugging.

Alternatively you can also consider using Google chrome remote debugging for Android. The jsHybugger can also offers you a similar tool that will equally allow Android remote debugging.

Indeed you can choose the approach that suits you better.

Otherwise, if what you meant is to listen to event in some application, then this has to be done by yourself by hand, including it to the respective app you want to listen for every single event. Further details on this direction you find here:

As you can see, Android has a lot of capabilities, but everything come at some cost – i.e. you have to code it. Otherwise, something that could be done according to your suggestion would be kind of an App or an API that would monitor every single event from all Apps currently in your mobile. But if this is what you really want, then in my view such approach would be cumbersome and overload your mobile.

Categories
discuss

Text (font) looks faded on older apis

I am using a custom typeface, and it displays perfectly on newer android versions(tested on API 17(Asus tab), 18(Dell tab), 19(Nex4) – devices). However, the same typeface looks faded (possibly distorted?) on older versions – API 8(SE X10i), 10(LG P500H).

Here’s a comparison, in case my explanation doesn’t make sense:

On nex4:

enter image description here

On x10i:

enter image description here

I am using a custom typeface with Typeface.BOLD:

tvTitle.setTypeface(titleAndBodyFont, Typeface.BOLD);

And the body (“Looks *” part):

tvBody.setTypeface(titleAndBodyFont);

XML declaration for title:

<TextView
    android:id="@+id/tvTitle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="@dimen/margin_title_side"
    android:layout_marginRight="@dimen/margin_title_side"
    android:layout_marginTop="@dimen/margin_title_top"
    android:ellipsize="end"
    android:maxLines="1"
    android:textColor="@color/constant_color"
    android:textSize="@dimen/text_size_title" />

tvBody is declared in a similar fashion.

Is this a known bug? If so, could someone help me find the bug report? It would help knowing what version this was fixed in. If not, I would be grateful for a solution.

Thanks everyone.

Answer

I always use 2 fonts, 1 normal and 1 bold. So when you need to go bold, just change your font. Never had problems, you can also create your custom textviewplus.

Something like this:

/res/values/attrs.xml

<resources>   
<attr name="fontFamily" format="enum">
    <enum name="helvetica" value="0"/>
    <enum name="helvetica_bold" value="1"/>
</attr>

your TextViewPlus:

public class TextViewPlus extends TextView{

private static final String TAG = "TextViewPlus";

public TextViewPlus(Context context) {
    super(context);
}

public TextViewPlus(Context context, AttributeSet attrs) {
    super(context, attrs);
    setCustomFont(context, attrs);
}

public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    setCustomFont(context, attrs);
}

private void setCustomFont(Context ctx, AttributeSet attrs) {
    TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
    int customFont = a.getInt(R.styleable.TextViewPlus_fontFamily, -1);
    setCustomFont(ctx, customFont);
    a.recycle();
}

public boolean setCustomFont(Context ctx, int font) {
    Typeface tf = null;
    try {
    tf = Typefaces.get(ctx, font);  
    } catch (Exception e) {
        Log.e(TAG, "Could not get typeface: "+e.getMessage());
        return false;
    }

    setTypeface(tf);  
    return true;
}

public boolean setCustomFont(Context ctx, String asset) {
    Typeface tf = null;
    try {
    tf = Typefaces.get(ctx, asset);  
    } catch (Exception e) {
        Log.e(TAG, "Could not get typeface: "+e.getMessage());
        return false;
    }

    setTypeface(tf);
    return true;
}

}

How to use:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.myapp"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
        <com.myapp.viewhelpers.TextViewPlus 
        app:fontFamily="helvetica"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:fontFamily="helvetica"
        android:text="helo world"/>

Categories
discuss

Use a custom contextual action bar for WebView text selection

I have used this guide from Google and this tutorial to produce my own contextual action bar.

private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

    // Called when the action mode is created; startActionMode() was called
    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate a menu resource providing context menu items
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.annotation_menu, menu);
        return true;
    }

    // Called each time the action mode is shown.
    // Always called after onCreateActionMode, but
    // may be called multiple times if the mode is invalidated.
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false; // Return false if nothing is done
    }

    // Called when the user selects a contextual menu item
    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.custom_button:
                // do some stuff
                break;
            case R.id.custom_button2:
                // do some other stuff
                break;
            default:
                // This essentially acts as a catch statement
                // If none of the other cases are true, return false
                // because the action was not handled
                return false;
        }
        finish(); // An action was handled, so close the CAB
        return true;
    }

    // Called when the user exits the action mode
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mActionMode = null;
    }
};

This menu is designed to appear when the user selects text, so it overrides the native copy/paste menu. Now I get to my issue.

Because I am overriding functions for text selection, I also added a LongClickListener to a WebView and implemented the onLongClick(View v) method so I can detect when users make the selection.

    myWebView.setOnLongClickListener(new View.OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            if (mActionMode != null) {
                return false;
            }

            mActionMode = startActionMode(mActionModeCallback);
            v.setSelected(true);
            return true;
        }
    });

When I long click, I see my custom menu appear, but no text is highlighted.
I need to have the text selection functionality; without it, my menu is pointless.

How do I override onLongClick(View v), but maintain the text selection provided by Android?
If that is not possible, can I make the call to startActionMode(mActionModeCallback) somewhere else so that text will be selected as normal, but my custom menu will also appear?
If neither of those are possible… help.

Answer

THERE IS AN EASIER WAY! See update below 😀


For the sake of completeness, here is how I fixed the problem:

I followed the suggestion according to this answer, with a little more tweaking to more closely match the overridden code:

public class MyWebView extends WebView {

    private ActionMode mActionMode;
    private mActionMode.Callback mActionModeCallback;

    @Override
    public ActionMode startActionMode(Callback callback) {
        ViewParent parent = getParent();
        if (parent == null) {
            return null;
        }
        mActionModeCallback = new CustomActionModeCallback();
        return parent.startActionModeForChild(this, mActionModeCallback);
    }
}

Essentially, this forces your customized CAB to appear instead of the Android CAB. Now you have to modify your callback so that the text highlight will go away along with the CAB:

public class MyWebView extends WebView {
    ...
    private class CustomActionModeCallback implements ActionMode.Callback {
        ...
        // Everything up to this point is the same as in the question

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            clearFocus(); // This is the new code to remove the text highlight
             mActionMode = null;
        }
    }
}

That’s all there is to it. Be aware that as long as you are using MyWebView with the overridden startActionMode there is NO WAY to get the native CAB (the copy/paste menu, in the case of a WebView). It may be possible to implement that sort of behavior, but that is not the way this code works.


UPDATE: There is a much easier way to do this! The above solution works well, but here is an alternative, easier way.

This solution provides less control over the ActionMode, but it requires far less code than the above solution.

public class MyActivity extends Activity {

    private ActionMode mActionMode = null;

    @Override
    public void onActionModeStarted(ActionMode mode) {
        if (mActionMode == null) {
            mActionMode = mode;
            Menu menu = mode.getMenu();
            // Remove the default menu items (select all, copy, paste, search)
            menu.clear();

            // If you want to keep any of the defaults,
            // remove the items you don't want individually:
            // menu.removeItem(android.R.id.[id_of_item_to_remove])

            // Inflate your own menu items
            mode.getMenuInflater().inflate(R.menu.my_custom_menu, menu);
        }

        super.onActionModeStarted(mode);
    }

    // This method is what you should set as your item's onClick
    // <item android:onClick="onContextualMenuItemClicked" />
    public void onContextualMenuItemClicked(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.example_item_1:
                // do some stuff
                break;
            case R.id.example_item_2:
                // do some different stuff
                break;
            default:
                // ...
                break;
        }

        // This will likely always be true, but check it anyway, just in case
        if (mActionMode != null) {
            mActionMode.finish();
        }
    }

    @Override
    public void onActionModeFinished(ActionMode mode) {
        mActionMode = null;
        super.onActionModeFinished(mode);
    }
}

Here is an example Menu to get you started:

<!-- my_custom_menu.xml -->
<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/example_item_1"
        android:icon="@drawable/ic_menu_example_1"
        android:showAsAction="always"
        android:onClick="onContextualMenuItemClicked"
        android:title="@string/example_1">
    </item>

    <item
        android:id="@+id/example_item_2"
        android:icon="@drawable/ic_menu_example_2"
        android:showAsAction="ifRoom"
        android:onClick="onContextualMenuItemClicked"
        android:title="@string/example_2">
    </item>

</menu>

That’s it! You’re done! Now your custom menu will show up, you don’t have to worry about the selection, and you barely have to concern yourself with the ActionMode lifecycle.

This works nearly flawlessly with a WebView that occupies its entire parent Activity. I am not sure how well it will work if there are multiple Views within your Activity at one time. It will likely require some tweaking in that case.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..