I am trying to make a Unity app go into kiosk mode by using COSU (Corporate Owned Single Use) functionality.
My plan was to first get things working using just Android, so I followed the tutorial offered by Google Code Labs
After I got this working, my plan was to then figure out how to integrate this into my Unity project. I followed
this youtube video that showed how to make a plugin that can be called from Unity.
When I build my project, I try to execute the following command
adb shell dpm set-device-owner com.modalvr.unityplugin/.DeviceAdminReceiver
However, I keep getting the following error
Error: Unknown admin: ComponentInfo{com.modalvr.unityplugin/com.modalvr.unityplugin.DeviceAdminReceiver}
I wonder if Unity is not merging the AndroidManifest.xml files together correctly. Here is my AndroidManifest.xml file from plugin.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.modalvr.unityplugin">
<application android:allowBackup="true" android:label="#string/app_name" android:supportsRtl="true">
<receiver
android:name="com.modalvr.unityplugin.DeviceAdminReceiver"
android:description="#string/app_name"
android:label="#string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/device_admin_receiver" />
<intent-filter>
<action android:name="android.intent.action.DEVICE_ADMIN_ENABLED"/>
<action android:name="android.intent.action.PROFILE_PROVISIONING_COMPLETE"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>
I copied it and the classes.jar file into Unity's Assets/Plugins/Android/libs folder
I am able to successfully call functions in my plugin, so the plugin appears to be set up correctly.
For reference, this is my C# code that calls into the plugin
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LockManager : MonoBehaviour {
#if UNITY_ANDROID
private AndroidJavaObject playerActivityContext = null;
#endif
public void SaveContext() {
#if UNITY_ANDROID
// First, obtain the current activity context
using (var actClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
playerActivityContext = actClass.GetStatic<AndroidJavaObject>("currentActivity");
}
var plugin = new AndroidJavaClass("com.modalvr.unityplugin.PluginClass");
plugin.CallStatic<bool>("setContext", playerActivityContext);
#endif
}
public void LockButtonClicked() {
#if UNITY_ANDROID
SaveContext();
var plugin = new AndroidJavaClass("com.modalvr.unityplugin.PluginClass");
bool retVal = plugin.CallStatic<bool>("lock", 7);
#endif
}
public void UnlockButtonClicked() {
#if UNITY_ANDROID
SaveContext();
var plugin = new AndroidJavaClass("com.modalvr.unityplugin.PluginClass");
bool retVal = plugin.CallStatic<bool>("unlock", 7);
#endif
}
}
And this is the java class that defines those functions.
package com.modalvr.unityplugin;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
public class PluginClass {
private static Context context;
public static boolean setContext(Context ctx) {
context = ctx;
return true;
}
public static boolean lock(int number) {
Log.d("SOME TAG", "onReceive Lock");
Activity activity = (Activity) context;
activity.startLockTask();
return true;
}
public static boolean unlock(int number) {
Log.d("SOME TAG", "onReceive Unlock");
Activity activity = (Activity) context;
activity.stopLockTask();
return true;
}
}
It looks like Unity generates 2 XML files that it puts in Temp/StagingArea
AndroidManfist.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ModalVR.KioskPluginTest" xmlns:tools="http://schemas.android.com/tools" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="#style/UnityThemeSelector" android:icon="#drawable/app_icon" android:label="#string/app_name" android:debuggable="false" android:isGame="true" android:banner="#drawable/app_banner">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="#string/app_name" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="25" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>
and AndroidManifest-main.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ModalVR.KioskPluginTest" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal" android:versionName="1.0" android:versionCode="1">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="#style/UnityThemeSelector" android:icon="#drawable/app_icon" android:label="#string/app_name" android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="25" />
</manifest>
In neither of these files do I see the contents of my Android plugin AndroidManifest.xml I guess that is the issue. Do I need to do something to make the manifest files merge?
And for completeness, here is
DeviceAdminReceiver.java
package com.modalvr.unityplugin;
import android.content.ComponentName;
import android.content.Context;
/**
* Handles events related to the managed profile.
*/
public class DeviceAdminReceiver extends android.app.admin.DeviceAdminReceiver {
private static final String TAG = "DeviceAdminReceiver";
/**
* #param context The context of the application.
* #return The component name of this component in the given context.
*/
public static ComponentName getComponentName(Context context) {
return new ComponentName(context.getApplicationContext(), DeviceAdminReceiver.class);
}
}
Thanks in advance for any help.
John Lawrie
Do I need to do something to make the manifest files merge?
Yes.
The manifest in Unity will automatically merge only if you compile the Java plugin as .aar package. If you build it as .jar file then you have to manually put the Manifest in the right folder in Unity so that Unity can merge it into your program during build.
You are currently building as .jar library so below is where to place the Manifest:
Put the AndroidManifest.xml file in your <ProjectName>Assets\Plugins\Android folder. Make sure to spell AndroidManifest and the folder names of where to put it correctly. That's it.
Related
sorry for my bad English
I made an Android plugin for Unity3D v4.5 by command prompt, JDK, SDK and Apache Ant.
The command "ant jar" built it with no errors, but when I try to open my game in my mobile device, he tells me: "Unfortunately, TheGame has stopped."
My mobile is Android 4.1.2 (Api 16) and I built the game in Api 15.
Before using plugin I had no problems and I had no errors using Apache and JDK.
This is my java code "MyLibrary.java" in src\com\test\app:
package com.test.app;
import com.unity3d.player.UnityPlayerActivity;
public class MyLibrary extends UnityPlayerActivity
{
public static float GetValue()
{
return 1.0f;
}
}
As you see, I want to use it to simply get a float number (1.0f)
This is the Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.app"
android:versionCode="1"
android:versionName="1.0">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"/>
<application android:label="#string/app_name" android:icon="#drawable/app_icon">
<activity android:name=".MyLibrary"
android:label="#string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:label="#string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
</activity>
</application>
</manifest>
And it`s my C# Script for unity:
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
AndroidJavaClass pluginTutorialActivityJavaClass;
public string GetValue ()
{
AndroidJNI.AttachCurrentThread();
pluginTutorialActivityJavaClass = new AndroidJavaClass("com.test.app.MyLibrary");
float number = pluginTutorialActivityJavaClass.CallStatic<float>("GetValue");
return number.ToString();
}
string val = "";
void OnGUI()
{
if(GUI.Button(new Rect(0,0,200,200),"GetValue"))
{
val = GetValue();
}
GUI.TextArea(new Rect(0,200,200,200),val);
}
}
Did I do something wrong? Help me please
Thanks
I have created a sample app called NoteApp, that can save data to Parse. I have created the app in Parse as per the image below, and have created the app..which is still in progress.
I have created the object"testObject", I have matched the ID, and imported data(Ctrl+Shift+O)but when I try to run the app, and check the Parse dashboard, I can't see the object being created. I have tried this so many times, I don't know where the problem is. I just can't link my android app in eclipse with the Parse.com. the app can't create the object, hence I can't save data.
Here is the Application code, and the manifest file, and the image of the Parse.com Dashboard.
NoteApplication.java
package com.echessa.noteapp;![enter image description here][1]
import android.app.Application;
import com.parse.Parse;
import com.parse.ParseObject;
public class NoteApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Parse.initialize(NoteApplication.this, "XXXXXXXXXXXXXXXX","XXXXXXXXXXXXXXXXXX");
ParseObject testObject = new ParseObject("TestObject");
testObject.put("foo", "bar");
testObject.saveInBackground();
}
}
The Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.echessa.noteapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name="com.echessa.noteapp.NoteApplication"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I have problem create a basic applicationn for google glass based on this tutorial. I have 2 classes. I followed exactly the same as the tutorial, but I couldn't find it in google glass. I tried from "Ok Glass", but I also couldnt find it.
I have created 2 classes, the first is HelloWorldActivity.java. This class is a Activity class. Here is the HelloWorldActivity.java
public class HelloWorldActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Card myCard = new Card(this);
myCard.setText("Hello, World!");
myCard.setFootnote("First Glassware for Glass");
View cardView = myCard.getView();
// Display the card we just created
setContentView(cardView);
}
}
The second is HelloGlass.java This class is a Service class that will recognize the voice command.
public class HelloGlass extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
Intent i = new Intent(this, HelloWorldActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
return START_STICKY;
}
}
I have created the necessary xml files including the voice_trigger_start.xml. Here is the andorid manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.app.helloglass"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".HelloWorldActivity"
android:label="#string/app_name"
android:enabled="true" >
</activity>
<service
android:name="com.app.helloglass.HelloGlass"
android:enabled="true"
android:exported="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<!-- Voice command found in res/xml/voice_trigger_start -->
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voice_trigger_start" />
</service>
</application>
</manifest>
Anybody know what I have missed? I tried to run it but I couldn't find it.
Edit:
After adding the permission, the voice command works fine but the app crashes because the package name in the manifest is wrong.
See the whole update project on my GitHub.
The tutorial uses a custom voice command. You need this permission in the manifest:
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />
Please see Why is my voice command missing from the ok glass menu in XE16? and also https://developers.google.com/glass/develop/gdk/voice
Could you try this manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.app.helloglass"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".HelloWorldActivity"
android:label="#string/app_name"
android:enabled="true" >
</activity>
<service
android:name="com.app.helloglass.HelloGlass"
android:enabled="true"
android:exported="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<!-- Voice command found in res/xml/voice_trigger_start -->
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voice_trigger_start" />
</service>
</application>
</manifest>
I am trying to use google map for my android application but all i get is grey grids and in logcat it shows error like :
02-11 09:49:56.860: E/MapActivity(979): Couldn't get connection factory client
I have added permission in manifest to use internet.
I have used google library.
I have used Correct Map Api key for android application.
I am using correct emulator to support google API
Browser in my emulator is working and connecting to internet but my App is not working even on android mobile!
here is my manifest file code :
package="com.nawed.maps"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<uses-library android:name="com.google.android.maps"/>
<activity
android:name="com.nawed.maps.ShowMap"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
My activity class :
package com.nawed.maps;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import android.os.Bundle;
public class ShowMap extends MapActivity {
MapView mapView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_map);
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
}
My XML file :
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="MyKey"
/>
I have seen other repeated questions but it doesn't worked for me.
Thank you in advance.
I've seen this question asked often, but none of the proposed solutions seem to be working for me. I'm getting
E/AndroidRuntime(897): java.lang.NoClassDefFoundError: android.support.v4.app.FragmentMapActivity$4
when attempting to open a new FragmentMapActivity.
Code:
public class Maps extends FragmentMapActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maps_simple);
//MapView for the lose :(
Toast.makeText(this, R.string.map_warning, Toast.LENGTH_LONG).show();
MapView mapView = (MapView)findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
R.layout.maps_simple contains:
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="<key removed for security>"
/>
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="osmstudios.mappingapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="13" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application android:icon="#drawable/icon" android:label="#string/app_name" android:theme="#style/Theme.MapApp" android:hardwareAccelerated="true">
<uses-library android:name="com.google.android.maps" />
<activity android:label="#string/app_name" android:name=".AppMainActivity">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:label="#string/app_name" android:name="com.keyes.youtube.OpenYouTubePlayerActivity"></activity>
<activity android:label="#string/app_name" android:name=".Maps">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="osmstudios.mappingapp" />
</intent-filter>
</activity>
</application>
</manifest>
Here is the inner code of the button press that opens the FragmentMapActivity intent:
Intent intent = new Intent(ctx, Maps.class);
startActivity(intent);
Finally, this is what my Libraries folder in the Java Build Path tool look like:
I've been really beating my head against a wall on this one. Any help would be appreciated.
This is bit late but I had the exact same issue and could at least resolve the "java.lang.NoClassDefFoundError:". In project property->java Build path -> Libraries, I had included android-support-v4.jar from android sdk path. This lib was available during compile time but not at run time. You need to copy this jar from sdk path to application libs location that way this lib is statically added to your app and could be found during run time. hope this helps. This solution I found after lots of search in StackOverFlow. Hers is the link. Trying to use DialogFragments via v4 compatability causes NoClassDefFoundErrors
It turns out the issue had to do with a change in Android versions.
More information and the fix can be found http://www.wiseappsllc.com/homepage/android-dev-tips
I had same problem, then i resolved it by checking the build path of the project. There i had two map jars. I deleted one in libraries, Now it is working fine. Just check it may work.