ActivityNotFoundException invoking an inner-class activity - android

I have a non-Activity class (let's call it "NonActivity") that needs to post a message and get user feedback. I have a message activity (MsgActivity) class to do this. But only Activity classes can call startActivityForResult() so I made an inner helper class in NoActivity:
// just to provide an Activity to launch MsgActivity
class ActivityMsgClass extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent iMA = new Intent(this, MsgActivity.class);
iMA.putExtra("MsgText", mParams[0]);
...blah blah ...
iMA.putExtra("ButtonCode", iBtns);
startActivityForResult(iMA,3);
}
}
My Activity class is declared in the Manifest thusly:
<activity android:name="ActivityMsgClass"
android:configChanges="orientation"
android:screenOrientation="portrait"
android:launchMode="singleInstance"></activity>
But when I try to invoke it . . .
Intent i = new Intent(ctx, ActivityMsgClass.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(i);
... I get an ActivityNotFound exception. I've also tried it without the FLAG_ACTIVITY_NEW_TASK, and I've also tried qualifying the name in the manifest, e.g.,
<activity android:name=".NoActivity.ActivityMsgClass"
. . . to no avail. What am I doing wrong?
Thanks in advance.

The technical solution is to specify the fully qualified activity path in the manifest.
The actual solution is to avoid doing this. Let activity be a public class, and not an inner class, this is just not good practice.

In your manifeast file change like below and try...
<activity android:name=".ActivityMsgClass"
android:configChanges="orientation"
android:screenOrientation="portrait"
android:launchMode="singleInstance"></activity>
<activity android:name=".MsgActivity"
android:configChanges="orientation"
android:screenOrientation="portrait"
android:launchMode="singleInstance"></activity>

your activity name declaration should start with a period. declare it this way.
<activity android:name=".ActivityMsgClass"
android:configChanges="orientation"
android:screenOrientation="portrait"
android:launchMode="singleInstance"></activity>
also make sure that the activity MsgActivity is also declared in the manifest.

Related

Android: make sure that specific activity retains in backstack

I want to make so the every activity launches with only one main activity in the backstack, so I always can return to the main activity with back button as for example (for starting activities I use startActivity()):
Main Activity - Activity1 (back pressed) returns to Main
Activity
Main Activity - Activity1 - Activity2 (back pressed) also
returns to Main Activity
It looks like I need to use FLAG_ACTIVITY_CLEAR_TASK flag on launching every new activity, but it clears Main Activity either. I've tried FLAG_ACTIVITY_CLEAR_TOP works fine in the 1st case, but not in the 2nd.
If someone has the same problem, please help. Any thoughts appreciated! Thanks!
My main activity:
<activity
android:name=".activity.main.MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTop">
<meta-data
android:name="android.app.default_searchable"
android:value=".activity.search.SearchActivity" />
</activity>
Set FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY flag while firing the intent of Main Activity in onBackPressed().
Just make sure that you call finish() when Activity1 starts Activity2. This will ensure that your task stack looks like this: MainActivity->Activity2.
As #EmmanuelMtali mentioned, I used parent activity for this reason.
For activity different from Main, I set meta-data (and android:parentActivityName, API > 16) as follows:
<activity
android:name=".activity.user.LoginActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTop"
android:parentActivityName=".activity.main.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.main.MainActivity" />
</activity>
When I need to start new activity I use array of intents and startActivities() method:
public static Intent[] createIntentsWithMainActivityInStack(Context context, Intent topMostIntent) {
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);
topMostIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
Intent[] intents =
taskStackBuilder
.addNextIntentWithParentStack(topMostIntent)
.getIntents();
return intents; }
and
Intent[] intents = createIntentsWithMainActivityInStack(context, new Intent(context, LoginActivity.class));
startActivities(intents);
Try this in every activity so that when you back press main activity opens:
#Override
public void onBackPressed()
{
super.onBackPressed();
Intent intent = new Intent(ACTIVITYTHREE.this,MAINACTIVITY.class);
startActivity(intent);
}

How to access the Class of the Activity defined in parentActivityName

For every activity which has a logical parent we define that parent Activity in the Manifest like so:
<activity
android:name=".ui.activity.MyActivity"
android:label="#string/activity_title"
android:parentActivityName=".ui.activity.ParentActivity"
android:theme="#style/My.Theme" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.activity.ParentActivity" />
</activity>
Is there a way to access the Class referenced in either #parentActivityName or meta-data#value in MyActivity?
(Please note that I don't want to access the parent Activity instance, just the Class)
The reason is that for tracking purposes we want to generate a path-like String for each Activity. In this case this String would be /parent_activity/my_activity – and since the hierachy is already defined in the Manifest, best case would be to access it there then to define it twice.
Thank you for your help!
Maybe it will help you NavUtils.getParentActivityName(childActivityInstance)
You could always go with the easy way: Pass the parent activity name in intent extras as string, in ParentActivity
Intent intent = new Intent(ParentActivity.this, ChildActivity.class);
intent.putExtra("parent_activity_name", "ParentActivity");
...
startActivity(intent);
And then get it in the ChildActivity activity
Intent intent = getIntent();
String parentName = intent.getStringExtra("parent_activity_name");
Not sure if there is any other more elegant solution.

Can multiple Activity declarations share the same class name?

For example
<manifest>
<activity android:label="MyActivity1" android:name=".MyClass">
</activity>
<activity android:label="MyActivity2" android:name=".MyClass">
</activity>
</manifest>
Yes and no. When you prepend the Activity name with a ., it looks at the Manifest's default package to get the whole class path, such as com.example.android.MyClass. Thus, if instead you have one .MyClass and another com.example.android.other.MyClass, then this should work.
<manifest>
<package="com.example.android">
<activity android:label="MyActivity1" android:name=".MyClass">
</activity>
<activity android:label="MyActivity2" android:name="com.example.android.other.MyClass">
</activity>
</manifest>
I'm not 100% sure if this is possible, but perhaps there is a better way to go about this. If you need the same activity you can call it in both situations like you normally would but pass in data during the call as well. In your MyClass you can read the data and decide how to handle it.
Example:
//Activity 1
Intent i = new Intent(this, MyActivity.class);
i.putExtra("open", "activity1data");
startActivity(i);
//Activity 2
Intent i = new Intent(this, MyActivity.class);
i.putExtra("open", "activity2data");
startActivity(i);
And in MyActivity do something like this in onCreate()
Intent intent = getIntent();
Bundle extras = intent.getExtras();
String action = intent.getAction();
if(extras.containsKey("open")){
if(extras.getString("open").equals("activity1data")){
//DO activity 1 stuff
}
}
This is a pretty rough example, you could use ints and switch on those etc. But the real goal is to let one activity handle a variety of cases. This seems to be what you want since your going to use the same class anyway.

Android - Vertical layout only

How do I make sure my app is only for vertical layout?
I have tried android:screenOrientation="portrait" but that doesn't seem to do the trick.
You need to add to all your activity not for one only. I think you understood that setting is per application wide, but it isn't.
<activity android:name=".MyActivity"
android:label="My Activity"
android:screenOrientation="portrait">
Add the declaration to the activity tag in AndroidManifest for every Activity you want to be portrait-only.
If you want some group of your activities to be locked on PORTRAIT mode only, than you can choose the next way:
public abstract class BasePortraitActivity extends Activity {
#Override
protected final void onCreate(Bundle state) {
super.onCreate(state);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
performOnCreate(state);
}
protected abstract void performOnCreate(Bundle state);
}
And than just extend BasePortraitActivity where you need it. Or just add setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); to YourActivity.onCreate().
you have to change into AndroidManifest.xml.
for each activity you have to insert:
android:configChanges = "orientation"
android:screenOrientation = "portrait"
for e.g.:
<activity android:name=".YourActivityName"
android:label="#string/app_name"
android:configChanges = "orientation"
android:screenOrientation = "portrait">
This works for a single activity.. But there seems no application wide setting there.
In your manifest under activity add this :
<activity
android:name="com.zeus.MyProject"
android:screenOrientation="portrait"
>
Activity is to block just in case want to block all and only repeat this line of code in their Activitys.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// Here, talk to the java does not want that the user can rotate their activity.
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
or open your "AndroidManisfest.xml" and add the rows for the portrait mode as shown below.
android:configChanges="orientation"
android:screenOrientation="portrait">
Add android:configChanges="keyboardHidden|orientation" to the activity.
Put this attribute in layout root:
android:orientation="vertical"
It may help.
Just to confirm Pentium10's answer.
I was having a similar issue and adding android:screenOrientation="portrait" to the activity tag.
Did the trick for me.

Using Intent from non-activity class

I have three classes one main-activity(named MainMap), one non-activity class(named MyItemizedOverlay), and one activity class(named AudioStream).
I want to start AudioStream activity from non-activity class but i don't know how to.
i tried
this is in third class(called MyItemizedOverlay):
Intent myIntentA = new Intent(MainMap.this, AudioStream.class);
myIntentA.putExtra(AUDIO_STREAM,AUDIO_STREAM_URL);
MojProg.this.startActivity(myIntentA);
but it doesn't work, says: No enclosing instance of the type MainMap is accessible in scope
What should i do? What shoul i write instead of MainMap.this?
This isn't so much an Android question as it is a Java question. Unless you were to make "MyItemizedOverlay" an inner class of "MainMap" (see http://forums.sun.com/thread.jspa?threadID=690545), what you really need is for MyItemizedOverlay to store an internal reference to the MainMap object that it wants to use for the inent.
Regards,
Mark
Intent myIntentA = new Intent(MainMap.this, AudioStream.class);
myIntentA.putExtra(AUDIO_STREAM,AUDIO_STREAM_URL);
MojProg.this.startActivity(myIntentA);
This won't work. Because "this" means "this class". You cannot use it on another class (Yes, you can, but there are different ways for it. Please study on "this" at forums, this site or oracle web site.). It is the reason of that warning.
Well it looks like your question is "How can i pull the context to a non-activity class?". (First parameter of Intent() is Context).
To do this you can create a Context instant in your Main Activity and assign your base context to it like:
static Context context;
....
context = this.getBaseContext();
Don't forget that was your Main Activity. Then in your non-activity class, you can pull this context and use it with intent like:
Context context;
Intent intent;
....Constructor:
context = MainActivity.context;
intent = new Intent(context, YourSecondActivity.class); // you have to declare your second activity in the AndroidManifest.xml
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // this is required to call "Intent()" in a non-activity class.
//And then you can call the method anywhere you like (in this class of course)
context.startActivity(intent);
Ok. You are ready to go after one more step. In AndroidManifest.xml, declare your second activity like first one like;
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="landscape"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".YourSecondActivity"
android:label="#string/app_name"
android:screenOrientation="landscape"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
You are ready now. But a last warning, dont forget to dispose your activity before opening another to avoid lagging.
Have fun.

Categories

Resources