Calling helper function inside android application project from a library project - function

I have an android application project. I have created a library project and added reference in the application project. Now I need to call/access certain functions/class/methods that is there in the application project from the library project. How can I do that ?

Create an interface in the library that defines the functions you would like the library to call. Have the application implement the interface and then register the implementing object with the library. Then the library can call the application through that object.
In the library, declare the interface and add the registration function:
public class MyLibrary {
public interface AppInterface {
public void myFunction();
}
static AppInterface myapp = null;
static void registerApp(AppInterface appinterface) {
myapp = appinterface;
}
}
Then in your application:
public class MyApplication implements MyLibrary.AppInterface {
public void myFunction() {
// the library will be able to call this function
}
MyApplication() {
MyLibrary.registerApp(this);
}
}
You library can now call the app through the AppInterface object:
// in some library function
if (myapp != null) myapp.myFunction();

You can just create the object of that particular class and then you can directly call that method or variable.
class A{
public void methodA(){
new B().methodB();
//or
B.methodB1();
}
}
class B{
//instance method
public void methodB(){
}
//static method
public static void methodB1(){
}
}
Don't forget to import the necessary packages.

Related

Trying to integrate facebook with libgdx, where to implement this code because there is no "module:app" is present?

According to facebook:-
"Add the following to the dependencies {} section of your build.gradle (module: app) file to compile the latest version of the Facebook SDK:
implementation 'com.facebook.android:facebook-android-sdk:[4,5)'"
I don't see any module named app in the android studio project.where to add above line?
module:app in this case just means the main android app. So you should add the dependency to the android module.
Then I bet your next question how to use this library from the core since the Android module depends on the core module and not vice versa so you do not have access to the library in the core project. One way is to pass a contract to the platform launchers where each implements it differently.
//Simple contract
public interface IPlatformContract {
void runThis();
}
// Core project (MyGame)
private IPlatformContract platformContract;
public MyGame(IPlatformContract platformContract) {
this.platformContract = platformContract;
}
//DesktopLauncher
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
// Launch desktop with it's own implementation of the contract.
new LwjglApplication(new MyGame(new IPlatformContract() {
#Override
public void runThis() {
System.out.println(" I run on desktop!");
}
}), config);
}
//AndroidLauncher, different way. Here the class itself implements the contract.
public class AndroidLauncher extends AndroidApplication implements IPlatformContract{
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
initialize(new LibgdxTestEnvironment(this), config);
}
#Override
public void runThis() {
System.out.println("I run on android!");
}
}
You can pass along the contract to other classes like screens in your core project so you have access to it. You can even make a Singleton.

Kotlin #JvmStatic and accidental override in a companion object

I'm working on a Swing look&feel using kotlin. In order to create a UI, Swing requires to have a static method createUI with the following signature:
class ButtonUI: BasicButtonUI() {
...
companion object {
#JvmStatic fun createUI(p0: JComponent): ComponentUI {
...
}
}
}
and then it is called via reflection in Swing code:
m = uiClass.getMethod("createUI", new Class[]{JComponent.class});
Unfortunately, the code above cannot be compiled by the kotlin compiler because of:
Error:(88, 9) Kotlin: Accidental override: The following declarations have the same JVM signature (createUI(Ljavax/swing/JComponent;)Ljavax/swing/plaf/ComponentUI;):
fun createUI(c: JComponent): ComponentUI
fun createUI(p0: JComponent!): ComponentUI!
Is there a workaround for this case?
it's a kotlin bug KT-12993. Unfortunately, the bug is not fixed yet. just using java implements your ButtonUI or switch between java and kotlin to solving the problem if you want to let kotlin implements your ui logic. for example, you should define a peer between java and kotlin.
the java code as below:
public class ButtonUI extends BasicButtonUI {
private ButtonUIPeer peer;
public ButtonUI(ButtonUIPeer peer) {
this.peer = peer;
}
#Override
public void installUI(JComponent c) {
peer.installUI(c, () -> super.installUI(c));
}
// override other methods ...
public static ComponentUI createUI(JComponent c) {
// create the peer which write by kotlin
// |
return new ButtonUI(new YourButtonUIPeer());
}
}
interface ButtonUIPeer {
void installUI(Component c, Runnable parentCall);
//adding other methods for the ButtonUI
}
the kotlin code as below:
class YourButtonUIPeer : ButtonUIPeer {
override fun installUI(c: Component, parentCall: Runnable) {
// todo: implements your own ui logic
}
}
IF you have more than half dozen methods to implements, you can using the Proxy Design Pattern just delegate request to the target ButtonUI which implemented in kotlin (many IDE support generates delegate methods for a field). for example:
public class ButtonUIProxy extends BasicButtonUI {
private final BasicButtonUI target;
//1. move the cursor to here ---^
//2. press `ALT+INSERT`
//3. choose `Delegate Methods`
//4. select all public methods and then click `OK`
public ButtonUIProxy(BasicButtonUI target) {
this.target = target;
}
public static ComponentUI createUI(JComponent c){
// class created by kotlin ---v
return new ButtonUIProxy(new ButtonUI());
}
}
In latest version of Kotlin 1.3.70 the error can be suppressed with #Suppress("ACCIDENTAL_OVERRIDE"). I am not sure since which version it works.

How to make a public method that is not inherited by subclasses?

As the question states, I want to know how I can make a function in a class that other classes can access, but subclasses cannot. I have a class that has some public getters and setters that I want my document class to have access to call, but I don't want the subclass to have these functions because they'd be useless on the subclass.
For example
public class SomeClass
{
public function SomeClass() {}
public function notInherited():void { trace("Not inherited"; }
}
public class OtherClass extends SomeClass
{
public function OtherClass()
{
notInherited(); //Want this to return an error
}
}
public class HasAccess
{
public function HasAccess()
{
notInherited(); //Not inherited
}
}
I know this probably has something to do with custom namespaces, but after searching up about them I still don't really have much understanding of how they work. That's about it; thanks for reading.
You can't do this quite in the general terms you've asked, but you can do this if you put your document class and your other class in the same package and use internal instead of public, and you put your sub-class in a different package. The internal keyword limits access to classes in the same package.
Example (notice the package statements):
package main {
public class Main extends MovieClip {
public function Main() {
var stuff:Stuff = new Stuff();
stuff.doStuff();
}
}
}
package main {
public class Stuff {
internal function doStuff():void { }
}
}
package other {
public class OtherStuff extends Stuff {
public function OtherStuff() {
// no access to this.doStuff()
}
}
}
As for using a namespace, this can be a good option to make the intent of your code more clear, but it doesn't actually limit access in any new way, it just requires access to be more deliberate: while the namespace does hide visibility of the API to anyone who doesn't use the namespace, anyone can use the namespace and have access to the API without any additional limits (ie public, internal and protected).
Still, this may be all you are after. Here's an example which uses a public namespace and no packages:
// my_stuff.as
package {
public namespace my_stuff;
}
// Stuff.as
package {
public class Stuff {
my_stuff function doStuff():void { }
}
}
// Main.as
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
use namespace my_stuff; // you can put this above the class to give the entire class access to the namespace
var stuff:Stuff = new Stuff();
stuff.doStuff();
}
}
}
// OtherStuff.as
package {
public class OtherStuff extends Stuff {
public function OtherStuff() {
this.doStuff(); // not allowed
this.my_stuff::doStuff(); // allowed
// also allowed
use namespace my_stuff;
this.doStuff();
}
}
}
(Note that if your namespace is in a package, ex package stuff { public namespace my_stuff }, you must import the namespace just like a class, for example: import stuff.my_stuff)

Using MvvmCross from content providers and activities

I am trying to use MvvmCross v3 in one of my applications which consists of activities, content providers and broadcast receivers. However, I am not quite succeeding.
The application consists of a Core PCL which contains logic, models and viewmodels and a Droid application which contains all MonoDroid-specific stuff.
In Core I have an App:MvxApplication class and in Droid I have a Setup:MvxSetup class which creates an App-instance and initialises stuff.
I can use the IOC parts with content providers, broadcast receivers and non-Mvx-activities without problems. When I now want to add an MvxActivity it falls apart.
When the Mvx Activity launches I get an exception "Cirrious.CrossCore.Exceptions.MvxException: MvxTrace already initialized".
Obviously I am initialising things in the wrong order / wrong place. But, I need a pointer in the right direction.
My App Class
public class App
: MvxApplication
{
public override void Initialize()
{
base.Initialize();
InitialisePlugins();
InitaliseServices();
InitialiseStartNavigation();
}
private void InitaliseServices()
{
CreatableTypes().EndingWith("Service").AsInterfaces().RegisterAsLazySingleton();
}
private void InitialiseStartNavigation()
{
}
private void InitialisePlugins()
{
// initialise any plugins where are required at app startup
// e.g. Cirrious.MvvmCross.Plugins.Visibility.PluginLoader.Instance.EnsureLoaded();
}
}
And my setup class
public class Setup
: MvxAndroidSetup
{
public Setup(Context applicationContext)
: base(applicationContext)
{
}
protected override IMvxApplication CreateApp()
{
return new App();
}
protected override IMvxNavigationSerializer CreateNavigationSerializer()
{
return new MvxJsonNavigationSerializer();
}
public override void LoadPlugins(Cirrious.CrossCore.Plugins.IMvxPluginManager pluginManager)
{
pluginManager.EnsurePluginLoaded<Cirrious.MvvmCross.Plugins.Json.PluginLoader>();
base.LoadPlugins(pluginManager);
}
public void RegisterServices()
{
// I register a bunch of singletons here
}
// The following is called from my content provider's OnCreate()
// Which is the first code that is run
public static void DoSetup(Context applicationContext)
{
var setup = new Setup(applicationContext);
setup.Initialize();
setup.RegisterServices();
}
My Content provider's OnCreate():
public override bool OnCreate()
{
Log.Debug(Tag, "OnCreate");
_context = Context;
Setup.DoSetup(_context);
return true;
}
My MvxActivity:
[Activity(Label = "#string/ApplicationName", MainLauncher = true)]
[IntentFilter(new[] { "Settings" })]
public class SettingsView
: MvxActivity
{
public new SettingsViewModel ViewModel
{
get { return (SettingsViewModel) base.ViewModel; }
set { base.ViewModel = value; }
}
protected override void OnViewModelSet()
{
SetContentView(Resource.Layout.Page_SettingsView);
}
}
Short answer (I'm in an airport on mobile)
all the mvx android views will check the setup singleton has been created - https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Droid/Platform/MvxAndroidSetupSingleton.cs (vnext tree - but similar on v3)
so if you are creating a setup, but not setting this singleton, then you will get a second setup created when you first show a view
i suspect you can just get your setup created via the singleton class, but if this isn't flexible enough for your needs, then please log an issue on github
would also love to see some blogging about this - I've not used custom content providers much (at all!)

Flex Strongly Typed Proxy Classes for Lazy Instantiation

Does anyone know of a framework, preferably some way to have the Flex compiler run an extension or perhaps just a build step that we could generate strongly typed proxy classes of our application's data models.
There are 2 main things we want to do with the proxy's:
At runtime we want to lazily parse and instantiate the instance as accessed (similiar to how Java's Hibernate has Lazy proxy objects)
In an editor application we want to implement setter calls so we can track which objects have been modified
The Proxy is really necessary in this situation beyond things like programatically setting up ChangeWatcther's because we need to track Array adds/remove and possibly track "reference" objects so that when a "reference key" is changed we know to save those objects that are referencing it by key
In the first case we want the proxy to basically abstract when that object is loaded from serialized data, but still pass around references of it with the same public properties and data access pattern if it were the real object.
Basically the proxy would instantiate the object the first time a method is called on it.
I know we could use some AS3 byte-code libraries like as3-commons-bytecode.
Or possibly repurposing the GraniteDS Code Generation.
I'd prefer to generate code because it is a deterministic thing and it'd be nice if we could have a way to debug it at runtime easier.
Does anyone know if I could do something like MXMLC does when it generates AS3 code from MXML files.
Also is there anyway to control "when" in the compilation pipeline I can generate code, because we have a lot of data objects using public fields instead of getter/setters, but that are [Bindable] and so if I could generate the proxy based on the generated getter/setter methods that would work.
Here's an example application data object and proxy classes:
[Bindable]
public class PersonDTO implements Serializable {
private var _name:String;
private var _age:Number
public function get age():Number {
return _age;
}
public function set age(a:Number):void {
_age = a;
}
public function get name():String {
return _name;
}
public function set name(n:String):void {
_name = n;
}
public void readObject(data:*) {
//...
}
}
// GENERATED CLASS BASED ON PersonDTO
public class LazyProxy_PersonDTO extends PersonDTO {
private var _instance:PersonDTO = null;
private var _instanceData:*;
private function getInstance():void {
if (_instance == null) {
_instance = new PersonDTO();
_instance.readObject(_instanceData);
}
}
override public function get age():Number {
//Ensure object is instantiated
return getInstance().age;
}
override public function get name():String {
//Ensure object is instantiated
return getInstance().name;
}
}
// GENERATED CLASS BASED ON PersonDTO
public class LogChangeProxy_PersonDTO extends PersonDTO {
//This will be set in the application
public var instance:PersonDTO;
//set by application
public var dirtyWatcher:DirtyWatcherManager;
override public function set age(a:Number):void {
dirtyWatcher.markAsDirty(instance);
instance.age = a;
}
}
Digging a little deeper into AS3-Commons byte code library it looks like they support generating proxy classes and interceptors.
http://www.as3commons.org/as3-commons-bytecode/proxy.html
public class DirtyUpdateInterceptor implements IInterceptor {
public function DirtyUpdateInterceptor() {
super();
}
public function intercept(invocation:IMethodInvocation):void {
if (invocation.kind === MethodInvocationKind.SETTER) {
if (invocation.arguments[0] != invocation.instance[invocation.targetMember]) {
invocation.instance.isDirty = true;
}
}
}
}