Binding Jar Library - android

I'm trying to bind a jar library (jCIFS) on MFA, but i'm stuck on some errors, like this one:
'Jcifs.Util.MD4' does not implement inherited abstract member 'Java.Security.MessageDigestSpi.EngineDigest()
After some research, i found some topics about this, telling to edit the metadata to change the permissions of the classes, like this:
<attr path="/api/package[#name='java.security']/class[#name='MessageDigestSpi']/method[#name='engineDigest']" name="visibility">public</attr>
But the error didn't change, and a still won't get what this error means.
Anyone ?
Edit: This's the code of virtual class who return me the error:
public virtual byte[] EngineDigest ()
{
if (id_engineDigest == IntPtr.Zero)
id_engineDigest = JNIEnv.GetMethodID (class_ref, "engineDigest", "()[B");
if (GetType () == ThresholdType)
return (byte[]) JNIEnv.GetArray (JNIEnv.CallObjectMethod (Handle, id_engineDigest), JniHandleOwnership.TransferLocalRef, typeof (byte));
else
return (byte[]) JNIEnv.GetArray (JNIEnv.CallNonvirtualObjectMethod (Handle, ThresholdClass, id_engineDigest), JniHandleOwnership.TransferLocalRef, typeof (byte));
}
And i added this in a new file:
partial class MD4
{
public override byte[] EngineDigest()
{
return null;
}
}
If i do that, this error is returned:
Error 1 Type 'Jcifs.Util.MD4' already defines a member called 'EngineDigest' with the same parameter types
From what I understand, the method EngineDigest already exists, but the class needs to implement it. How i do that ?
The full error: Error 195 'Jcifs.Util.MD4' does not implement inherited abstract member 'Java.Security.MessageDigestSpi.EngineDigest()'
Edit 2: I've tried to reply the problem using OsmDroidBinding example from xamarin site. I edited the metafile until i get a similar error. And one of the lines i found was this one:
<attr path="/api/package[#name='org.osmdroid.tileprovider']/class[#name='MapTileProviderBase.ScaleTileLooper']/method[#name='handleTile']" name="visibility">public</attr>
And i get this error:
Then i tried to add this to my project metafile (like above), but the error persists:
<attr path="/api/package[#name='java.security']/class[#name='MessageDigestSpi']/method[#name='engineDigest']" name="visibility">public</attr>
Thanks.

It is telling you that the generated class Jcifs.Util.MD4 doesn't implement an inherited abstract method. An abstract method is a method which must be overridden by any derived class.
The code below is changing the visibility of the base class's method to public, which obviously won't fix the problem.
<attr path="/api/package[#name='java.security']/class[#name='MessageDigestSpi']/method[#name='engineDigest']" name="visibility">public</attr>
There are several ways you could fix this error. Perhaps the easiest would be to add a class file to your Java Binding Library and add the following code to it.
namespace Jcifs.Util
{
public partial class MD4
{
public override void EngineDigest()
{
}
}
}
NOTE You will need to change the return type of EngineDigest() to the return type defined for the abstract method in the base class. You haven't mentioned the return type in your question so I made it void.

Change
public override byte[] EngineDigest ()
To
protected override byte[] EngineDigest ()

Related

How to replace method reference(::) in java to normal constructor call?

Earlier I have model class in java which uses autovalue. Now, it's converted to Kotlin data class.
Model Class -->
public static SampleClass create(
#NonNull final SamplePost post,
#NonNull final List<SampleComment> comments) {
return new AutoValue_SampleClass(post, comments);
}
Calling Class -->
return Observable.zip(...
SampleClass::create);
}
new data class -->
data class SampleClass(val post: DiscussionPost,
val comments: List<SampleComment>) : Parcelable
Now how to call it for data class?
U can use SampleClass::new to call the constructor.
If I understand correctly, you don't need a constructor call, but a constructor reference. The syntax for it is ::SampleClass. But this may not trigger SAM conversion, in which case you'll need
Observable.zip(...,
{ post, comments -> SampleClass(post, comments) })
EDIT: The above assumes that zip is called from Kotlin, if you want to call it from Java, see #ebasha's answer.

Retrofit HEAD must use Void as Response Type in Kotlin

I have the following API method defined:
#HEAD("test/{name})
fun checkTitle(#Path("name") name: String): Single<Response<Void>>
I then want to unit test a successful response on this HEAD request but can't figure out how to instantiate a Void object in Kotlin.
whenever(mockService.checkTitle(any()))
.thenReturn(Single.just(Response.success(*VOID NEEDS TO BE HERE*)))
repo.checkTitle("tester")
.test()
.assertError(ValueTaken::class.java)
If I change the api call response to return Unit, it crashes at runtime with the following error as Retrofit does not support Unit yet.
HEAD method must use Void as response type.
EDIT - Addition of classes tried so far
I have tried the following so far but the compiler complains saying that it is expecting a return type of Single<Response<Void>>!
Unit
Nothing
Any
null
You can create an instance of Void through the (ab)use of reflection:
val voidConstructor = Void::class.java.getDeclaredConstructors()[0]
voidConstructor.setAccessible(true)
val voidInstance = voidConstructor.newInstance()
What this is doing is:
getting the first declared constructor for Void, which is private
setting it to public
creating an instance from that constructor
While I wouldn't suggest this in production code, in testing this is more palatable.
The issue might stem from wrapping with Single (is that RxJava?),because it only checks for !Void.class.equals(responseType):
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
Therefore it might be easier to use Call<Void> & Response<Void> (without any ResponseBody or other ORM mapping class). With #HEAD there won't be a ResponseBody anyway and instancing Void seems strange to me (as this data-type definition is barely used for delivering and eventually mapping the response). Regular co-routines eg. with suspend might play along better (because the data-type does not need to be wrapped). For comparison, in Java this is straightforward:
#HEAD Call<Void> checkTitle(#Path(value = "name") String name);

Picasso.with().invalidate(file) error: can not resolve method invalidate(java.io.File)

In my app I had used the picasso library but when I integrated in my code then it will show .invalidate(file) by red color . How can solve it?
Please find the below code for more reference:
FutureCallback<File> writeNewFileCallback = new FutureCallback<File>() {
#Override
public void onCompleted(Exception e, File file) {
if (e == null) { // Success
Picasso.with(MyApp.this.getActivity()).invalidate(file);
Transformation transformation = new RoundedTransformationBuilder()
.scaleType(ImageView.ScaleType.FIT_XY)
.borderColor(Color.parseColor("#77e5e5e5"))
.borderWidthDp(2)
.cornerRadiusDp(15)
.oval(false)
.build();}
When change it to :
`Picasso.with(this).invalidate(file);`
"this" will be unknown.
For user interface related calls use the Activity context.
See this explanation by Reto Meier: Using Application context everywhere?
This is simple to solve. Just do,
Picasso.with(getApplicationContext()).invalidate(file);
The with() method takes a Context as parameter, putting this works fine when you are inside an Activity.
But in your case, you are using this inside an anonymous inner class, so this refers to that specific class and not your Context.
Hope it helps.

Haxe: How can I setup a class to store data in an array of type that I pass in the constructor

I am coding in Haxe, Lime, OpenFl. I am trying to set up a Class to store data in a Map, referenced by class instance. The class type is to be passed in the constructor, via inference. But I am quite new to all this and can't quite figure out the syntax, this is what I got so far:
class DynamicStore<A>
{
private var hashA:Map<Class<A>,String>;
public function new<A>(paramA:Class<A>) {
hashA = new Map();
}
}
But this gives me the following error:
Abstract Map has no #:to function that accepts IMap<Class<DynamicStore.A>, String>
Is there a way to do this?
A question first:
do you really want to use classes as key? or objects?
In classes should be the key
It would be much simpler to use the classe's full name as key, like "mypackage.blob.MyClass". It's safer, easier to handle and debug.
Map<String, String>
Would suffice in that case.
If objects should be keys
Then the code would look like:
import haxe.ds.ObjectMap;
class Test<A>
{
static function main() {}
private var hashA :ObjectMap<A,String>;
public function new(paramA:A) {
hashA = new ObjectMap<A,String>();
}
}
The reason "Map" cannot be directly used in this case is that "Map" is a syntactic sugar, being resolved to StringMap, IntMap or others depending on the key type. If it doesn't know what kind of map to be used, it cannot proceed (this is mainly due to cross-compiling issues).
Remark
As a final note, I would mention your construction seems a bit wacky/strange to me. It would be interesting to know what you are trying to achieve and why you structure it the way you do.
I don't think you can use Class as the key of a Map. A good work around it to use a String as a key and the fully qualified names of the types. You can also define an abstract to move from the Type to String easily ... something like the following (code not-tested);
private var hashA : Map<String, String>;
public function addClass(className : ClassId, ...)
And the abstract will look something like this:
abstract ClassId(String) {
inline public function new(name : String) this = name;
#:from public static inline function fromClass(cls : Class<Dynamic>)
return new ClassId(Type.getClassName(cls));
#:to public inline function toClass() : Class<Dynamic>
return Type.resolveClass(this);
#:to public inline function toString() : String
return this;
}

C++ - inheriting ostream crashes on android but not windows

I have implemented a simple ostream and streambuf class. For some reason, it crashes when I try to instantiate my AndroidLogOStream object.
Note: I have stlport_static in my Application.mk
class AndroidLogStreamBuf : public std::streambuf
{
public:
inline AndroidLogStreamBuf() : std::streambuf()
{
//std::cout << "asdfg";
}
inline ~AndroidLogStreamBuf()
{
}
};
class AndroidLogOStream : public std::ostream
{
public:
inline AndroidLogOStream() : std::ostream(&mBuf)
{
}
inline ~AndroidLogOStream()
{
}
private:
AndroidLogStreamBuf mBuf;
};
It's barebones, and it runs fine on windows. It compiles fine on android, but it crashes for some reason. The last line it tries to execute is in _streambuf.c:46:
template <class _CharT, class _Traits>
locale
basic_streambuf<_CharT, _Traits>::pubimbue(const locale& __loc) {
this->imbue(__loc); <---- crash
locale __tmp = _M_locale;
_M_locale = __loc;
return __tmp;
}
Granted I am still quite confused on iostreams, but it must be something wrong with the constructor, I suppose it is not valid?
In a constructor, the base class is initialized first, followed by all of the members. When you call the base class constructor std::ostream, you're passing it the address of mBuf, which has not yet been constructed. Accessing an object that hasn't yet been constructed has undefined behaviour.
To get around this, you could redesign your classes as follows:
class AndroidLogStreamBuf : public std::streambuf
{
public:
AndroidLogStreamBuf() : std::streambuf()
{ }
~AndroidLogStreamBuf()
{ }
};
class AndroidLogOStream : public std::ostream
{
public:
AndroidLogOStream(AndroidLogStreamBuf *buf) :
std::ostream(buf),
mBuf(buf)
{ }
~AndroidLogOStream()
{ }
private:
AndroidLogStreamBuf *mBuf;
};
class AndroidLogOStreamWithBuf
{
private:
AndroidLogStreamBuf mBuf;
AndroidLogOStream mStream;
public:
AndroidLogOStreamWithBuf() :
mBuf(&mStream),
mStream()
{ }
virtual ~AndroidLogOStreamWithBuf()
{ }
AndroidLogOStream& getOStream()
{
return mStream;
}
};
Notice the order I've declared mBuf and mStream in AndroidLogOStreamWithBuf: the two fields will be initialized in that order, regardless of the order they appear in the constructor initializer list. As an aside, marking the member functions as inline in your original code was superfluous: when you define a member function within the class definition, it's automatically marked as inlinable.
Whether this is a sensible design for your system depends on how you're intending to use these classes, but the answer is probably "no".
As was pointed out, the base class is constructed first and from the looks of it, the base class constructor seems to do something. I don't think it is meant to but the base class destructor would also create a problem and that will call pubsync() on the stream buffer.
Of course, this explains the problem but doesn't provide a solution: the solution to this initialization problem is to make the the stream buffer (or a custom class containing the stream buffer as member) a virtual base class:
class oandroidligstream:
virtual AndroidLogStream,
public std::ostringstream {
...
}
};
the reason the base has to be virtual is that the stream buffer is an argument to the virtual base std::ios. To make sure your stream buffer is initialized first it has to be the left-most virtual base.

Categories

Resources