Use #Test annotation and ActivityTestRule with Robotium (Espresso-way) - java

I wonder how can i mark my test as #Test like in JUnit, because so far I have to use 'test...' name. It means:
#Test
private void creatingAcc(){
instead of
private void testCreatingAcc(){
Thanks in advance

Yes, you can do it. Follow these steps to achieve it:
Go to your's app build.gradle file and add test dependendencies like below:
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support:support-annotations:24.1.1'
compile 'com.jayway.android.robotium:robotium-solo:5.6.1'
Now your build.gradle should look like:
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.example.piotr.myapplication"
minSdkVersion 15
targetSdkVersion 21
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.1.1'
compile 'com.android.support:design:24.1.1'
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support:support-annotations:24.1.1'
compile 'com.jayway.android.robotium:robotium-solo:5.6.1'
}
Then you need to go to your androidTest directory and create Java class and name it for example MyActivityTestRule
In this file put code below:
#Beta
public class MyActivityTestRule<T extends Activity> extends UiThreadTestRule {
private static final String TAG = "ActivityInstrumentationRule";
private final Class<T> mActivityClass;
public Instrumentation getInstrumentation() {
return mInstrumentation;
}
private Instrumentation mInstrumentation;
private boolean mInitialTouchMode = false;
private boolean mLaunchActivity = false;
private T mActivity;
/**
* Similar to {#link #MyActivityTestRule(Class, boolean, boolean)} but with "touch mode" disabled.
*
* #param activityClass The activity under test. This must be a class in the instrumentation
* targetPackage specified in the AndroidManifest.xml
* #see MyActivityTestRule#MyActivityTestRule(Class, boolean, boolean)
*/
public MyActivityTestRule(Class<T> activityClass) {
this(activityClass, false);
}
/**
* Similar to {#link #MyActivityTestRule(Class, boolean, boolean)} but defaults to launch the
* activity under test once per
* <code>Test</code> method.
* It is launched before the first
* <code>Before</code>
* method, and terminated after the last
* <code>After</code>
* method.
*
* #param activityClass The activity under test. This must be a class in the instrumentation
* targetPackage specified in the AndroidManifest.xml
* #param initialTouchMode true if the Activity should be placed into "touch mode" when started
* #see MyActivityTestRule#MyActivityTestRule(Class, boolean, boolean)
*/
public MyActivityTestRule(Class<T> activityClass, boolean initialTouchMode) {
this(activityClass, initialTouchMode, true);
}
/**
* Creates an {#link MyActivityTestRule} for the Activity under test.
*
* #param activityClass The activity under test. This must be a class in the instrumentation
* targetPackage specified in the AndroidManifest.xml
* #param initialTouchMode true if the Activity should be placed into "touch mode" when started
* #param launchActivity true if the Activity should be launched once per
* <a href="http://junit.org/javadoc/latest/org/junit/Test.html">
* <code>Test</code></a> method. It will be launched before the first
* <a href="http://junit.sourceforge.net/javadoc/org/junit/Before.html">
* <code>Before</code></a> method, and terminated after the last
* <a href="http://junit.sourceforge.net/javadoc/org/junit/After.html">
* <code>After</code></a> method.
*/
public MyActivityTestRule(Class<T> activityClass, boolean initialTouchMode,
boolean launchActivity) {
mActivityClass = activityClass;
mInitialTouchMode = initialTouchMode;
mLaunchActivity = launchActivity;
mInstrumentation = InstrumentationRegistry.getInstrumentation();
}
/**
* Override this method to set up Intent as if supplied to
* {#link android.content.Context#startActivity}.
* <p>
* The default Intent (if this method returns null or is not overwritten) is:
* action = {#link Intent#ACTION_MAIN}
* flags = {#link Intent#FLAG_ACTIVITY_NEW_TASK}
* All other intent fields are null or empty.
*
* #return The Intent as if supplied to {#link android.content.Context#startActivity}.
*/
protected Intent getActivityIntent() {
return new Intent(Intent.ACTION_MAIN);
}
/**
* Override this method to execute any code that should run before your {#link Activity} is
* created and launched.
* This method is called before each test method, including any method annotated with
* <code>Before</code>.
*/
protected void beforeActivityLaunched() {
// empty by default
}
/**
* Override this method to execute any code that should run after your {#link Activity} is
* launched, but before any test code is run including any method annotated with
* <code>Before</code>.
* <p>
* Prefer
* <code>Before</code>
* over this method. This method should usually not be overwritten directly in tests and only be
* used by subclasses of MyActivityTestRule to get notified when the activity is created and
* visible but test runs.
*/
protected void afterActivityLaunched() {
// empty by default
}
/**
* Override this method to execute any code that should run after your {#link Activity} is
* finished.
* This method is called after each test method, including any method annotated with
* <code>After</code>.
*/
protected void afterActivityFinished() {
// empty by default
}
/**
* #return The activity under test.
*/
public T getActivity() {
if (mActivity == null) {
Log.w(TAG, "Activity wasn't created yet");
}
return mActivity;
}
#Override
public Statement apply(final Statement base, Description description) {
return new ActivityStatement(super.apply(base, description));
}
/**
* Launches the Activity under test.
* <p>
* Don't call this method directly, unless you explicitly requested not to launch the Activity
* manually using the launchActivity flag in
* {#link MyActivityTestRule#MyActivityTestRule(Class, boolean, boolean)}.
* <p>
* Usage:
* <pre>
* #Test
* public void customIntentToStartActivity() {
* Intent intent = new Intent(Intent.ACTION_PICK);
* mActivity = mActivityRule.launchActivity(intent);
* }
* </pre>
* #param startIntent The Intent that will be used to start the Activity under test. If
* {#code startIntent} is null, the Intent returned by
* {#link MyActivityTestRule#getActivityIntent()} is used.
* #return the Activity launched by this rule.
* #see MyActivityTestRule#getActivityIntent()
*/
public T launchActivity(#Nullable Intent startIntent) {
// set initial touch mode
mInstrumentation.setInTouchMode(mInitialTouchMode);
final String targetPackage = mInstrumentation.getTargetContext().getPackageName();
// inject custom intent, if provided
if (null == startIntent) {
startIntent = getActivityIntent();
if (null == startIntent) {
Log.w(TAG, "getActivityIntent() returned null using default: " +
"Intent(Intent.ACTION_MAIN)");
startIntent = new Intent(Intent.ACTION_MAIN);
}
}
startIntent.setClassName(targetPackage, mActivityClass.getName());
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Log.d(TAG, String.format("Launching activity %s",
mActivityClass.getName()));
beforeActivityLaunched();
// The following cast is correct because the activity we're creating is of the same type as
// the one passed in
mActivity = mActivityClass.cast(mInstrumentation.startActivitySync(startIntent));
mInstrumentation.waitForIdleSync();
afterActivityLaunched();
return mActivity;
}
// Visible for testing
void setInstrumentation(Instrumentation instrumentation) {
mInstrumentation = checkNotNull(instrumentation, "instrumentation cannot be null!");
}
void finishActivity() {
if (mActivity != null) {
mActivity.finish();
mActivity = null;
}
}
/**
* <a href="http://junit.org/apidocs/org/junit/runners/model/Statement.html">
* <code>Statement</code></a> that finishes the activity after the test was executed
*/
private class ActivityStatement extends Statement {
private final Statement mBase;
public ActivityStatement(Statement base) {
mBase = base;
}
#Override
public void evaluate() throws Throwable {
try {
if (mLaunchActivity) {
mActivity = launchActivity(getActivityIntent());
}
mBase.evaluate();
} finally {
finishActivity();
afterActivityFinished();
}
}
}
}
Well, to be honest, it's standard ActivityTestRule with additional getter getInstrumentation(), which I would used in my test class.
Create a new Java class - it would be your test class and put the code below:
#RunWith(AndroidJUnit4.class)
public class MainActivityTest {
private Solo solo;
private static final String MAIN_ACTIVITY = MainActivity.class.getSimpleName();
#Rule
public MyActivityTestRule<MainActivity> mActivityRule = new MyActivityTestRule<>(MainActivity.class);
#Before
public void setUp() throws Exception {
solo = new Solo(mActivityRule.getInstrumentation(), mActivityRule.getActivity());
}
#Test
public void checkIfMainActivityIsProperlyDisplayed() throws InterruptedException {
solo.waitForActivity("MainActivity", 2000);
solo.assertCurrentActivity(mActivityRule.getActivity().getString(
R.string.error_no_class_def_found, MAIN_ACTIVITY), MAIN_ACTIVITY);
solo.getText("Hello World").isShown();
}
}
As you see it's not difficult as might be.
Hope it will help

Related

Getting unexpected element error when trying to communcate to soap client

I'm trying to consume wsdl client that can be found on this link https://tim-erp.com/ERPX_WEB/awws/ErpX.awws?wsdl
My java code looks like this
public class SoapServicesImpl extends WebServiceGatewaySupport implements SoapServices {
#Override
public String doAuth(AuthDto authDto){
AuthStrct authStrct = new AuthStrct();
authStrct.setFirmaNaziv(authDto.getNazivFirme());
authStrct.setGodina(authDto.getGodina());
authStrct.setPassword(authDto.getPassword());
authStrct.setUsername(authDto.getUsername());
return callService(new ObjectFactory().createAuthStrct(authStrct));
}
#SuppressWarnings("unchecked")
public <T> T callService(JAXBElement<?> jaxbRequest) {
jaxbRequest.getValue();
JAXBElement<T> jaxbResponse;
try {
jaxbResponse = (JAXBElement<T>) getWebServiceTemplate().marshalSendAndReceive(jaxbRequest);
} catch (WebServiceException e) {
e.printStackTrace();
throw e;
}
return jaxbResponse.getValue();
}
}
package-info looks like this
#javax.xml.bind.annotation.XmlSchema(namespace = "urn:ErpX")
package rs.sweetchoice.commonservice.generated;
Generated ObjectFactory snippet:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.0
// See https://javaee.github.io/jaxb-v2/
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2020.09.05 at 01:28:42 PM CEST
//
package rs.sweetchoice.commonservice.generated;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.namespace.QName;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the rs.sweetchoice.commonservice.generated package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
*/
#XmlRegistry
public class ObjectFactory {
private final static QName _WSID_QNAME = new QName("urn:ErpX", "WSID");
private final static QName _AUTH_QNAME = new QName("urn:ErpX", "authStrct");
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: rs.sweetchoice.commonservice.generated
*
*/
public ObjectFactory() {
}
/**
* Create an instance of {#link AutoCompleteStrct }
*
*/
public AutoCompleteStrct createAutoCompleteStrct() {
return new AutoCompleteStrct();
}
/**
* Create an instance of {#link KorpaStrct }
*
*/
public KorpaStrct createKorpaStrct() {
return new KorpaStrct();
}
/**
* Create an instance of {#link CmbStrct }
*
*/
public CmbStrct createCmbStrct() {
return new CmbStrct();
}
/**
* Create an instance of {#link AuthStrct }
*
*/
#XmlElementDecl(namespace = "urn:ErpX", name = "authStrct")
public JAXBElement<AuthStrct> createAuthStrct(AuthStrct value) {
return new JAXBElement<>(_AUTH_QNAME, AuthStrct.class, null, value);
}
/**
* Create an instance of {#link FilterStrct }
*
*/
public FilterStrct createFilterStrct() {
return new FilterStrct();
}
/**
* Create an instance of {#link ProfakStavStrct }
*
*/
public ProfakStavStrct createProfakStavStrct() {
return new ProfakStavStrct();
}
/**
* Create an instance of {#link ProfakStrct }
*
*/
public ProfakStrct createProfakStrct() {
return new ProfakStrct();
}
/**
* Create an instance of {#link RacunStavStrct }
*
*/
public RacunStavStrct createRacunStavStrct() {
return new RacunStavStrct();
}
/**
* Create an instance of {#link RacunStrct }
*
*/
public RacunStrct createRacunStrct() {
return new RacunStrct();
}
/**
* Create an instance of {#link UplKomitStrct }
*
*/
public UplKomitStrct createUplKomitStrct() {
return new UplKomitStrct();
}
/**
* Create an instance of {#link UplListaStavStrct }
*
*/
public UplListaStavStrct createUplListaStavStrct() {
return new UplListaStavStrct();
}
/**
* Create an instance of {#link UplListaStrct }
*
*/
public UplListaStrct createUplListaStrct() {
return new UplListaStrct();
}
/**
* Create an instance of {#link WsGetRoba }
*
*/
public WsGetRoba createWsGetRoba() {
return new WsGetRoba();
}
/**
* Create an instance of {#link WsGetKomit }
*
*/
public WsGetKomit createWsGetKomit() {
return new WsGetKomit();
}
/**
* Create an instance of {#link WsGetGrpRoba }
*
*/
public WsGetGrpRoba createWsGetGrpRoba() {
return new WsGetGrpRoba();
}
/**
* Create an instance of {#link WsGetGrpKomit }
*
*/
public WsGetGrpKomit createWsGetGrpKomit() {
return new WsGetGrpKomit();
}
/**
* Create an instance of {#link WsGetManuf }
*
*/
public WsGetManuf createWsGetManuf() {
return new WsGetManuf();
}
/**
* Create an instance of {#link WsUplProfak }
*
*/
public WsUplProfak createWsUplProfak() {
return new WsUplProfak();
}
/**
* Create an instance of {#link WsGetMagacin }
*
*/
public WsGetMagacin createWsGetMagacin() {
return new WsGetMagacin();
}
/**
* Create an instance of {#link WsGetAkcijskeCene }
*
*/
public WsGetAkcijskeCene createWsGetAkcijskeCene() {
return new WsGetAkcijskeCene();
}
/**
* Create an instance of {#link WsUplKomit }
*
*/
public WsUplKomit createWsUplKomit() {
return new WsUplKomit();
}
/**
* Create an instance of {#link WsUplKomitResponse }
*
*/
public WsUplKomitResponse createWsUplKomitResponse() {
return new WsUplKomitResponse();
}
/**
* Create an instance of {#link WsUplRacun }
*
*/
public WsUplRacun createWsUplRacun() {
return new WsUplRacun();
}
/**
* Create an instance of {#link JAXBElement }{#code <}{#link byte[]}{#code >}
*
* #param value
* Java instance representing xml element's value.
* #return
* the new instance of {#link JAXBElement }{#code <}{#link byte[]}{#code >}
*/
#XmlElementDecl(namespace = "urn:ErpX", name = "WSID")
#XmlJavaTypeAdapter(HexBinaryAdapter.class)
public JAXBElement<byte[]> createWSID(byte[] value) {
return new JAXBElement<byte[]>(_WSID_QNAME, byte[].class, null, ((byte[]) value));
}
}
And i get error
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Fault"). Expected elements are <{urn:ErpX}WSID>,<{urn:ErpX}authStrct>
Using java 11 and spring boot 2.3.3.
EDIT this is my config class
#Configuration
public class WsConfig {
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("rs.sweetchoice.commonservice.generated");
return marshaller;
}
#Bean
public SoapServicesImpl soapServicesImpl(Jaxb2Marshaller marshaller) {
SoapServicesImpl client = new SoapServicesImpl();
client.setDefaultUri("https://tim-erp.com/ERPX_WEB/awws/ErpX.awws");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
Try to setCheckConnectionForFault to false on WebServiceTemplate. For example, replace the method:
public <T> T callService(JAXBElement<?> jaxbRequest) {
jaxbRequest.getValue();
JAXBElement<T> jaxbResponse;
try {
WebServiceTemplate webServiceTemplate = getWebServiceTemplate();
webServiceTemplate.setCheckConnectionForFault(false);
jaxbResponse = (JAXBElement<T>) webServiceTemplate.marshalSendAndReceive(jaxbRequest);
} catch (WebServiceException e) {
e.printStackTrace();
throw e;
}
return jaxbResponse.getValue();
}

Volley requestQueue in Singleton returns null

I am making a network request with Volley and I am using but which was working very well until suddenly it started throwing Null pointer exception on the requestQueue.
class VolleySingleton(context: Context) {
companion object{
#Volatile
private var newInstance: VolleySingleton? = null
fun getInstance(context: Context) =
newInstance
?: synchronized(this){
newInstance
?: VolleySingleton(context).also{
newInstance = it
}
}
}
private val requestQueue: RequestQueue by lazy{
Volley.newRequestQueue(context) // throws NullPointer exception
}
fun<T> addToRequestQueue(req: Request<T>){
requestQueue.add(req)
}
}
I have tried to initialize it like this
private val requestQueue: RequestQueue =
Volley.newRequestQueue(context) // throws NullPointer exception
but it won't work still.
You should use context.getApplicationContext() instead of context.
// Add a request (in this example, called stringRequest) to your RequestQueue.
VolleySingleton.getInstance(context.getApplicationContext()).addToRequestQueue(request)
I do this in the Application class which is global and stays in scope for the life of the app session. This is in Java, but you might see something I'm doing that you are not.
public class MyApplication extends Application {
/**
* Log or request TAG
*/
public static final String TAG = "MyApp";
/**
* Global request queue for Volley
*/
private RequestQueue mRequestQueue;
/**
* A singleton instance of the application class for easy access in other places
*/
private static MyApplication sInstance;
#Override
public void onCreate() {
super.onCreate();
// initialize the singleton
sInstance = this;
}
/**
* #return MyApplication singleton instance
*/
public static synchronized MyApplication getInstance() {
return sInstance;
}
/**
* #return The Volley Request queue, the queue will be created if it is null
*/
public RequestQueue getRequestQueue() {
// lazy initialize the request queue, the queue instance will be
// created when it is accessed for the first time
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
/**
* Adds the specified request to the global queue, if tag is specified
* then it is used else Default TAG is used.
*
* #param req
* #param tag
*/
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
VolleyLog.d("Adding request to queue: %s", req.getUrl());
getRequestQueue().add(req);
}
/**
* Adds the specified request to the global queue using the Default TAG.
*
* #param req
* #param tag
*/
public <T> void addToRequestQueue(Request<T> req) {
// set the default tag if tag is empty
req.setTag(TAG);
getRequestQueue().add(req);
}
/**
* Cancels all pending requests by the specified TAG, it is important
* to specify a TAG so that the pending/ongoing requests can be cancelled.
*
* #param tag
*/
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
Then, you call this in your other Activity code after creating your request object:
MyApplication.getInstance().addToRequestQueue(postRequest);

Java Generic Type utilisation

I have these classes:
My problem is that for each class I am having to manually register the node.
/**
* Contains the encoder for messages from the server.
*
* #since 18/08/2018
*/
public abstract class MessageEncoder<T> {
/**
* Register this encoder to a message.
*/
public abstract void register();
/**
* Get the encoded message to send to the client.
*
* #param message The message.
* #return the {#link GamePacket} ready to be sent.
*/
public abstract GamePacket encode(T message);
}
Where < T > is always someClass extends Message.
And here is how a message encoder looks like:
public final class ComponentMessageEncoder extends MessageEncoder<ComponentTextMessage> {
#Override
public void register() {
GameConstants.RELEASE.register(ComponentTextMessage.class, this);
}
#Override
public GamePacket encode(ComponentTextMessage message) {
// TODO Auto-generated method stub
return null;
}
}
As you can see the items in the register method, I have to manually type that for every encoder I make.
Is there a shortcut for this that I can just put in MessageEncoder abstract class instead?
I could not find anything that works here
Edit:
Where register sig. is:
/**
* The encoders.
*/
private final Map<Class<? extends Message>, MessageEncoder<?>> encoders = new HashMap<>();
/**
* Register a encoder to a message.
*
* #param message The message.
* #param encoder The encoder.
*/
public void register(Class<? extends Message> message, MessageEncoder<?> encoder) {
encoders.put(message, encoder);
}
You can do slightly better with:
public abstract class MessageEncoder<T extends Message> {
protected MessageEncoder(Class<? extends T> messageClass) {
GameConstants.RELEASE.register(messageClass, this);
}
/**
* Get the encoded message to send to the client.
*
* #param message The message.
* #return the {#link GamePacket} ready to be sent.
*/
public abstract GamePacket encode(T message);
}
Now subclasses would do:
public final class ComponentMessageEncoder extends MessageEncoder<ComponentTextMessage> {
ComponentMessageEncoder() {
super(ComponentTextMessage.class);
}
// etc as before
}
This cuts down slightly on the repetition, and it allows the compiler to stop you from getting it wrong, so it's something of a win.

Generate APK constructor issue on my app

I developed some app and it's working fine without any problem. No problem on debug. I created some custom class with the ShareActionProvider class methods for check to user actions from ActionShareProvider menu. When I want to generate APK from Android Studio it gives me this error;
Error:(87) Error: This class should provide a default constructor (a public constructor with no arguments) (com.esmobileinc.vetmapp.ShareActionProvider) [Instantiatable]
There is the ShareActionProvider class;
public class ShareActionProvider extends ActionProvider {
public void setOnShareListener(OnShareListener listener) {
mOnShareListener = listener;
setActivityChooserPolicyIfNeeded();
}
/**
* Listener for the event of selecting a share target.
*/
public interface OnShareTargetSelectedListener {
/**
* Called when a share target has been selected. The client can
* decide whether to perform some action before the sharing is
* actually performed.
* <p>
* <strong>Note:</strong> Modifying the intent is not permitted and
* any changes to the latter will be ignored.
* </p>
* <p>
* <strong>Note:</strong> You should <strong>not</strong> handle the
* intent here. This callback aims to notify the client that a
* sharing is being performed, so the client can update the UI
* if necessary.
* </p>
*
* #param source The source of the notification.
* #param intent The intent for launching the chosen share target.
* #return The return result is ignored. Always return false for consistency.
*/
public boolean onShareTargetSelected(ShareActionProvider source, Intent intent);
}
private OnShareListener mOnShareListener; //also need to add getter and setter
public interface OnShareListener {
/**
* Called when a share target has been selected. The client can
* decide whether to perform some action before the sharing is
* actually performed OR handle the action itself.
*
* #param source The source of the notification.
* #param intent The intent for launching the chosen share target.
* #return Return true if you have handled the intent.
*/
public boolean willHandleShareTarget(ShareActionProvider source, Intent intent);
}
/**
* The default for the maximal number of activities shown in the sub-menu.
*/
private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4;
/**
* The the maximum number activities shown in the sub-menu.
*/
private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT;
/**
* Listener for handling menu item clicks.
*/
private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener =
new ShareMenuItemOnMenuItemClickListener();
/**
* The default name for storing share history.
*/
public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
/**
* Context for accessing resources.
*/
private final Context mContext;
/**
* The name of the file with share history data.
*/
private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
private OnShareTargetSelectedListener mOnShareTargetSelectedListener;
private OnChooseActivityListener mOnChooseActivityListener;
/**
* Creates a new instance.
*
* #param context Context for accessing resources.
*/
public ShareActionProvider(Context context) {
super(context);
mContext = context;
}
/**
* Sets a listener to be notified when a share target has been selected.
* The listener can optionally decide to handle the selection and
* not rely on the default behavior which is to launch the activity.
* <p>
* <strong>Note:</strong> If you choose the backing share history file
* you will still be notified in this callback.
* </p>
* #param listener The listener.
*/
public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) {
mOnShareTargetSelectedListener = listener;
setActivityChooserPolicyIfNeeded();
}
/**
* {#inheritDoc}
*/
#Override
public View onCreateActionView() {
// Create the view and set its data model.
ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
if (!activityChooserView.isInEditMode()) {
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
activityChooserView.setActivityChooserModel(dataModel);
}
// Lookup and set the expand action icon.
TypedValue outTypedValue = new TypedValue();
mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
Drawable drawable = TintManager.getDrawable(mContext, outTypedValue.resourceId);
activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
activityChooserView.setProvider(this);
// Set content description.
activityChooserView.setDefaultActionButtonContentDescription(
R.string.abc_shareactionprovider_share_with_application);
activityChooserView.setExpandActivityOverflowButtonContentDescription(
R.string.abc_shareactionprovider_share_with);
return activityChooserView;
}
/**
* {#inheritDoc}
*/
#Override
public boolean hasSubMenu() {
return true;
}
/**
* {#inheritDoc}
*/
#Override
public void onPrepareSubMenu(SubMenu subMenu) {
// Clear since the order of items may change.
subMenu.clear();
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
PackageManager packageManager = mContext.getPackageManager();
final int expandedActivityCount = dataModel.getActivityCount();
final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount);
// Populate the sub-menu with a sub set of the activities.
for (int i = 0; i < collapsedActivityCount; i++) {
ResolveInfo activity = dataModel.getActivity(i);
subMenu.add(0, i, i, activity.loadLabel(packageManager))
.setIcon(activity.loadIcon(packageManager))
.setOnMenuItemClickListener(mOnMenuItemClickListener);
}
if (collapsedActivityCount < expandedActivityCount) {
// Add a sub-menu for showing all activities as a list item.
SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount,
collapsedActivityCount,
mContext.getString(R.string.abc_activity_chooser_view_see_all));
for (int i = 0; i < expandedActivityCount; i++) {
ResolveInfo activity = dataModel.getActivity(i);
expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager))
.setIcon(activity.loadIcon(packageManager))
.setOnMenuItemClickListener(mOnMenuItemClickListener);
}
}
}
/**
* Sets the file name of a file for persisting the share history which
* history will be used for ordering share targets. This file will be used
* for all view created by {#link #onCreateActionView()}. Defaults to
* {#link #DEFAULT_SHARE_HISTORY_FILE_NAME}. Set to <code>null</code>
* if share history should not be persisted between sessions.
* <p>
* <strong>Note:</strong> The history file name can be set any time, however
* only the action views created by {#link #onCreateActionView()} after setting
* the file name will be backed by the provided file. Therefore, if you want to
* use different history files for sharing specific types of content, every time
* you change the history file {#link #setShareHistoryFileName(String)} you must
* call {#link android.app.Activity#invalidateOptionsMenu()} to recreate the
* action view. You should <strong>not</strong> call
* {#link android.app.Activity#invalidateOptionsMenu()} from
* {#link android.app.Activity#onCreateOptionsMenu(Menu)}."
* <p>
* <code>
* private void doShare(Intent intent) {
* if (IMAGE.equals(intent.getMimeType())) {
* mShareActionProvider.setHistoryFileName(SHARE_IMAGE_HISTORY_FILE_NAME);
* } else if (TEXT.equals(intent.getMimeType())) {
* mShareActionProvider.setHistoryFileName(SHARE_TEXT_HISTORY_FILE_NAME);
* }
* mShareActionProvider.setIntent(intent);
* invalidateOptionsMenu();
* }
* <code>
*
* #param shareHistoryFile The share history file name.
*/
public void setShareHistoryFileName(String shareHistoryFile) {
mShareHistoryFileName = shareHistoryFile;
setActivityChooserPolicyIfNeeded();
}
/**
* Sets an intent with information about the share action. Here is a
* sample for constructing a share intent:
* <p>
* <pre>
* <code>
* Intent shareIntent = new Intent(Intent.ACTION_SEND);
* shareIntent.setType("image/*");
* Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
* shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
* </pre>
* </code>
* </p>
*
* #param shareIntent The share intent.
*
* #see Intent#ACTION_SEND
* #see Intent#ACTION_SEND_MULTIPLE
*/
public void setShareIntent(Intent shareIntent) {
if (shareIntent != null) {
final String action = shareIntent.getAction();
if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
updateIntent(shareIntent);
}
}
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
mShareHistoryFileName);
dataModel.setIntent(shareIntent);
}
/**
* Reusable listener for handling share item clicks.
*/
private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener {
#Override
public boolean onMenuItemClick(MenuItem item) {
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
mShareHistoryFileName);
final int itemId = item.getItemId();
Intent launchIntent = dataModel.chooseActivity(itemId);
if (launchIntent != null) {
final String action = launchIntent.getAction();
if (Intent.ACTION_SEND.equals(action) ||
Intent.ACTION_SEND_MULTIPLE.equals(action)) {
updateIntent(launchIntent);
}
mContext.startActivity(launchIntent);
}
return true;
}
}
/**
* Set the activity chooser policy of the model backed by the current
* share history file if needed which is if there is a registered callback.
*/
private void setActivityChooserPolicyIfNeeded() {
if (mOnShareListener == null) {
return;
}
if (mOnChooseActivityListener == null) {
mOnChooseActivityListener = new ShareActivityChooserModelPolicy();
}
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
dataModel.setOnChooseActivityListener(mOnChooseActivityListener);
}
/**
* Policy that delegates to the {#link OnShareTargetSelectedListener}, if such.
*/
private class ShareActivityChooserModelPolicy implements OnChooseActivityListener {
#Override
public boolean onChooseActivity(ActivityChooserModel host, Intent intent) {
if (mOnShareListener != null) {
boolean result = mOnShareListener.willHandleShareTarget(
ShareActionProvider.this, intent);
return result;
}
return false;
}
}
private void updateIntent(Intent intent) {
if (Build.VERSION.SDK_INT >= 21) {
// If we're on Lollipop, we can open the intent as a document
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
} else {
// Else, we will use the old CLEAR_WHEN_TASK_RESET flag
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
}
}
}
There is a constructor here in my ShareActionProvider class;
public ShareActionProvider(Context context) {
super(context);
mContext = context;
}
Why it gives me this error ? How can I solve this problem. Thank you !
I renamed my custom ActionShareProvider.class to CustomActionShareProvider.class and problem resolved.

private static method access from public static

I have a question regarding static method access. I have a class within i have 4 static method. as shown in code:
package com.itrucking.util;
public class ZKUtil implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
* #author Shekhar
* #param _class
* #param listbox
* To make Listbox sorting enabled
* #throws NoSuchMethodException
* #throws SecurityException
*/
public static void setSortingEnabled(Class<?> _class, Listbox listbox){
Map<Listheader, String> sortingPair = new HashMap<Listheader, String>();
sortingPair = getMapForSorting(_class, listbox);
if (!sortingPair.isEmpty()) {
for (Map.Entry<Listheader, String> entry : sortingPair.entrySet()) {
entry.getKey().setSortAscending(
new FieldComparator(entry.getValue(), true));
entry.getKey().setSortDescending(
new FieldComparator(entry.getValue(), false));
}
}
}
/**
* #author Shekhar
* #param _class
* #param listbox
* #return Map<Listheader, String>
*/
private static Map<Listheader, String> getMapForSorting(Class<?> _class,Listbox listbox) {
List<Listheader> headerList = getListHeaderList(listbox);
Map<Listheader, String> sortingPair = new HashMap<Listheader, String>();
System.out.println(_class);
Field[] fields = _class.getDeclaredFields();
for (Field f : fields) {
// System.out.println(f.getName()+":"+f.getType());
for (Listheader lh : headerList) {
if (f.getName().equals(getId(lh)))
sortingPair.put(lh, f.getName());
}
}
System.out.println(sortingPair);
return sortingPair;
}
private static String getId(Listheader listheader) {
String listheaderId = null;
if (listheader.getId().contains("_")) {
listheaderId = listheader.getId().split("_")[1];
// System.out.println("listheaderId->"+listheaderId);
}
return listheaderId;
}
/**
* #author Shekhar
* #param listbox
* #return List<Listheader>
*/
#SuppressWarnings("unchecked")
private static List<Listheader> getListHeaderList(Listbox listbox) {
List<Listheader> headerList = new ArrayList<Listheader>();
Listhead listhead = null;
List<Component> listboxComponentList = listbox.getChildren();
for (Component listboxComponent : listboxComponentList) {
if (listboxComponent instanceof Listhead) {
listhead = (Listhead) listboxComponent;
break;
}
}
List<Component> listOfComp = listhead.getChildren();
if (listhead != null) {
for (Component c : listOfComp) {
if (c instanceof Listheader)
headerList.add((Listheader) c);
}
}
return headerList;
}
}
and i am calling setSortingEnabled() method from onLoadShipperDetailsListCtrl() from code bellow :
package com.itrucking.webui.controller;
public class ShipperDetailsListCtrl{
/**
* #param e
* #return void
*/
public void onCreate$window_shipperDetailsList(Event e){
onLoadShipperDetailsListCtrl();
}
/**
* #return void
*/
public void onLoadShipperDetailsListCtrl(){
System.out.println("onLoadShipperDetailsListCtrl called.");
shipperList = shipperService.getShipperList();
doRenderListboxShipperDetailsList(shipperList);
ZKUtil.setSortingEnabled(ShipperMaster.class, listbox_shipperDetailsList);
}
}
so what i think if i am calling setSortingEnabled() method from other class so i kept is as public and other method's i kept as private but it's giving me error as :
java.lang.NoSuchMethodError: com/itrucking/util/ZKUtil.getMapForSorting(Ljava/lang/Class;Lorg/zkoss/zul/Listbox;)Ljava/util/Map;
Why there is error NoSuchMethodError for ZKUtil.getMapForSorting() call in setSortingEnabled()
I know we can call private method from public in the same class. So i am not able to understand what is the problem.
Thanks in advance.
A NoSuchMethodError (the runtime error saying a method can't be found, instead of a compiler error) usually means that the .class files you're using are of a different version than the files you compiled against. In this case, you probably made changes to ZKUtil.java, but the JVM is loading an outdated version of ZKUtil.class. Clean and rebuild all of your .class files.

Categories

Resources