I want to launch camera app in android from Unity3d app. I can do it by building an Android app through Android Studio. I want to create a jar plugin of that android studio project and call the code through Unity game.
Unity C# code
public class UnityAndroidPluginExample : MonoBehaviour
{
AndroidJavaObject javaClass;
public void CallPlugin()
{
javaClass = new AndroidJavaObject("com.mycompany.pluginexample.CameraPluginClass");
javaClass.Call("LaunchCameraApp");
}
}
Android Studio Code
package com.mycompany.pluginexample;
import android.content.Intent;
import android.provider.MediaStore;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
public class CameraPluginClass extends AppCompatActivity
{
public void LaunchCameraApp()
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivity(intent);
}
}
I am getting error
AndroidJavaException: java.lang.ClassNotFoundException:com.mycompany.pluginexample.CameraPluginClass
AndroidJavaException: java.lang.NoClassDefFoundError:Failed resolution of: Landroidx/appcompat/app/AppCompatActivity
Here is my Android Studio code that worked for Android
btnCaptureImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);
}
});
Please help, I am stuck here. In short, I cannot call a method of the Java class that extends AppCompatACtivity. If I remove extends AppCompatActivity and call a method in that Java Class from Unity, it works, only if I use extends AppCompatActivty, I cannot call any method inside that class from Unity. I am using Unity version 2019.1.7f1.
Any help would be much appreciated.
Changing "AppCompatActivity" to just "Activity" worked for me, though I'm not sure why. If you ever figure out why, let me know!
Related
Trying to check if a particular application is installed in the android phone or not.
In android studio, I used Package manager to get the installation status of the application. But I need to use Xamarin.Forms for development.
yes,you could use DependencyService to achive this:
first,define a Interface :
public interface IsInstallApplication
{
bool IsInstall(string packageName);
}
then in Droid.project create a class which implement the interface :
[assembly: Dependency(typeof(AndroidIsInstallApplication))]// do not miss the line
namespace App18.Droid
{
class AndroidIsInstallApplication : IsInstallApplication
{
public bool IsInstall(string packageName)
{
... //here you could use Package manager to get the installation status of the application like in native android
return true;
}
}
}
finally you could call it in you page like :
DependencyService.Get<IsInstallApplication>().IsInstall(packageName);
I am implementing Share the App feature in Xamarin forms project. Yes, there are libraries which are available, But library conflicts with a version of Xamarin forms package and I have already completed all the stuff and don't want any issue, and I want to implement using dependency service by doing platform specific coding in Android and iOS without any package.
Here, I am using intent for share the app from Android project by making custom renderer. But I am getting error.
public class ShareTheAppRenderer : IShareTheApp
{
public void ShareApp()
{
var mainActivity = new MainActivity();
Intent sendIntent = new Intent();
sendIntent.SetAction(Intent.ActionSend);
sendIntent.PutExtra(Intent.ExtraText, "Check out our app at: https://play.google.com/store/apps/details?id=");
sendIntent.SetType("text/plain");
mainActivity.StartActivity(sendIntent);
}
}
Please give some suggestions to resolve this issue.
Thank you for your reply. But I got the solution for this. Here I don't want to use any other libraries to achieve this.
My Working solution is as below:
public class ShareTheAppRenderer : IShareTheApp
{
public void ShareApp()
{
var appPackageName = Forms.Context.PackageName;
var myIntent = new Intent(Android.Content.Intent.ActionSend);
myIntent.SetType("text/plain");
myIntent.PutExtra(Intent.ExtraText, "Check out our app at: https://play.google.com/store/apps/details?id=" + appPackageName);
Forms.Context.StartActivity(Intent.CreateChooser(myIntent, "Choose an App"));
}
}
This solution works for me.
My app is getting the following error when trying to load or show interstitial ad via AdMob for Unity: ClassNotFoundException: com.google.unity.ads.UnityAdListener.
AndroidJavaException: java.lang.ClassNotFoundException: com.google.unity.ads.UnityAdListener
java.lang.ClassNotFoundException: com.google.unity.ads.UnityAdListener
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
at java.lang.Class.forName(Class.java:378)
at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
at com.unity3d.player.UnityPlayer.c(Unknown Source:0)
at com.unity3d.player.UnityPlayer$e$2.queueIdle(Unknown Source:72)
at android.os.MessageQueue.next(MessageQueue.java:394)
at android.os.Looper.loop(Looper.java:142)
at com.unity3d.player.UnityPlayer$e.run(Unknown Source:32)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.unity.ads.UnityAdListener"
My main advertisment code is:
public class AdsTest : MonoBehaviour
{
private InterstitialAd interstitial;
public void LoadAd()
{
string adUnitId = "ca-app-pub-3940256099942544/1033173712";
interstitial = new InterstitialAd(adUnitId);
interstitial.OnAdLoaded += HandleOnAdLoaded;
interstitial.OnAdFailedToLoad += HandleOnAdFailedToLoad;
interstitial.OnAdOpening += HandleOnAdOpened;
interstitial.OnAdClosed += HandleOnAdClosed;
interstitial.OnAdLeavingApplication += HandleOnAdLeavingApplication;
AdRequest request = new AdRequest.Builder().Build();
interstitial.LoadAd(request);
}
public void ShowAd()
{
if (interstitial.IsLoaded())
{
interstitial.Show();
}
}
...
}
The rest of the AdsTest class are the standard event voids (OnAdLoaded, OnAdClosed, ect.), the same as they're in Google's docs.
Calling the ads script from another class:
void OnTriggerEnter2D(Collider2D trigger)
{
ReturnToStart();
// where ads is a instance of the AdsTest class
// ads = new AdsTest();
ads.LoadAd();
ads.ShowAd();
}
And I've initialized the AdMob Id at the beginning of the game in a controller object.
// executed when the app starts
string appId = "ca-app-pub-3522556458609123~3670809634";
MobileAds.Initialize(appId);
I've imported all the assets from the unity-package and force resolved the play services dependencies.
Also my AndroidManifest looks like this:
Environment and versioning:
Unity - 2018.3.0f2 Personal for Windows 10 x64
Android SDK - 27
AdMob Plugin - v3.15.1 (downloaded from Github)
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) Client VM (build 25.191-b12, mixed mode, sharing)
Play services - as installed via the Admob package
Tested on Android 8.1, API 27
I think some of the dependencies had a conflict and while the dependency resolver fixed them, ProGuard messed the things even more. Here is how I solved this particular problem:
Go to Build Settings > Player Setting > Publishing Settings (Player settings docs).
Enable custom ProGuard config.
Configure the proguard file to work for your problem. On my side the code snippet below does the job. But if you’re using additional dependencies they may conflict with this configuration. In such case it’s more of try and fail until the right config shows up… ProGuard docs.
-keep class com.google.unity.** {
*;
}
-keep public class com.google.android.gms.ads.**{
public *;
}
-keep public class com.google.ads.**{
public *;
}
-keepattributes *Annotation*
-dontobfuscate
For more details take a look at the blog post I've written about the issue.
NOTE: In more recent project with the newest version of AdMob and the Android SDK, the problem didn't appear. (As of May 2019)
Using the Glide library on Xamarin.Android, I was hoping someone could shed some light on how to use the AppGlideModule. According to the documentation, I need to register my custom ModelLoader using the AppGlideModule.
Here is a link to the example in the Glide documentation:
http://bumptech.github.io/glide/tut/custom-modelloader.html#writing-the-modelloader
Here is my custom AppGlideModule class:
public class MyCustomGlideModule : AppGlideModule
{
public override void ApplyOptions(Context context, GlideBuilder builder)
{
base.ApplyOptions(context, builder);
}
public override void RegisterComponents(Context context, Glide glide, Registry registry)
{
registry.Prepend(
Java.Lang.Class.FromType(typeof(Java.IO.OutputStream)),
Java.Lang.Class.FromType(typeof(Drawable)),
new MyCustomImageStreamModelLoaderFactory()
);
}
}
I don't know if it's necessary, but if you'd like to see the classes I made for the ModelLoader, please let me know in the comments.
Old question but here is the trick. You will need to create an Android/Java library that contains an AppGlideModule wrapper. This library contains nothing else and is simply used to generate the GlideApp class. It needs to contain a static instance of your final AppGlideModule. Basically, it will look like this :
#GlideModule
public class XamarinGlideModule extends AppGlideModule {
public static AppGlideModule InjectedModule;
#Override
public void registerComponents(Context context, Glide glide, Registry registry) {
if(InjectedModule != null) {
InjectedModule.registerComponents(context, glide, registry);
}
}
}
You will then need to wrap this library in an Android binding library. Nothing is worthy of mention in this step, simply drop your built AAR in the binding project, add the matching version of the Glide Nuget and build.
You can then add a reference to that binding library in your app project. In your Android Application class, you will need to setup the InjectedModule static property to inject your Xamarin implementation. You must do this before any call to Glide, something similar to this :
public override void OnCreate()
{
base.OnCreate();
XamarinGlideModule.InjectedModule = new MyLoaderModule();
var temp = GlideApp.Get(this); // Init Glide, it will register your Xamarin module
}
Now there's one more option to use custom glide module from C# code. Just install package of this project:
https://github.com/KDD-Digital-Healthcare-GmbH/Kdd.Glide.AppModuleInjector
NOTE: if you need custom AppModule for glide just to accept self-signed certificates, you can install this package as well, it already has implementation of such module:
https://github.com/KDD-Digital-Healthcare-GmbH/Kdd.Glide.UnsafeUrlLoadingAppGlideModule
I'm having an issue building the Unity3d project in Xcode (to test on a device) with a Objective C plug-in I've made.
Here are the files:
The TestPlugin.h file:
#import <Foundation/Foundation.h>
#interface TestPlugin : NSObject
+(int)getGoodNumber;
#end
The TestPlugin.m file:
#import "TestPlugin.h"
#implementation TestPlugin
+(int)getGoodNumber
{
return 1111111;
}
#end
And finally the C# script in unity that's supposed to print out the value that getGoodNumber() returns:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class PluginTest : MonoBehaviour
{
[DllImport ("__Internal")]
public static extern int getGoodNumber();
void OnGUI()
{
string goodNum = getGoodNumber().ToString();
GUILayout.Label (goodNum);
}
}
As much as I can tell there shouldn't be any problem with the code. But even though I followed many different tutorials, when I try to compile I get an error in Xcode:
Undefined symbols for architecture armv7:
"_getGoodNumber", referenced from:
RegisterMonoModules() in RegisterMonoModules.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I tried a million different things and nothing seems to help. As much as I could read from other tutorials I do not need any special settings for Xcode and I can leave them same as it was for the Unity project without the plug-in.
I would also like to clarify a few things:
The plugin files are located in /Plugins/iOS/ folder in Unity3d
The build target was iPad Air 2 with the latest iOS, so no problem should arise there. Also using the newest Xcode on the newest OS X version.
I have the newest available version of Unity3d, and if that matters - I do have the Pro version of Unity3d.
The project works if the plugin is removed, so it's not a problem between Unity3d and Xcode.
I do not think I need to use extern "C" wrapper in Objective-C code as it's a ".m" file, not ".mm", so there shouldn't be a problem of name-mangling.
The plug-in was created in Xcode through the "Cocoa Touch Static Library" template. I was able to successfully build the Xcode project by itself before importing it to Unity3d.
If someone encountered such a problem as solved it, I would love to hear the solution.
You've written an "objective-c" class and method, but that can not be exposed to Unity. You need to create a "c" method (which could then call an objective-c method if needed).
Eg:
plugin.m:
long getGoodNumber() {
return 111;
}
Here is a fuller example that demonstrates out params to get a gyro.
Let's make a motion manager to get gyro (faked out for now). This would be standard objective-c:
MyMotionManager.h
#interface MyMotionManager : NSObject { }
+(MyMotionManager*) sharedManager;
-(void) getGyroXYZ:(float[])xyz;
#end
MyMotionManager.m:
#implementation MyMotionManager
+ (MyMotionManager*)sharedManager
{
static MyMotionManager *sharedManager = nil;
if( !sharedManager )
sharedManager = [[MyMotionManager alloc] init];
return sharedManager;
}
- (void) getGyroXYZ:(float[])xyz
{
// fake
xyz[0] = 0.5f;
xyz[1] = 0.5f;
xyz[2] = 0.5f;
}
#end
Now lets expose it via a C external reference (no need for extern as it's in a .m (not a .mm):
MyMotionManagerExterns.m:
#import "MyMotionManager.h"
void GetGyroXYZ(float xyz[])
{
[[MyMotionManager sharedManager] getGyroXYZ:xyz];
}
Finally, in Unity C# lets call it:
MotionPlugin.cs:
using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;
public class MotionPlugin
{
[DllImport("__Internal")]
private static extern void GetGyroXYZ(float[] xyz);
public static Vector3 GetGyro()
{
float [] xyz = {0, 0, 0};
GetGyroXYZ(xyz);
return new Vector3(xyz[0], xyz[1], xyz[2]);
}
}