I'm trying to implement a fragment, and am using the Android example as a guide.
In the onActivityCreated() method of the TitlesFragment class, there is this line:
View detailsFrame = getActivity().findViewById(R.id.details);
When I try to include a similar line in my code, I get the error that the 'getActivity' symbol can't be resolved.
I've tried importing everything that their example imports, but it doesn't seem to make any difference. Nor can I find any documentation anywhere that helps me know how to make this accessible.
So, what's the secret on being able to use getActivity?
make sure your class extends Fragment or ListFragment, as shown in the example
public static class TitlesFragment extends ListFragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
View detailsFrame = getActivity().findViewById(R.id.details);
...
}
}
Related
I'm getting strange error while trying to use Toothpick DI in a fragment:
toothpick.registries.NoFactoryFoundException: No factory could be found for class android.app.Application. Check that the class has either a #Inject annotated constructor or contains #Inject annotated members. If using Registries, check that they are properly setup with annotation processor arguments.
My fragment:
public class ApplicationMenu extends SidebarFragment {
#Inject ApplicationsService applicationsService;
#Inject SectionsService sectionsService;
private EventBus bus = EventBus.getDefault();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toothpick.inject(this, Toothpick.openScope(LauncherActivity.class)); // <- Erroring here
}
...
}
Activity:
public class LauncherActivity extends SidebarActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
Scope scope = Toothpick.openScopes(LauncherApplication.class, LauncherActivity.class);
scope.bindScopeAnnotation(LauncherActivitySingleton.class);
scope.installModules(new LauncherActivityModule(this));
super.onCreate(savedInstanceState);
Toothpick.inject(this, scope);
setContentView(R.layout.activity_launcher);
ButterKnife.bind(this);
...
}
...
}
The strange thing is I get the error only in fragments, all injections in other places (ViewRenderers, Adapters, Services etc) work fine with no problem
I figured that out. I close the application scope in one of my services by mistake. That service was using in fragments which cases the error.
Unfortunately the error message does not provide any useful information and the only way to find the problem is to analyze and debug all the code.
So using the toothpick di you have to be very careful with scope life-cycle.
I used the anko library to create a login view.
class SingInView : AnkoComponent<SingleInActivity> {
override fun createView(ui: AnkoContext<SingleInActivity>) = with(ui) {
verticalLayout {
lparams(width = matchParent, height = matchParent)
textView("Member Login")
editText {
hint = "E-mail"
}
editText {
hint = "PassWord"
}
button("Login")
}
}
}
and SingleInActivity.kt
class SingleInActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState)
SingInView().setContentView(this)
and MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startActivity(new Intent(this, SingInView.class));
finish();
}
}
current My app MainActivity -> SingleInActivity -> SingInView .
of course it can be made simply.
but there is a condition
1. MainActivity is java (kotlin prohibition)
2. use only MainActivity, SingInView.
How to solve this problem?
How to call the Anko class directly from a Java class
If you dig through the Anko source code you'll quickly find this:
interface AnkoComponent<in T> {
fun createView(ui: AnkoContext<T>): View
}
And from the wiki (where MyActivityUI is the component): MyActivityUI().setContentView(this). Now, the AnkoComponent is just an interface and the setContentView method is an extension function that returns createView.
Anyways, the setContentView extension function passes the last variable of the AnkoContextImpl as true. The last variable is whether or not to actually set the content view, which is the reason the activity is passed in the first place.
TL;DR (and possibly more sensible summary of my point):
The component is not an Activity
The setContentView method is not a replacement for setContentView in an Activity; just a wrapper for it.
And since it isn't an activity, you can't use an intent into it. And, as a result of that, you cannot use it standalone. You need an activity. Now, you can of course use the regular approach, but there's also another way. Since the AnkoComponent itself doesn't have any fields, it can be serialized without much trouble. Just to clarify: some fields can be serialized even if it isn't serializable (all though some classes like Context cannot be serialized). Anyways, you create an activity:
class AnkoComponentActivity : AppCompatActivity(){//Can be a regular Activity too
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
val component = intent.getSerializableExtra("uiComponent") as AnkoComponent<AnkoComponentActivity>//The type has to match this activity, or setContentView won't allow passing `this`
component.setContentView(this)//The context of the activity doesn't get passed until this point, which enables the use of this system.
}
}
Or it's equivalent in Java:
public class AnkoComponentActivity extends AppCompatActivity {
public void onCreate(Bundle sis){
super.onCreate(sis);
AnkoComponent<AnkoComponentActivity> component = (AnkoComponent<AnkoComponentActivity>) getIntent().getSerializableExtra("uiComponent");
org.jetbrains.anko.AnkoContextKt.setContentView(component, this);//For reference, this is how you call Kotlin extension functions from Java
}
}
Note that any UI component sent to this class has to be declared with <AnkoComponentActivity>. In addition, the components have to implement Serializable. Otherwise they can't be passed through the Bundle. Alternatively, you can use ints or Strings as identifiers and use the value to pick which AnkoComponent to show.
All though, the absolutely easiest way is just creating one activity per component.
TL;DR: AnkoComponent is not an Activity, meaning you can't use intents into it. You have to use an Activity, but using Serializable enables you to pass the component through a bundle to an Activity made for manual creation of multiple AnkoComponents without specifying specific types.
I am using a webview and want to load a JScode to show in that webview. However I am getting a problem above API16.It never loads the JS page. It gives me an error:
Here is my code:
#JavascriptInterface
public void loadWebviewUrl(){
Map <String, String> extraEncryptionHeaders = new HashMap<String, String>();
extraEncryptionHeaders.put("X-APP-DEVICETYPE", "ANDROID");
appVersionname=CommonMethods.getAppVersion(WebPayUActivity.this);
extraEncryptionHeaders.put("X-APP-APPVERSIONNAME", appVersionname);
extraEncryptionHeaders.put("X-DEVICE", Constant.ANDROIDID);
extraEncryptionHeaders.put(Constant.HEADER_SECURITY_KEY, Constant.SECURITY_HASH_VALUE);
mWebView.loadUrl(mPayUrl, extraEncryptionHeaders);
**//getting error in this line that has been mentioned above**
mWebView.addJavascriptInterface(new Wscript(WebPayUActivity.this),
"Android");
screenDpi=CommonMethods.getResoltuion(this);
mWebView.setWebViewClient(new MyWebViewClient(this));
mImageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
customAlertDialog();
}
});
mWebView.setWebChromeClient(new WebChromeClient());
}
After reading the solutions at different sites I got to know to add annotation. But after writing the annotation, the error is still the same.
Can anyone please check and help me back
Thanks
You must add
#SuppressLint("JavascriptInterface")
to the your public methods which you used your webView object.
You must add #JavascriptInterface to the public methods of your Wscript class.
If your code is obscured with proguard, you should also add -keepattributes *Annotation* to the configuration file of proguard.
Here is the parent class:
public class void ParentClass () extends Activity {
private ListView _listView;
#Override
protected onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_parent);
_listView = (ListView) getViewById(R.id.list_view);
ChildClass cc = new ChildClass();
}
protected void SetScroll() {
try {
_listView.setFastScrollEnabled(false);
} catch (Exception e) {
e.printStackTrace();
}
}
Here is the child class:
private void ChildClass extends ParentClass () {
public ChildClass() {
SetScroll();
}
}
Forgive me with regards to the syntax as I'm typing this from memory. The problem with these classes is that the SetScroll function called from the CallParent function does not work because it is unable to find the right _listView reference (it becomes null). What should I do to make it work correctly? Bear in mind that this is just an example.
But the view is getting null is because you are extending an activity class and before using its view you need to call the onCreate and set the view (if child activity needs new one). But for that you will have to follow the complete flow of the lifecycle. This will help you in extending an activity class. android how to create my own Activity and extend it?
Call parent class activity like this (Just for info). With your code it wont work. You need to correct your code first. See the link I have posted.
super.SetScroll();
In my Android app, I want to use a single variable for the log name in multiple files. At the moment, I'm specifying it separately in each file, e.g.
public final String LOG_NAME = "LogName";
Log.d(LOG_NAME, "Logged output);
I've tried this:
public final String LOG_NAME = (String) getText(R.string.app_name_nospaces);
And while this works in generally most of my files, Eclipse complains about one of them:
The method getText(int) is undefined
for the type DatabaseManager
I've made sure I'm definitely importing android.content.Context in that file. If I tell it exactly where to find getText:
Multiple markers at this line
- Cannot make a static reference to the non-static method getText(int)
from the type Context
- The method getText(int) is undefined for the type DatabaseManager
I'm sure I've committed a glaringly obvious n00b error, but I just can't see it! Thanks for all help: if any other code snippets would help, let me know.
That's because getText is a method of Context. It does not matter if you import the Context class; what matters is that you invoke that method from a Context (for instance, the Activity class is a Context (it inherits Context)).
In that case, what I'd recommend, is creating a Application class that returns the context you want. Here I explain how to do it. After that you can do something like:
public final String LOG_NAME = (String) App.getContext().getText(R.string.app_name_nospaces);
Depending on what sort of 'files' you are using, you can define a TAG that is used.
For example, when I create an app, I like to create a base class for my Activity classes...
Suppose my app is called 'Wibble', and my package is com.mydomain.Wibble...I create my base Activity like so...
package com.mydomain.Wibble
public class WibbleActivity extends Activity {
final protected String TAG = this.getClass().getName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// I'll explain how this next line works later
android.util.Log.d(TAG, "Entered onCreate()...");
}
}
Now suppose I derive an activity as follows...
package com.mydomain.Wibble
public class SomeActivity extends WibbleActivity {
#Override
protexted void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Don't Log "Entered onCreate()..." - WibbleActivity does it for me
android.util.Log.d(TAG, "SomeText");
}
}
Then I derive another Activity...
package com.mydomain.Wibble
public class SomeOtherActivity extends WibbleActivity {
#Override
protexted void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Don't Log "Entered onCreate()..." - WibbleActivity does it for me
android.util.Log.d(TAG, "SomeOtherText");
}
When onCreate() is called for SomeActivity, the output will be...
com.mydomain.Wibble.SomeActivity Entered onCreate()...
com.mydomain.Wibble.SomeActivity SomeText
...when onCreate() is called for SomeOtherActivity however, the output will be...
com.mydomain.Wibble.SomeOtherActivity Entered onCreate()...
com.mydomain.Wibble.SomeOtherActivity SomeOtherText
Neither activity needs to know specifics through an explicit string and the package name is prefixed. Obviously it will only work in certain situations but I find it useful.