Everything was working until two days ago I got this error:
> Task :app:compileDebugJavaWithJavac FAILED
Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.5/userguide/command_line_interface.html#sec:command_line_warnings
224 actionable tasks: 195 executed, 29 up-to-date
Note: /Users/yashatreya/Desktop/realyze/node_modules/#react-native-community/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorage
Module.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: /Users/yashatreya/Desktop/realyze/node_modules/#react-native-community/datetimepicker/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerD
ialogFragment.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Note: /Users/yashatreya/Desktop/realyze/node_modules/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: /Users/yashatreya/Desktop/realyze/node_modules/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/NodesManager.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: /Users/yashatreya/Desktop/realyze/node_modules/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/NodesManager.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Note: /Users/yashatreya/Desktop/realyze/node_modules/react-native-sound/android/src/main/java/com/zmxv/RNSound/RNSoundModule.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: /Users/yashatreya/Desktop/realyze/node_modules/react-native-svg/android/src/main/java/com/horcrux/svg/TSpanView.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
/Users/yashatreya/Desktop/realyze/android/app/build/generated/rncli/src/main/java/debug/facebook/react/PackageList.java:90: error: getApplication() has protected access in ReactNativeHost
return this.reactNativeHost.getApplication();
^
1 error
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
This is my MainApplication.java
package com.realyze;
import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import io.expo.appearance.RNCAppearancePackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
//MultiDex
import androidx.multidex.MultiDexApplication;
//RN-PushNotification
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
public class MainApplication extends MultiDexApplication implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
#Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
#Override
protected List<ReactPackage> getPackages() {
#SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
new ReactNativePushNotificationPackage();
return packages;
}
#Override
protected String getJSMainModuleName() {
return "index";
}
};
#Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
#Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this); // Remove this line if you don't want Flipper enabled
}
/**
* Loads Flipper in React Native templates.
*
* #param context
*/
private static void initializeFlipper(Context context) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper");
aClass.getMethod("initializeFlipper", Context.class).invoke(null, context);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
Versions:
React Native: 0.61.4
Android Studio: 3.6.1
Gradle Plugin: 3.4.2
I have tried clearing the build cache but it still gives me the same error.
I am a beginner react-native developer and I can't understand what is going wrong.
Your help would be very much appreciated
The comments inside MainApplication.java are there to help and guide you on how to add packages that do not get to auto-link; so, if react-native-push-notification does not support auto-linking, you'll have to add it to the packages list like this:
//RN-PushNotification
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
public class MainApplication extends MultiDexApplication implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
#Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
#Override
protected List<ReactPackage> getPackages() {
#SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// Add a new ReactNativePushNotificationPackage to the packages
// ONLY IF ReactNativePushNotificationPackage does not support auto-linking
packages.add(new ReactNativePushNotificationPackage());
return packages;
}
...
If it does support auto-linking, then you'll have to remove/reverse the manual installation steps, clean the project and let React Native handle the native linking with the new RN >= 60 auto-linking system.
Related
I have installed react-native-navigation package for navigation in react native. After that I didn't like it and try use another package for navigation. But when I tried to uninstall this package and tried to run the app, it gives the following errors as given below. I didn't do anything, I had just uinstalled this react-native-navigation package from npm.
error Failed to install the app. Make sure you have the Android development environment set up: https://reactnative.dev/docs/environment-setup.
Error: Command failed: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Note: S:\Collab\ReactNative\Edesign\node_modules\#react-native-firebase\messaging\android\src\main\java\io\invertase\firebase\messaging\ReactNativeFirebaseMessagingModule.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainActivity.java:4: error: package com.reactnativenavigation does not exist
import com.reactnativenavigation.NavigationActivity;
^
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainActivity.java:7: error: cannot find symbol
public class MainActivity extends NavigationActivity {
^
symbol: class NavigationActivity
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainApplication.java:9: error: package com.reactnativenavigation does not exist
import com.reactnativenavigation.NavigationApplication;
^
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainApplication.java:10: error: package com.reactnativenavigation.react does not exist
import com.reactnativenavigation.react.NavigationPackage;
^
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainApplication.java:35: error: package com.reactnativenavigation.react does not exist
import com.reactnativenavigation.react.NavigationReactNativeHost;
^
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainApplication.java:41: error: cannot find symbol
public class MainApplication extends NavigationApplication {
^
symbol: class NavigationApplication
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainActivity.java:11: error: method does not override or implement a method from a supertype
#Override
^
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainActivity.java:13: error: cannot find symbol
super.onCreate(null);
^
symbol: variable super
location: class MainActivity
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainApplication.java:44: error: cannot find symbol
new NavigationReactNativeHost(this) {
^
symbol: class NavigationReactNativeHost
location: class MainApplication
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainApplication.java:45: error: method does not override or implement a method from a supertype
#Override
^
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainApplication.java:50: error: method does not override or implement a method from a supertype
#Override
^
S:\Collab\ReactNative\Edesign\android\app\src\main\java\com\edesign\MainApplication.java:53: error: no suitable constructor found for PackageList(<anonymous NavigationReactNativeHost>)
List<ReactPackage> packages = new PackageList(this).getPackages();
Is there any solution for this??
After you uninstalled react-native-navigation from npm, you should also revert back installation on Android
Update MainActivity.java
remove this line:
import com.reactnativenavigation.NavigationActivity;
Instead add this:
import com.facebook.react.ReactActivity;
Also, extends from ReactActivity, not NavigationActivity
Update MainApplication.java
Remove these:
import com.reactnativenavigation.NavigationApplication;
import com.reactnativenavigation.react.NavigationReactNativeHost;
Update this line:
public class MainApplication extends NavigationApplication
to this one:
public class MainApplication extends Application implements ReactApplication {
Update this line:
new NavigationReactNativeHost(this) {
to this one:
new ReactNativeHost(this) {
onCreate method:
#Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false); // add this one
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
I have an app with the following code on the MainActivity.java:
package com.MyApp;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
import android.view.Window;
import android.view.WindowManager;
import android.os.Bundle;
import com.MyApp.CustomLockscreenPackage;
public class MainActivity extends ReactActivity {
#Override
protected String getMainComponentName() {
return "MyApp";
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Window w = getWindow();
w.setFlags(
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
);
}
#Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
#Override
protected ReactRootView createRootView() {
return new RNGestureHandlerEnabledRootView(MainActivity.this);
}
};
}
}
The lines who make the app work on the lockscreen are:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Window w = getWindow();
w.setFlags(
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
);
}
But, the entire app works on the lockscreen, and i need to make only certain screens works on the lockscreen (It's a call app).
I tried creating a native module but don't worked.
i know its possible remove the flags with:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
So, if i can call these lines on my react native screen, it probably can work
[EDIT]: I made a module who does that for me: react-native-keep-awake
[EDIT]: How to use my module:
first of all, install him:
npm install --save https://github.com/willnaoosmit/react-native-keep-visible
(or with yarn, if you want to)
then:
import KeepAwake from 'react-native-keep-awake'; #import the module, of course
KeepAwake.activate(); #when you want to use the app on the lockscreen
KeepAwake.deactivate(); #when you dont want to use the app on the lockscreen anymore
I'm using React Native to create an Android/iOS app and trying to get a video to play in the WebView component. The video plays fine on iOS, but I'm having trouble getting it to play in the android WebView.
I've come across a few threads like this one (Enabling HTML5 video playback in android WebView?) that claim this is a fairly common problem on Android and can be solved by importing WebChromeClient and setting that option on the webview like so:
mainWebView.setWebChromeClient(new WebChromeClient());
But almost all these threads are strictly about building a native Android app and not using React Native.
Does anyone know how to get this to work in React Native?
I refer to an article by Yevgen Safronov
In it, he writes
Obviously the most challenging part of the application is handling
live video stream, because it requires switching stream’s video
quality based on available Internet bandwidth. But first things
first — I needed a RN native component to show any video stream. There
is a popular video component for RN but it has support for iOS only. I
decided to write my own RN component wrapper around Vitamio player. It
is well known open-source project and has support of RTMP protocol we
use for mobile app.
I had no prior experience with writing native RN components so I went
directly to RN documentation on how to create one. A guide I refer to
is called Native UI Components, there is similar one for iOS. There
are several essential parts to declare:
Implement custom ViewManager (Android part)
Register the ViewManager (Android part)
Implement the JavaScript module
Register the module (Android part)
Implement custom ViewManager Referring to the example of declaring
VideoView for Vitamio this is how the essence of VideoView declaration
looks like:
public class VideoViewDemo extends Activity {
#Override public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (!LibsChecker.checkVitamioLibs(this))
return;
setContentView(R.layout.videoview);
mEditText = (EditText) findViewById(R.id.url);
mVideoView = (VideoView) findViewById(R.id.surface_view);
if (path == "") { return; }
mVideoView.setVideoPath(path);
mVideoView.setMediaController(new MediaController(this));
mVideoView.requestFocus();
}
...
}
The code looks quite straightforward. Apart from passing a reference
to Activity into LibsChecker, VideoView requires a path to a video
stream and instance of MediaController.
public class VitamioViewManager extends SimpleViewManager<VideoView>{
public static final String REACT_CLASS = “RCTVitamioView”;
#Override
public String getName() {
return REACT_CLASS;
}
expose setStreamUrl setter using ReactProp:
#ReactProp(name = "streamUrl")
public void setStreamUrl(VideoView view, #Nullable String streamUrl) {
if (!LibsChecker.checkVitamioLibs(mActivity))
return;
view.setVideoPath(streamUrl);
view.setMediaController(new MediaController(mContext));
view.requestFocus();
}
add createViewInstance implementation:
private ThemedReactContext mContext = null;
private Activity mActivity = null;
#Override
public VideoView createViewInstance(ThemedReactContext context){
mContext = context;
return new VideoView(context);
}
One note about the code. Because LibsChecker requires an instance of Activity we will receive it via constructor, it will reference root activity used for RN application;
public VitamioViewManager(Activity activity) {
mActivity = activity;
}
Register the ViewManager
The final Java step is to register the ViewManager to the application, this happens via the applications package member function createViewManagers:
...
public class VitamioViewPackage implements ReactPackage {
private Activity mActivity = null;
public VitamioViewPackage(Activity activity) {
mActivity = activity;
}
#Override
public List<NativeModule>
createNativeModules(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
#Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
#Override
public List<ViewManager>
createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
new VitamioViewManager(mActivity)
);
}
}
Implement the JavaScript module In order to expose custom UI component
in JavaScript it is necessary to call special requireNativeComponent
function:
var { requireNativeComponent, PropTypes } = require('react-native');
var iface = {
name: 'VideoView',
propTypes: {
streamUrl: PropTypes.string
}
};
module.exports = requireNativeComponent('RCTVitamioView', iface);
Register the module Although it’s not mentioned as required step in
official documentation we need it because of reference to the root
activity: package com.vitamio_demo;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;
import com.sejoker.VitamView.VitamioViewPackage; // <--- import
public class MainActivity extends ReactActivity {
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
#Override
protected String getMainComponentName() {
return "vitamio_demo";
}
/**
* Returns whether dev mode should be enabled.
* This enables e.g. the dev menu.
*/
#Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
/**
* A list of packages used by the app. If the app uses additional views
* or modules besides the default ones, add more packages here.
*/
#Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new VitamioViewPackage(this) // <------ add here
);
}
}
Example of usage
Install the package in a project:
npm i react-native-android-vitamio --save
DeclareVideoView:
var VitamioView = require('react-native-android-vitamio');
class VideoScreen extends React.Component {
render() {
return (
<View>
<VitamioView style={styles.video} streamUrl="rtmp://fms.12E5.edgecastcdn.net/0012E5/mp4:videos/8Juv1MVa-485.mp4"/>
</View>
);
}
}
var styles = StyleSheet.create({
video: {
flex: 1,
flexDirection: 'row',
height: 400,
}
})
module.exports = VideoScreen;
Hope this is of help, A list of his own references is given in the article.
I am trying to set up a simple Android app that displays a webview and has some extra functionality available via the Javascript Interface.
I am testing on a HTC One S running Kitkat (via Cyanogenmod). When I inspect the webview the object inserted (Android) is empty "Object {}". I cannot use the functions in the interface via the loaded page.
I had built a more complicated activity but could not get the interface working, so I've created this new app for testing which contains the only the code from the webview guides. Still not inserting the methods into the exposed object.
MyActivity
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebSettings;
import android.webkit.WebView;
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl("http://47e148ba.ngrok.com");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
WebAppInterface
import android.content.Context;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
/**
* Created by graeme on 28/08/2014.
*/
public class WebAppInterface {
Context mContext;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
/** Show a toast from the web page */
#JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "com.mydomain.jswebview"
minSdkVersion 17
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
You can see I'm using the decorator required for the methods, which most questions seem to have as the solution. I'm developing in Android Studio if any of the presets in there might be interfering?
Edit:
In The JS file, or via the console if I'm inspecting the webview via chrome if I call Android or window.Android i get an empty objected returned "Object {}". Or if I try to use the methods defined in the interface above I'll receive a method undefined error.
I was having the same problem. Turned out to be a Proguard problem. Try adding the following to your Proguard rules:
-keepclassmembers class ** {
#android.webkit.JavascriptInterface <methods>;
}
I don't know how are you trying to call to your Java methods from inside of your WebView. I think that the correct way is:
javascript:window.Android.showToast('Hi!');
you could also test your JS interface from your Java code using:
myWebView.loadUrl("javascript:window.Android.showToast('Hi!');");
I hope this help you!
I have seen lots of problems with using ProGuard on applications that include webviews with JavascriptInterfaces, but none of the solutions seem to work for me so I must be missing something.
I have this activity
public class MapviewActivity extends Activity {
private WebView webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview_map);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setTitle("The Map");
webView = (WebView) findViewById(R.id.map_webview);
webView.clearCache(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
webView.setInitialScale(1);
webView.getSettings().setUseWideViewPort(true);
webView.loadUrl("file:///android_asset/map.html");
webView.addJavascriptInterface(new MapviewJSInterface(this), "Android");
}
public class MapviewJSInterface {
public Context mContext;
public MapviewJSInterface(MapviewActivity mapviewActivity) {
this.mContext = mapviewActivity;
}
#JavascriptInterface
public void showResidents(String locCode) {
Intent intent = new Intent(mContext, DialogResidentsList.class);
intent.putExtra("colorString", locCode);
mContext.startActivity(intent);
}
}
}
my proguard-project.txt includes this
-keep class tv.cmc2.zaratancodex.controller.MapviewActivity$MapviewJSInterface
-keepclassmembers class tv.cmc2.zaratancodex.controller.MapviewActivity$MapviewJSInterface {
public void showResidents(java.lang.String);
}
but I keep getting this error when I try to export an apk
Warning: tv.cmc2.zaratancodex.view.MapviewActivity$MapviewJSInterface: can't find referenced class android.webkit.JavascriptInterface
there must be something else that I am missing because those are the rules that seem to be working for everyone else.
You should build against a version of the Android runtime that contains the class android.webkit.JavascriptInterface. That would be android-17 or higher. ProGuard then won't complain that it can't find it.
If your code uses the annotation to mark Javascript interface classes (as required in recent versions of the Android SDK), you can also use it in your ProGuard configuration:
-keepclassmembers class * {
#android.webkit.JavascriptInterface <methods>;
}
You then no longer need to exhaustively list the interface classes and methods.