NameNotFoundException at ActivityUnitTestCase with ActionBarActivity - android

I am trying to write some tests for an existing application. I wanted to supply a test Application class to the tests and I followed the example here, since I am also using Dagger for DI.
However, if the activity under test is an ActionBarActivity, I get the following exception:
java.lang.IllegalArgumentException: android.content.pm.PackageManager$NameNotFoundException: ComponentInfo{mypackage.view.activity/mypackage.view.activity.MyActivity}
at android.support.v4.app.NavUtils.getParentActivityName(NavUtils.java:282)
at android.support.v7.app.ActionBarActivityDelegate.onCreate(ActionBarActivityDelegate.java:116)
at android.support.v7.app.ActionBarActivityDelegateICS.onCreate(ActionBarActivityDelegateICS.java:57)
at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:98)
at mypackage.view.activity.MyActivity.onCreate(MyActivity.java:68)
at android.app.Activity.performCreate(Activity.java:5231)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.test.ActivityUnitTestCase.startActivity(ActivityUnitTestCase.java:158)
at mypackage.MyActivityTest.test(MyActivityTest.java:89)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)
Caused by: android.content.pm.PackageManager$NameNotFoundException: ComponentInfo{mypackage.view.activity/mypackage.view.activity.MyActivity}
at android.app.ApplicationPackageManager.getActivityInfo(ApplicationPackageManager.java:242)
at android.support.v4.app.NavUtils.getParentActivityName(NavUtils.java:298)
at android.support.v4.app.NavUtils.getParentActivityName(NavUtils.java:279)
... 21 more
My test class looks like follows:
public class MyActivityTest extends ActivityUnitTestCase<MyActivity> {
...
public MyActivityTest() {
super(MyActivity.class);
}
private Context context;
private TestBaseApplication application;
#Override
protected void setUp() throws Exception {
super.setUp();
context = new ContextThemeWrapper( getInstrumentation().getTargetContext(), R.style.Theme_AppCompat){
#Override
public Context getApplicationContext() {
return application;
}
};
application = new TestBaseApplication( context);
setApplication(application);
...
}
public void test() throws InterruptedException {
setActivityContext( context);
Intent intent = new Intent( context, MyActivity.class);
startActivity(intent, null, null);
...
}
}
The activity appears in the AndroidManifest as follows:
<activity
android:name=".view.activity.MyActivity"
android:icon="#drawable/actionbar_logo"
android:screenOrientation="portrait"
android:parentActivityName="mypackage.ParentActivity">
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="mypackage.ParentActivity"/>
</activity>
After some troubleshooting, I tried running the example at the link above and it works just fine, even when I change the activity to extend ActionBarActivity.
Since I wasn't able to find the cause of the problem, I also played around with the manifest, build.gradle, etc. Now, I am just stuck with this and I cannot think of anything else.
This post may also be close to related to the problem, but there is not any comment on that one either. And this post also seemed to have similar problem but the solution there doesn't work me as I don't want the real application to be launched with the activity.
EDIT:
I've created a simple separate project, in order to isolate the issue.
First I've written an ActivityUnitTestCase for an Activity which extends ActionBarActivity. It worked fine.
After that, I've tried adding few more activities, making them parent of each other.( so that it looks like my actual project). And that worked fine too.
Lastly, I've added more ActivityUnitTestCase classes with different activities from my actual project, all extending ActionBarActivity, with same setup for all of them , and run the tests on two devices, one being an emulator (Genymotion) and the other is my physical device. (Nexus 4)
Tests all gave the NameNotFoundException on the emulator. All but one of the tests passed on the physical device, which made me even more confused.

It all comes down to this bug in ActivityUnitTestCase.
Activities built using ActivityUnitTestCase.startAcitvity() have a componentName pointing to the application package. So when ActionBarActivity checks for a parent activity to update the Up symbol, the test crashes if the activity is not in the app 'root' package.
Fortunately the workaround proposed in the issue description works just fine, so until this is fixed, just make a local copy of ActivityUnitTestCase, update the line in which the componentName is defined as below, and make sure your test cases extend that class instead of the original ActivityUnitTestCase.
// replace this line
new ComponentName(mActivityClass.getPackage().getName(), mActivityClass.getName());
// with this
new ComponentName(getInstrumentation().getTargetContext(), mActivityClass);

Related

Binding a whole native Activity to Xamarin.Android

So, I have a certain activity coded in pure Android that I want to use in my Xamarin.Android project. I compiled the activity into a ".jar" file, created a binding project, referenced it and so far everything was working. But when I try to create an intent to navigate to that activity, it returns an error:
System.TypeLoadException
Could not resolve type with token 01000013 (from typeref, class/assembly BR.Com.MyProject.Project.UI.SignUpPageActivity, MyBindingProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)
Anyone have any clue on how to fix it? The binding is working fine, because along the activity I bound a few other classes, and they are all working, the only exception is when I call the "typeof()" method.
I've searched the whole documentation and found nothing about.
My Metadata.xml:
<attr path="/api/package[#name='br.com.myproject.project.ui']/class[#name='SignUpPageActivity']" name="visibility">public</attr>
Code calling the activity:
public void NavigateToSignup()
{
Context context = Application.Context;
Intent intent = new Intent(context, typeof(SignUpPageActivity));
StartActivity(intent);
}

Google Espresso java.lang.RuntimeException: Could not launch intent Intent { act=android.intent.action.MAIN

I am new to Espresso UI testing.
I am getting this error while running tests (ADT Eclipse IDE ).
The app is already developed and there are lots of request going on while launching the app. it is not possible to rewrite the app. but i need to find the way to test this UI even if there is any delay in the loading of the components.
java.lang.RuntimeException: Could not launch intent Intent { act=android.intent.action.MAIN flg=0x14000000 cmp=com.xx.android/com.yy.core.android.map.MapActivity } within 45 seconds. Perhaps the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen. Or the activity is doing network calls on creation? See the threaddump logs. For your reference the last time the event queue was idle before your activity launch request was 1390913271702 and and now the last time the queue went idle was: 1390913271767. If these numbers are the same your activity might be hogging the event queue.
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentation.startActivitySync(GoogleInstrumentation.java:277)
at android.test.InstrumentationTestCase.launchActivityWithIntent(InstrumentationTestCase.java:119)
at android.test.InstrumentationTestCase.launchActivity(InstrumentationTestCase.java:97)
at android.test.ActivityInstrumentationTestCase2.getActivity(ActivityInstrumentationTestCase2.java:104)
at com.gulesider.android.test.UItest.setUp(UItest.java:25)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onStart(GoogleInstrumentationTestRunner.java:167)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1799)
I have one library project called “Core” - it will not generate any .apk
Also i have one Android project called “AA” which will access “Core”. - This is AA.apk
Now i have created a test project called “UItest”
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.AA.android.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8"
android:targetSdkVersion="18" />
<instrumentation
android:name="com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
android:targetPackage="com.AA.android"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name="com.core.android.map.MapActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<uses-library android:name="android.test.runner" />
</application>
</manifest>
My test:
public class UItest extends ActivityInstrumentationTestCase2<MapActivity> {
public UItest() {
super(MapActivity.class);
}
#Override
public void setUp() throws Exception {
super.setUp();
getActivity();
}
public void testSearchBox() {
Espresso.onView(ViewMatchers.withId(R.id.menu_button_logo)).perform(ViewActions.click());
}
}
For Espresso Testing it is highly recommend that you turn off system animations on the virtual or physical device(s) used for testing. So you can follow the steps below to manually turn off the animations:
Under:
Settings->
Developer options->
Drawing
Window Animations scale to OFF
Transition animation scale to OFF
Animator duration scale to OFF
If there is a progress bar running when you create the activity, you get an error like this. You should cause a stop for the progress bar in order to continue running the test.
I experienced this error while running Espresso tests on 6.0 devices but not on 5.1.1 or 7.0 devices. I tracked the cause down to using android:fadeScrollbars within a style. Removing this item from my style resolved the issue.
I have stuck into this problem for several hours. Finally, I got the reason.
This works for me.
Here are some different reasons, according to the phenomenon.
Activity can't be launched
Activity launched, but UI perform actions not work
The first scenario: activity can't be launched
Because of your target Activity maybe already in the activity stack.
Add a CLEAR flag and NEW_TASK flag
#get:Rule
val activityRule = ActivityTestRule<MainActivity>(MainActivity::class.java)
private lateinit var launchedActivity: MainActivity
#Before
fun setUp() {
val intent = Intent(Intent.ACTION_PICK)
//this is the key part
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
//this is the key part
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
launchedActivity = activityRule.launchActivity(intent)
}
The second scenario: activity launched but UI perform actions not work
In this scenario may be because of
Your code is executing some animation in a long time
Your code is doing a UI logic that you don't notice
(like Handler post event or runnable)
(register a listener in ViewTreeObserver like OnPreDrawListener and didn't unregister in a proper timing)
These actions may lead to UI thread busy, so the espresso can not do the test.
Probably you have animation inside your activity, which blocks espresso execution. You have to disable it - see https://github.com/googlesamples/android-testing/tree/master/ui/espresso/BasicSample
In my case a custom view caused this behaviour. It contained a Scroller which was constantly scrolling. Unfortunately, I didn't find a solution for this issue until now except disabling it for the tests...
If you are performing this test in MI or XIOMI phone then maybe it will not work so you can change device or you can use bluestack emulator. It will be work
At the very first page you will be calling too many request which will be taking time more than 15 seconds, the first page should be very lightwieght.
Just try by creating one new welcome page and then calling your original welcome page.
Hope this work for you.
Well, in my case it was caused by a strange thing.
One of my UI tests opened the external intent "android.app.action.CONFIRM_DEVICE_CREDENTIAL" so I decided to stub it. From now on, the MAIN intent didnt launch again until I manually closed the screen oipened by "android.app.action.CONFIRM_DEVICE_CREDENTIAL" from the recent tasks.
No idea why this happened, and have no time now for research. Maybe later I will update this thread.
I faced this error when I trying to test the opening of another activity when the user clicked on a given view. What I was doing wrong was not replacing:
#Rule
public ActivityTestRule<MyActivity> myActivityActivityTestRule = new ActivityTestRule<>(MyActivity.class);
Per:
#Rule
public IntentsTestRule<MyActivity> myActivityActivityTestRule =
new IntentsTestRule<>(MyActivity.class);
I had this problem too, and in the moment I changed physical device to other Android phone the tests were working. Just try to use other device. And use #rule for launching activity

Controlling Application during testing android

I using Roboguice to test application. I have two Modules for the app:
ProductionModule - used when application is not under test
TestingModule - used when application is under test
Those Modules are parameters for Injector which created in OnCreate() method of APPLICATION.
So how can i figure out, if the app is under test?
Is there a way to manage an APPLICATION lifecycle in ActivityInstrumentationTestCase2, so i can do some stuff BEFORE APPLICATION onCreate() method?
PS: I need to test activities after that so i using ActivityInstrumentationTestCase2 and i using custom TestRunner to generate reports.
Application on create is called before any of your tests run, this is because to run tests your application already has to exist.
You can however call application oncreate yourself within a test. You can cast an applicationcontext to your application and then call the onCreate method. I have had to do this in the past in order to clear any state in the application.
You can send extra params to the activity from JUnit in the setUp() like this:
#Override
public void setUp() {
Intent intent = new Intent();
intent.putExtra("debug", true);
setActivityIntent(intent);
mActivity = getActivity();
}
And inside the real Activity you can check it like this inside onCreate():
Bundle extras = getIntent().getExtras();
if(extras!=null){
boolean is= (Boolean)extras.get("debug");
if(is){
// here you are in debug mode
}
}

Acra: install, extend Application - Activity?

I am trying to install the ACRA crash report system to my android project. Now, my project is already extending a class, the Activity class. How can I implement the Acra project then?
As they state in normal way, you have to make a class f.e. MyApplication and extend it with Application. Since I am already extending the Activity class I am not sure what to do... They say: If your app already contains an Application subclass, add ACRA to this class; however, I don't know how I should do this..
Thanks!
http://code.google.com/p/acra/wiki/BasicSetup
Just create a MyApplication class that extends from Application, do what they say about overriding onCreate() and then go to your AndroidManifest.
You should have an <application> with values such as android:label or android:theme. Just add android:name=".MyApplication" there and you're ready to go.
Have in mind that if your package is com.example.test, MyApplication has to be there. If you want to put MyApplication wherever else, you must point to where it is.
For example, if your package is com.example.test and MyApplication is in com.example.test.application, you must add android:name=".application.MyApplication to your manifest. I strongly reccomend you to use a package just for your Application, as it atomizes your project and makes it far more manageable and mantainable.
Application is used because of the manifest. In the manifest, it is just to add this to the application tag(with all activities inside):
android:name=".MyApplication"
Ex:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:name=".MyApplication"
android:theme="#style/AppTheme" >
Because of the easy initialization(as it is automatically initialized by the Android System on launch) it will never not report. It can crash instantly on startup and still report. So it is a really smart setup.
My application class looks like this:
#ReportsCrashes(
formUri = "https://backend.com",
customReportContent = { /* */ReportField.APP_VERSION_NAME, ReportField.PACKAGE_NAME,ReportField.ANDROID_VERSION, ReportField.PHONE_MODEL,ReportField.LOGCAT },
mode = ReportingInteractionMode.TOAST,
resToastText = R.string.crash_toast_text
)
public class ACRAHandler extends Application {
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
final ACRAConfiguration config = new ConfigurationBuilder(this)
.build();
// Initialise ACRA
ACRA.init(this, config);
}
}
If you for an instance are using Firebase, you can use both together in the same application-extending class without any issues. I tried it myself and it worked, no problems with error reporting or Firebase.
Additionally, the new links for ACRA is now on Github: https://github.com/ACRA/acra/wiki/BasicSetup
I answered this because it was so long ago the answers came and it needs an update
An application sub class is required to maintain a global application state, it is not necessary for every app to sub class it. If you app does not have one yet, you can create it.
Example:
/* do ACRA imports */
#ReportsCrashes(formKey = "x-x-x-x-x-x")
public class YourApplication extends Application{
public void onCreate(){
ACRA.init(this);
super.onCreate();
}
}
you should also declare in the manifest file as stated in the tutorial.

Remove from launcher BUT keep enabled / startable

i tried coding it, i tried solving it with google and stackoverflow, nothing found :=) so hopefully someone else has a better idea, im not sure if i get everything right:
i have 2 applications: ad (main app) / adfree-pro (just license starts ad app without ads ;P)
so the problem is, i want to have a pro version (with pro icon) in the launcher, which starts the normal-ad app, which is (the normal ad-app) not in the launcher.
i tried removing the ad-app from the launcher (which due to my research should JUST remove it from the launcher)
pkgMgr.setComponentEnabledSetting(new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".Main"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
which results to: the icons in the launcher are correct ;) BUT the application can't be found on the phone, launched, started, even not with a launcher pro activity shortcut. it seems to be there (shortcuts can be created) but i crashes with an activity exception when i try to launch it.
02-18 14:38:59.237: ERROR/AndroidRuntime(9941): Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {PACKAGE_NAME/PACKAGE_NAME.Main}; have you declared this activity in your AndroidManifest.xml?
which doesnt seem to belong (the error message)
it looks like there has happened more to the application than just simply removed the entry in the launcher.
thanks a lot guys,
every workaround for this situation appreciated :)
best regards :)
You can't have app installed and hide it's launcher icon. The way I'm addressing it with my application which works similar to yours that I don't try to fight icons but instead the app can be launched using ether icon. Obviously you don't have to do in the main (free) app and the code that launches app from your pro icon will look something like the following:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
// check if main app is installed. If yes then start it
if (appExists()) {
Log.d(TAG, "Started main app from Pro");
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("myapp://com.myapp.main"));
startActivity(intent);
finish();
} else {
// display view with link back to Market
onAppNotExists();
}
}
It's up to you to implement appExists() which is probably some sort of license check
Of course, alternatively you can develop your app's common code as library project and then distribute it in 2 flavors without duplicating the code
BUT the application can't be found on the phone, launched, started,
even not with a launcher pro activity shortcut.
Not application, but activity.
So, if your LAUNCHER activity is BaseActivity, you may create something like BaseFakeActivity (don't forget to set it as LAUNCHER in your manifest instead of your BaseActivity) and which only function is to start your BaseActivity and then finish() itself.
Now you may hide your BaseFakeActivity but you'll still be possible to interact with your BaseActivity.
P.S.: Don't forget to test your app's behaviour after doing things this way ;)

Categories

Resources