Starting Activity from Android-Library-Project - android

after a long search I couldn't find any appropriate solution.
I have a Android-Library Project with nearly all code for the application. From the main activity in the library project I start an Intent to en explicit Activity A. In my derived Project, which uses the library Project, I have extended this Activity A and added some new code. The problem is that the the Superclass of Activity A will respond and not the derived class.
In the manifest of the new Project which uses the library project I have declared the new Activity with the new package.
Here is the Intent call from the Library Project:
Intent i = new Intent(getApplicationContext(), AndroidActivity.class);
startActivity(i);
Here is the derived AndroidActivity class:
public class AndroidActivity extends de.app.library.activities.AndroidActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
I am not able to get to the onCreate Method
The Manifest from the Library Project:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.app.library"
android:versionName="1.0"
android:versionCode="1">
<uses-sdk android:minSdkVersion="4" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name">
<activity android:name=".activities.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activities.AndroidActivity" android:label="#string/act_android" />
</application>
And here the Manifest from the new Project:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.app.free"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name">
<activity android:name="de.app.library.activities.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activities.LernenActivity" android:label="#string/act_lernen" />
So I have:
de.app.library.activities.AndroidActivity and
de.app.free.activities.AndroidActivity
I didn't want to do that much changes to the library project beacuase a third project should use the existing code with the untouched AndroidActivity
ALl other things works fine for me. For example the changed layouts are used from the new project.
How can I handle that problem? Maybe changes in the Manifest from the new project in which I declare, that the new activity should be called instead of the superclass?
Thanks in advance!

When you do this in your library project
Intent i = new Intent(getApplicationContext(), AndroidActivity.class);
AndroidActivity refers to the library project's AndroidActivity: A project doesn't know about other external projects unless you include them as a library. Just check your imports, you are importing AndroidActivity, and instructing Android to run it.
Which by the way it's obvious, it would be a bad design pattern if the library project had to know about the derived projects
An easy solution is to override the activity launching on the derived project, something like this:
Libary project Activity:
public void runMyActivity() {
Intent i = new Intent(getApplicationContext(), AndroidActivity.class);
// You are on the library project, so you can refer to the activities created in it.
// the only AndroidActivity known here is the library project's
.
.
}
Your derived project's Activity:
#Override
public void runMyActivity() {
// You are now on the derived project, so you can refer to
// the activities created in it, and also to the library project's. You
// just import the package name of the desired activity or use fully qualified
// names
Intent i1 = new Intent(getApplicationContext(), AndroidActivity.class);
// this one will use the activity in the imports
Intent i2 = new Intent(getApplicationContext(), de.app.libarary.AndroidActivity.class);
// use the activity from the library project
Intent i3 = new Intent(getApplicationContext(), de.app.free.AndroidActivity.class);
// use the activity from the derived project
.
.
}
So when you call runMyActivity() from anywhere, it will execute the overriden function ( provided the startup activity extends the library project's activity and overrides that method). And in the overriden function context, AndroidActivity.class will be your derived activity (or the other one, you can import any of them because here you have access to the derived activities AND the library project's).

In your new project, you could use a different name, instead of AndroidActivity. If you don't want to do that, the second AndroidActivity's fully qualified name in the manifest file should solve your problem. You are perhaps messing up with packages a little bit, somewhere.
activity android:name="de.app.library.activities.AndroidActivity"
should be
activity android:name="de.app.free.activities.AndroidActivity"
I meant, the AndroidActivity. In some way, your are picking up the wrong activity class from the wrong package.

Related

Does Android need a default layout file called activity_main.xml

I'm an Android noob and I'm having difficulty finding out something basic about Android.
I currently have an activity_main.xml file.
I want to use this layout when I first start the Android emulator, using Android Studio
Does Android look for a file activity_main.xml and use it as the default layout?
Here's my AndroidManifest.xml:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
So I understand that this specifies that my .MainActivity will respond to an action.MAIN intent call. What I don't know is what the action.MAIN intent call actually is, and how my activity_main.xml relates to this.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Can anyone provide an explanation or a link to a good primer that explains these basic concepts?
From manifest :
<action android:name="android.intent.action.MAIN" />
Means this activity is the entry point of the application. In your case, the MainActivity starts.
The MainActivity sets up the layout for itself - the line responsible is
setContentView(R.layout.activity_main);
Where it looks for layout file activity_main.xml. This is just the naming convention - feel free to rename the layout file and call the new one from setContentView. It's not required to be called activity_main

Reorganizing activities in different folders

I want to change the structure of my android application to have the activites in a subfolder called activities. So, my code structure will become
com.example.myapp.activities.MainActivity
and all the activities will reside within com.example.myapp.activities
How do I achieve this ? Also, What changes will have to be made in the manifest for this to work ? How will I access other activity classes from within other activities ?
<activity
android:name=".activities.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
EDIT : I achieved this using dragging and dropping the activities in the folders but now I am getting this error on setContentView(R.layout.main); : main cannot be resolved or is not a
field
If you organize all activities in same packages, then you have to define the activity without package declaration in Manifest file, example
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp.activities"
android:versionCode="1"
android:versionName="1.0" >
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:name=".WorldClockApplication"
<activity
android:name=".WorldClockHomeActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AddLocationActivity"/>
<activity android:name=".EditPreference"/>
</application>
</manifest>
Then you should call that activity inside another activity using intent. Consider I'm calling WorldClockHomeActivity from WorldClockApplication activity as follows:
Intent myIntent=new Intent(WorldClockApplication.this,WorldClockHomeActivity.class);
startActivity(myIntent);
Then do clean, refresh your project you wont get error in your project. If get error on
setContentView(R.layout.main);
that means you have problem in res/strings or res/layout or res/drawable folders not in manifest file
If you are using Eclipse create a new packet in your project and drag and drop your activities files in there. Eclipse will take care of all the necessary changes.
The changes are in your directory structure and in the manifest as you have posted in the question.
Activities can be launched (or new Intents can be sent to them) as usual through Intent(context, YourActivity.class);
I wouldn't move the activities though, rather I'd organize other Java classes in separate packages.

Android error "unable to find explicit activity class"

I have an android project with several packages. The structure of the packages in this case is com.WAPP.SetLocation is the package that contains the activity I want to run.
In my manifest, com.WAPP is considered the base package:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.WAPP"
android:versionCode="1"
android:versionName="1.0">
My activities are declared in my manifest as:
<activity android:name=".mainScreenActivity"></activity>
<activity android:name=".SetLocation.setLocationActivity"></activity>
The mainScreen activity displays fine, since it is inside the com.WAPP package. But when I try to run the setLocationActivity, I get the unable to find explicit class error. Here is how I have the intent parameters:
Intent i = new Intent();
i.setClassName("com.WAPP.SetLocation",
"com.WAPP.SetLocation.setLocationActivity");
startActivity(i);
The first parameter is application package not the package where the activity is.
You can invoke the Activity like this.
Intent i = new Intent();
i.setClassName("com.WAPP",
"com.WAPP.SetLocation.setLocationActivity");
startActivity(i);
It is preferred as SYLARRR suggested to have Android automatically figure that out for you. Hence the call as..
startActivity(new Intent(this, setLocationActivity.class));
It's recommended per java standards to have the package name all lower-cased and the class name as CamelCased.
If the new activity not in the same packet with MainActivity(you call from here?), try declare on manifest
<activity android:name="com.WAPP.SetLocation.setLocationActivity"></activity>
and in the caller
Intent intent = new Intent(this, setLocationActivity.class);
startActivity(intent);
Hope this helps!
In additional to the above answers make sure that your activities are declared inside application in manifest
<application
android:allowBackup="true"
android:label="#string/app_name"
android:supportsRtl="true">
<activity android:name=".mainScreenActivity"></activity>
<activity android:name=".SetLocation.setLocationActivity"></activity>
</application>
If i'm not mistaken, the i.setClassName("com.WAPP.SetLocation","com.WAPP.SetLocation.setLocationActivity"); should be i.setClassName(getBaseContext(),"setLocationActivity"); Reference
Also try this syntax:
startActivity(new Intent(MyActivity.this, setLocationActivity.class));
and try removing the starting dot from:
<activity android:name=".SetLocation.setLocationActivity"></activity>
Do it by this way:
Intent intent = new Intent();
intent.setComponent(
new ComponentName("com.WAPP", "com.WAPP.SetLocation.setLocationActivity"));
startActivity(i);
you should class ad to manifest.xml
for example of manifest.xml
in this example, i added SecondActivity.class
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.MyApplication">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
In Xamarin Android, make sure that your Activity class has an Activity attribute
[Activity(Theme = "#style/MyTheme")]
public class MyActivity : ActivityBase
{
...
}
With that you are making sure that your activity is registered in AndroidManifest.xml
I had the same kind of issue in the project . It wasted me almost a full day . i tried all the solutions that are mentioned above , but none of the solutions worked for me .
After all the hard work i just "Rebuild" the project and "clean" The project and it worked perfectly .
Note:
Before going through all the process u just needed to have a try to these options.
First of all, make sure that you have created activity and not the class. And, if it is activity then go to the manifest.xml file and look at the path of that particular file.
This worked for me absolutely well!!
https://forums.xamarin.com/discussion/104102/android-content-activitynotfoundexception-unable-to-find-explicit-activity-class
this is for reference
in your manifest you declared it as
.SetLoction.setLocationActivity
but
the package name is com.WAPP.SetLocation
so you need to prefix that again.
Intent i = new Intent();
i.setClassName("com.WAPP.SetLocation",
"com.WAPP.SetLocation.SetLocation.setLocationActivity");
startActivity(i);
This might be due to not registering your next activity XML file in the manifest. Register your next activity XML file in the AndroidManifest.xml file
<activity android:name=".NextActivity" />
Hope it helps.
Thia might be problem if ImageView is used :(
Intent intent = new Intent(context,ImageView.class);
intent.putExtra("imageurl",clients_document_return.getUrl());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
v.getContext().startActivity(intent);
and your class name might me Imageview.class
so first check all small capital in class name
Thanks :)

Android: Can't find activity in the Manifest, but it IS there?

And i can't figure out why! I checked logcat and i saw that the reason it crashed was because it isn't finding the Activity in the manifest file for some unknown reason.
I've looked at similar threads but none of the answers seem to work for me.
Here's the code where i start the activity:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
Intent ntnt = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(ntnt);
}
}
And the manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.jbhalmstad.ndroid"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SettingsActivity"></activity>
</application>
</manifest>
As you can see i declared the SettingsActivity that i'm trying to start, at the bottom of the Manifest, inside of the tag.
I might be blind, but i can't find anything wrong. Can you?
Let me know if you need more source, but the SettingsActivity should be irrelevant because it doesn't get that var when i run the program.
Source code
If you want to take a closer look, here's the entire source code.
http://www.speedyshare.com/files/30343046/project.zip
The problem is in your SettingsActivity
when you are using PreferenceActivity you use
addPreferencesFromResource(R.layout.settings);
to set contents.
but you are using
setContentView(R.layout.settings);
Could be package name mismatch. What Java package is the activity class in? Must match the one in the manifest, i. e. se.jbhalmstad.ndroid. Or provide full class name in the android:name attribute.
EDIT: I have a working example, and the <activity> element for my Preferences activity looks slightly different:
<activity android:name="Prefs"/>
No dot before Prefs.
Also, check if the SettingsActivity class is public. You never showed it to us.
i think you dont need to add the name of the package to your acitivity name , you can just add your activity SettingActivity like this :
<activity android:name="SettingsActivity" />
because your activity is in the same package that is declared on the manifest :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.jbhalmstad.ndroid"...
let me know if it helps
Be sure that Manifest intent on the right activity and not just the basic Java / Kotlin class file
New -> Activity -> Empty Activity instead of New -> Class/file
or
Use setContentView(R.layout.yours_activity_class_here); OnCreate

Unable to start Service Intent

I have a service class. I have exported this class to jar and I have embed the jar in my client app.
When needed, I call the service class. When I try to do this, I get the following error:
Unable to start service Intent {comp={com.sample.service/com.sample.service.serviceClass}} : not found
I have other class apart from the service class, which I am able to access (create object of that class) which are inside the same jar.
I feel I have missed out some thing in my configuration or manifest or so.
Please help me identifying the same. My code is below:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent () ;
intent.setClassName("com.sample.service" ,"com.sample.service.serviceClass") ;
this.startService(intent) ; // when I call this line I get the message...
// binding other process continue here
}
Client manifest.xml
<service android:name="com.sample.service.serviceClass"
android:exported="true" android:label="#string/app_name"
android:process=":remote">
<intent-filter><action android:name="com.sample.service.serviceClass"></action>
</intent-filter>
</service>
For anyone else coming across this thread I had this issue and was pulling my hair out.
I had the service declaration OUTSIDE of the '< application>' end tag DUH!
RIGHT:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...>
...
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity ...>
...
</activity>
<service android:name=".Service"/>
<receiver android:name=".Receiver">
<intent-filter>
...
</intent-filter>
</receiver>
</application>
<uses-permission android:name="..." />
WRONG but still compiles without errors:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...>
...
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity ...>
...
</activity>
</application>
<service android:name=".Service"/>
<receiver android:name=".Receiver">
<intent-filter>
...
</intent-filter>
</receiver>
<uses-permission android:name="..." />
First, you do not need android:process=":remote", so please remove it, since all it will do is take up extra RAM for no benefit.
Second, since the <service> element contains an action string, use it:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent=new Intent("com.sample.service.serviceClass");
this.startService(intent);
}
1) check if service declaration in manifest is nested in application tag
<application>
<service android:name="" />
</application>
2) check if your service.java is in the same package or diff package as the activity
<application>
<!-- service.java exists in diff package -->
<service android:name="com.package.helper.service" />
</application>
<application>
<!-- service.java exists in same package -->
<service android:name=".service" />
</application>
I hope I can help someone with this info as well:
I moved my service class into another package and I fixed the references. The project was perfectly fine, BUT the service class could not be found by the activity.
By watching the log in logcat I noticed the warning about the issue: the activity could not find the service class, but the funny thing was that the package was incorrect, it contained a "/" char. The compiler was looking for
com.something./service.MyService
instead of
com.something.service.MyService
I moved the service class out from the package and back in and everything worked just fine.
In my case the 1 MB maximum cap for data transport by Intent.
I'll just use Cache or Storage.
I've found the same problem. I lost almost a day trying to start a service from OnClickListener method - outside the onCreate and after 1 day, I still failed!!!! Very frustrating!
I was looking at the sample example RemoteServiceController. Theirs works, but my implementation does not work!
The only way that was working for me, was from inside onCreate method. None of the other variants worked and believe me I've tried them all.
Conclusion:
If you put your service class in different package than the mainActivity, I'll get all kind of errors
Also the one "/" couldn't find path to the service, tried starting with Intent(package,className) and nothing , also other type of Intent starting
I moved the service class in the same package of the activity
Final form that works
Hopefully this helps someone by defining the listerners onClick inside the onCreate method like this:
public void onCreate() {
//some code......
Button btnStartSrv = (Button)findViewById(R.id.btnStartService);
Button btnStopSrv = (Button)findViewById(R.id.btnStopService);
btnStartSrv.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
startService(new Intent("RM_SRV_AIDL"));
}
});
btnStopSrv.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
stopService(new Intent("RM_SRV_AIDL"));
}
});
} // end onCreate
Also very important for the Manifest file, be sure that service is child of application:
<application ... >
<activity ... >
...
</activity>
<service
android:name="com.mainActivity.MyRemoteGPSService"
android:label="GPSService"
android:process=":remote">
<intent-filter>
<action android:name="RM_SRV_AIDL" />
</intent-filter>
</service>
</application>

Categories

Resources