I'm new with Xamarin and have to create a cross platform library (iOS, Android, Win Phone). i have so much difficult to create a pcl who works for those 3 platforms.
For example, this pcl needs establish a socket connection with a printer.
In pcl i can't use System.Net.Sockets so my idea is create a method and tried call his code with shared project .
when i execute the code, is stepped over the code inside #if __ANDROID__ .
PCL
public class Class1
{
public void socket()
{
Conecta.Class oi = new Conecta.Class();
oi.conecta();
}
}
Shared code
#if __ANDROID__
using System.Net.Sockets;
#endif
namespace Conecta
{
class Class
{
public void conecta()
{
#if __ANDROID__
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
clientSocket.Connect("192.168.210.171", 4002);
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes("teste \n");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
#endif
}
}
}
It's just a test, the code isn't sophisticated
Someone can help me?
Any other idea?
I believe PCL is not yet finished.
Even if you can resolve your printer issue in future you will have a lot of other problems.
In our project we prefer to share a code from one directory with different .csproj files.
PCL benefits really not worth powder and shot.
Related
It's pretty hard to understand the nuget packages to install in a Xamrin solution when searching around the web, there are dozens of packages, dozens of different solutions.
Right now, our solution has 2 projects, an Android one and a PCL one. Our model and data access is defined in the PCL. Our platform implementation is defined in the Android one.
We need SQLite, SQLite.Net (for the data annotations and table relations), and SQLiteExtentions for the *withchildren methods.
We are stuck in old versions because anytime we try to update anything, our frail magical way in which our installed packages are working together just falls apart. We do need to upgrade or find a way to add SQLCipher to this weird snafu of nuget packages.
Our current packages installed, which works:
Android project
Mono.Data.Sqlite.Portable 1.0.3.5 (not sure why...)
SQLite.Net.Core-PCL 3.1.1
SQLite.Net.Platform.XamarinAndroidN 3.1.1
SQLite.Net-PCL 3.1.1
SQLiteNetExtensions 1.3.0 (required for GetWithChildren etc.)
SQLitePCL.raw 0.9.3
PCL Project (model definition and data access methods)
Mono.Data.Sqlite.Portable 1.0.3.5 (not sure why...)
SQLite.Net.Core-PCL 3.1.1
SQLite.Net.Platform.XamarinAndroidN 3.1.1
SQLite.Net-PCL 3.1.1
SQLiteNetExtensions 1.3.0 (required for GetWithChildren etc.)
SQLitePCL.raw 0.9.3
Currently, if we update the SQLiteExtensions to 2.0, a bunch of other SQLite nuget packages are installed, breaking the frail stability of our data access code (fails on the *WithChildren methods with:
Severity Code Description Project File Line Suppression State
Error CS1929 'SQLiteConnection' does not contain a definition for
'GetWithChildren' and the best extension method overload
'ReadOperations.GetWithChildren<TEntity>(SQLiteConnection, object, bool)'
requires a receiver of type 'SQLiteConnection'
We'd also need to incorporate SQLiteCipher and no combinations of packages can be made to work with our solution.
Our Android platform specific implementation:
#region Usings
using OURPCLLib.DataAccess;
using Serilog;
using SQLite.Net;
using SQLite.Net.Interop;
using SQLite.Net.Platform.XamarinAndroid;
using System;
using System.IO;
#endregion Usings
public class AndroidSQLiteDatabase : SQLiteDatabaseAccess
{
protected ISQLitePlatform SQLitePlatform
{
get { return new SQLitePlatformAndroidN(); }
}
protected override SQLiteConnection GetConnection()
{
var conn = new SQLiteConnection(
SQLitePlatform,
"dbpathforus.sqlite",
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.FullMutex |
SQLiteOpenFlags.ProtectionCompleteUnlessOpen |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
return conn;
}
}
The (simplified) base data access class in the PCL:
#region Usings
using OURPCLLib.DataAccess.Entities;
using SQLite.Net;
using SQLite.Net.Attributes;
using SQLite.Net.Interop;
using SQLiteNetExtensions.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
#endregion Usings
public abstract class SQLiteDatabaseAccess
{
protected abstract SQLiteConnection GetConnection();
// Example of one of the many methods accessing the DB using SQLite.Net
public bool Any<TEntity>(Expression<Func<TEntity, bool>> expression)
where TEntity : class, IBaseEntity, new()
{
using (var currentConnection = this.GetConnection())
{
return currentConnection.Table<TEntity>().Where(expression).FirstOrDefault() != null;
}
}
// Example of one of the methods accessing the DB using SQLiteExtentions
public TEntity GetWithChildren<TEntity>(int id, bool recursive = false)
where TEntity : class, IBaseEntity, new()
{
using (var currentConnection = this.GetConnection())
{
return currentConnection.GetWithChildren<TEntity>(id, recursive);
}
}
}
Anyone can help us as to how to use SQLite with SQLIte.net, SQLiteExtentions and SQLIte cipher on a project like ours? (data access in a pcl and connection implementation in an android project?
For anyone wondering, I solved it, with minimal code impact, and some loss of functionality but not much, by only installing SQLiteNetExtensions and letting it get its SQLite dependency by itself.
I'm studying the NFC code of Google Pixel AOSP build (android-8.0.0_r3). I can understand the call flow from kernel all the way to Android hardware module system\nfc\halimpl\pn54x\nfc_nci.c as following:
struct nfc_nci_module_t HAL_MODULE_INFO_SYM = {
.common =
{
.tag = HARDWARE_MODULE_TAG,
.module_api_version = 0x0100, /* [15:8] major, [7:0] minor (1.0) */
.hal_api_version = 0x00, /* 0 is only valid value */
.id = NFC_NCI_HARDWARE_MODULE_ID,
.name = "NXP PN54X NFC NCI HW HAL",
.author = "NXP Semiconductors",
.methods = &nfc_module_methods,
},
};
This hardware module is loaded via hw_get_module(NFC_NCI_HARDWARE_MODULE_ID) found it in hardware/interface/nfc/1.0/default/nfc.cpp : HIDL_FETCH_INfc(...). Now I'm stuck here unable to find where in the AOSP invoked HIDL_FETCH_INfc(...)and how does it link to the next layer?
For android services that interact with hardware it connects in the following way.
In the nfc.cpp there should be a functions that are similar to:
JNINativeMethod method_table[]= {
{"external_name","(I)Z)",(void*)internal_name},
};
int register_android_server_FlexcanService(JNIEnv* env)
{
return jniRegisterNativeMethods(env,"com/android/server/MyService",method_table,NELEM(method_table));
}
This jniRegisterNativeMethods is called in onload.cpp and nfc.cpp is added to the Android.mk in the same folder
Then in the java package com.android.server.MyService (core/java/com/android/server) there will be a call to the native function:
public static native boolean external_name(int someVar);
From there there will be an .aidl binder file to expose the service methods to the SDK and eventually into top level Android apps.
In Android 7.x, NFC JNI locates at packages/apps/Nfc/nci/jni/. I haven't checked Android 8.x source, but I think it's still there.
I am struggling with some funny, but annoying error in my C++ Android native app. I am extending already working example from Oculus Mobile SDK called VrCubeWorld_SurfaceView.
The problem is constant error: defined but not used [-Werror=unused-function] when I want to add my own simple class that is only including App.h from SDK.
My class header file looks like this:
#ifndef VRAPP_H_
#define VRAPP_H_
#include "App.h"
using namespace OVR;
namespace AiLab {
class VrApp : public OVR::VrAppInterface
{
public:
VrApp();
virtual ~VrApp();
void OneTimeInit();
OvrGuiSys* GuiSys;
};
}
#endif /* VRAPP_H_ */
This is my cpp file of a class:
#include "VrApp.h"
namespace AiLab {
VrApp::VrApp():
GuiSys(OvrGuiSys::Create())
{
}
VrApp::~VrApp()
{
OvrGuiSys::Destroy(GuiSys);
}
VrApp::OneTimeInit()
{
GuiSys->Init( app, &app->GetSoundMgr(), app->LoadFontForLocale(), &app->GetDebugLines() );
}
}
What is more interesting is that functions that tend to display this error are in face used, so I comment it out then another error emerge.
Can anyone advice what might be wrong?
As marcinj stated, you can just comment the unused function 'OneTimeInit' to fix this warning, because the compiler thinks this function is not necessary exist in your code since nobody use it at all.
class VrApp : public OVR::VrAppInterface
{
public:
VrApp();
virtual ~VrApp();
// void OneTimeInit();
OvrGuiSys* GuiSys;
};
Sorry for lame and easy question but I failed to find an answer to it.
Every time I print something to the System.Diagnostics.Debug.WriteLine I have my message tripled:
System.Diagnostics.Debug.WriteLine("test");
Output:
[0:]
test
[0:] test
10-22 19:57:13.981 I/mono-stdout( 1026): test
I'm stick to System.Diagnostic.Debug because I write messages from both UI part (monodroid) and business logic (PCL)
Is there any way to descrease level of debug noise of Xamarin.Android?
Thank you for any suggestions.
Make your own little abstraction. We have the same issue in our project, this little Interface helps:
public interface ILogger
{
void Write(LogLevel level, String tag, String message);
}
Then you have your Loggers for each platform, for example:
public class AndroidLogger: ILogger
{
public void Write(LogLevel level, string tag, string message)
{
Android.Util.Log.WriteLine(ConvertLogLevel(level), tag, message);
}
}
You inject the logger in the iOS/Android project and you can even create fancy logger like e.g. a nice file-logger for iOS:
#if DEBUG
LOG.AddLogger(new TouchFileLogger());
LOG.AddLogger(new ConsoleLogger());
#endif
The LOG-class is static and needs not to know about the implementations, thats why it can be easily used in your shared PCL library.
Hope that helps, despite your problem might be solved by now ;-)
You can use Android.Util.Log instead, this greatly decreases it. It also has different levels of logging which you can filter in logcat.
Info: Log.Info()
Debug: Log.Debug()
Warning: Log.Warn()
Error: Log.Error()
Verbose: Log.Verbose()
and additionally a WriteLine, which does all of the above:
Log.WriteLine()
I have integrated two native libraries (.so ) in my application. The libraries compile fine and I can load them in my application too. The first time I invoke a native method of a library it works fine, but if I call the same method again in the Activity the application shuts down.
The problem I am facing is exactly the same as mentioned in here :
http://grokbase.com/t/gg/android-ndk/1226m68ydm/app-exit-on-second-native-call
The solution that works is to invoke the native method in another Activity and shut it down forcefully via System.exit(0). Following the article I tried setting the pointers to NULL of the called method after a successful operation, but this too didn't help me. Also its not possible to unload a library once its loaded by System.loadLibrary().
I want to call the native methods more than once without creating a new Activity. Any ideas how to solve this issue ?
(I FINALLY FOUND A SOLUTION ... HERE IT IS)
Okay, I have finally found a way to resolve this issue. The solution is actually pretty simple. Build another independent native library (utility library) to load and unload the other libraries. What we need to do is use dlopen() and dlclose() in the native method of the utility. We can load the utility library like before via System.loadLibrary().
So in the native method of the utility library what we need to do is:
Use#include <dlfcn.h> // this is required to call dlopen() and dlclose() functions.
Provide handler and function prototype:
void *handle;
typedef int (*func)(int); // define function prototype
func myFunctionName; // some name for the function
Open the library via dlopen() :
handle = dlopen("/data/data/my.package.com/lib/somelibrary.so", RTLD_LAZY);
Get and Call the function of the library:
myFunctionName = (func)dlsym(handle, "actualFunctionNameInLibrary");
myFunctionName(1); // passing parameters if needed in the call
Now that the call is done. Close it via dlclose():
dlclose(handle);
Hope this will help others facing the same issue.
So ... my solution was starting a service that runs the shared library code, this service has a different process name ( you can set it in the Android Manifest ), as it is a different process you can kill it ( Using Process.killProcess(Process.myPid()) when it finishes running, without affecting your application in any way.
Worked very well for me, hope it helps someone else.
As this is the top hit for this issue and as the issue itself still exists, it seems that the approach that ZakiMak shared with us is still the most popular solution.
For others who may want to implement it and would like a little more detail for the latest Android releases, here are some notes I made as I stumbled through this:
Firstly, there is a solution which implements this approach on GitHub now. I have not tried it personally, but I have used it as a reference. It is very useful to see how the Android.mk file is structured and how the library is opened and methods called. Link is here: https://github.com/jhotovy/android-ffmpeg
The path to the native library folder changes over Android releases and it also appears to change every time you run the app (although this may be just in debug mode). Either way, it is best to pass the path in from the calling Java method if possible. For example:
In the Java wrapping class:
import android.content.Context;
import android.util.Log;
public class FfmpegJNIWrapper {
//This class provides a Java wrapper around the exposed JNI ffmpeg functions.
static {
//Load the 'first' or 'outer' JNI library so this activity can use it
System.loadLibrary("ffmpeg_wraper_multi_invoke_jni");
}
public static int call_ffmpegWrapper(Context appContext, String[] ffmpegArgs) {
//Get the native libary path
String nativeLibPath = appContext.getApplicationInfo().nativeLibraryDir;
//Call the method in the first or 'outer' library, passing it the
//native library past as well as the original args
return ffmpegWrapper(nativeLibPath, ffmpegArgs);
}
// Native methods for ffmpeg functions
public static native int ffmpegWrapper(String nativeLibPath, String[] argv);
}
In the 'first' or 'outer' native library:
JNIEXPORT jint JNICALL Java_com_yourpackage_androidffmpegwrapper_FfmpegJNIWrapper_ffmpegWrapper(JNIEnv *pEnv, jobject pObj, jstring nativeLibPath, jobjectArray javaArgv) {
//Get the second or 'inner' native library path
char* nativePathPassedIn = (char *)(*pEnv)->GetStringUTFChars(pEnv, nativeLibPath, NULL);
char ourNativeLibraryPath[256];
snprintf(ourNativeLibraryPath, sizeof (ourNativeLibraryPath), "%s%s", nativePathPassedIn, "/libffmpeg_wraper_jni.so"); //the name of your ffmpeg library
//Open the so library
void *handle;
typedef int (*func)(JNIEnv*, jobject, jobjectArray);
handle = dlopen(ourNativeLibraryPath, RTLD_LAZY);
if (handle == NULL) {
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "could not open library: %s", dlerror());
printf("Could not dlopen(\"libbar.so\"): %s\n", dlerror());
return(-1);
}
//Call the ffmpeg wrapper functon in the second or 'inner' library
func reenterable_ffmpegWrapperFunction;
reenterable_ffmpegWrapperFunction = (func)dlsym(handle, "Java_com_yourpackage_androidffmpegwrapper_FfmpegJNIWrapper_ffmpegWrapper");
reenterable_ffmpegWrapperFunction(pEnv, pObj, javaArgv); //the original arguments
//Close the library
dlclose(handle);
// return
return(1);
}
The Android.mk file is a little 'flaky' to put it politely. Because you are building two separate libraries in one Android.mk file, this may be a little more complex that other NDK make files so if you get some strange errors do some searching before you start taking your project apart. For example: https://stackoverflow.com/a/6243727/334402