Skip to content

Fixed android camera support #477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,13 @@ https://forum.unity.com/threads/android-hardwareaccelerated-is-forced-false-in-a

##### Unity 2017.x - 2018.0

Unity forcibly set `android:hardwareAccelerated="false"` regardless of its setting in `Plugins/Android/AndroidManifest.xml`, as discussed in https://github.com/gree/unity-webview/issues/382 (see also https://github.com/gree/unity-webview/issues/342 and https://forum.unity.com/threads/android-hardwareaccelerated-is-forced-false-in-all-activities.532786/ ), and there is no solution for automatically correcting this setting. Please export the project and manually correct AndroidManifest.xml.
Unity forcibly set `android:hardwareAccelerated="false"` regardless of its setting in `Plugins/Android/AndroidManifest.xml`, as discussed in https://github.com/gree/unity-webview/issues/382 (see also https://github.com/gree/unity-webview/issues/342 and https://forum.unity.com/threads/android-hardwareaccelerated-is-forced-false-in-all-activities.532786/ ), and there is no solution for automatically correcting this setting. Please export the project and manually correct `AndroidManifest.xml`.

##### Unity 5.x or older

After the initial build, `Assets/Plugins/Editor/UnityWebViewPostprocessBuild.cs` will copy
`sample/Temp/StatingArea/AndroidManifest-main.xml` to
`sample/Assets/Plugins/Android/AndroidManifest.xml`, edit the latter to add
`Temp/StatingArea/AndroidManifest-main.xml` to
`Assets/Plugins/Android/AndroidManifest.xml`, edit the latter to add
`android:hardwareAccelerated="true"` to `<activity
android:name="com.unity3d.player.UnityPlayerActivity" ...`. Then you need to build the app again to
reflect this change.
Expand All @@ -163,6 +163,17 @@ implementation will adjust Unity's SurfaceView z order. Please refer
and `plugins/Android/src/net/gree/unitywebview/CUnityPlayer.java` if
you already have your own activity implementation.

#### Camera Permission/Feature

In order to allow camera access (`navigator.mediaDevices.getUserMedia({ video:true })`), please define `UNITYWEBVIEW_ANDROID_ENABLE_CAMERA` so that `Assets/Plugins/Editor/UnityWebViewPostprocessBuild.cs` adds the followings to `AndroidManifest.xml`.

```xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
```

Details for each Unity version are the same as for hardwareAccelerated.

#### How to build WebViewPlugin.jar

The following steps are for Mac but you can follow similar ones for Windows.
Expand Down
Binary file added plugins/Android/extra/appcompat-v7-23.3.0.aar
Binary file not shown.
Binary file added plugins/Android/extra/support-v4-23.3.0.aar
Binary file not shown.
2 changes: 2 additions & 0 deletions plugins/Android/gradle_build/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ apply plugin: 'com.android.library'

dependencies {
provided files('./libs/classes.jar')
implementation 'com.android.support:appcompat-v7:23.3.0'
implementation 'com.android.support:support-v4:23.3.0'
}

android {
Expand Down
1 change: 1 addition & 0 deletions plugins/Android/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ if [ ${JAR_CMD} = "" ];then
else
jar cvf ${CWD}/bin/WebViewPlugin.jar -C ${BUILD_DIR}/build/intermediates/classes/release net
cp -a ${BIN_DIR}/WebViewPlugin.jar ${DEST_DIR}
cp -a extra/*.aar ${DEST_DIR}
fi

./gradlew clean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import android.webkit.CookieSyncManager;
import android.widget.FrameLayout;
import android.webkit.PermissionRequest;
import android.support.v4.app.ActivityCompat;

import java.net.HttpURLConnection;
import java.net.URL;
Expand Down Expand Up @@ -163,7 +164,13 @@ public void onPermissionRequest(final PermissionRequest request) {
final String[] requestedResources = request.getResources();
for (String r : requestedResources) {
if (r.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(request.getResources());
request.grant(requestedResources);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
a.runOnUiThread(new Runnable() {public void run() {
final String[] permissions = { "android.permission.CAMERA" };
ActivityCompat.requestPermissions(a, permissions, 0);
}});
}
break;
}
}
Expand Down
126 changes: 62 additions & 64 deletions plugins/Editor/UnityWebViewPostprocessBuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,20 @@ public class UnityWebViewPostprocessBuild
//// cf. https://forum.unity.com/threads/android-hardwareaccelerated-is-forced-false-in-all-activities.532786/
//// cf. https://github.com/Over17/UnityAndroidManifestCallback

#if UNITY_2018_1_OR_NEWER
public void OnPostGenerateGradleAndroidProject(string basePath) {
Debug.Log("adjusted AndroidManifest.xml.");
var changed = false;
var androidManifest = new AndroidManifest(GetManifestPath(basePath));
androidManifest.SetHardwareAccelerated(true);
androidManifest.Save();
changed = (androidManifest.SetHardwareAccelerated(true) || changed);
#if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA
changed = (androidManifest.AddCamera() || changed);
#endif
if (changed) {
androidManifest.Save();
Debug.Log("unitywebview: adjusted AndroidManifest.xml.");
}
}
#endif

public int callbackOrder {
get {
Expand All @@ -41,11 +49,6 @@ private string GetManifestPath(string basePath) {

//// for others

#if UNITYWEBVIEW_ANDROID_USE_ACTIVITY_NAME
// please modify ACTIVITY_NAME if you set UNITYWEBVIEW_ANDROID_USE_ACTIVITY_NAME and utilize any custom activty.
private const string ACTIVITY_NAME = "com.unity3d.player.UnityPlayerActivity";
#endif

[PostProcessBuild(100)]
public static void OnPostprocessBuild(BuildTarget buildTarget, string path) {
#if !UNITY_2018_1_OR_NEWER
Expand All @@ -54,29 +57,25 @@ public static void OnPostprocessBuild(BuildTarget buildTarget, string path) {
if (!File.Exists(manifest)) {
string manifest0 = Path.Combine(Application.dataPath, "../Temp/StagingArea/AndroidManifest-main.xml");
if (!File.Exists(manifest0)) {
Debug.LogError("cannot find both Assets/Plugins/Android/AndroidManifest.xml and Temp/StagingArea/AndroidManifest-main.xml. please build the app to generate Assets/Plugins/Android/AndroidManifest.xml and then rebuild it again.");
Debug.LogError("unitywebview: cannot find both Assets/Plugins/Android/AndroidManifest.xml and Temp/StagingArea/AndroidManifest-main.xml. please build the app to generate Assets/Plugins/Android/AndroidManifest.xml and then rebuild it again.");
return;
} else {
File.Copy(manifest0, manifest);
}
}
XmlDocument doc = new XmlDocument();
doc.Load(manifest);
XmlElement activity = SearchActivity(doc);
if (activity != null
&& string.IsNullOrEmpty(activity.GetAttribute("android:hardwareAccelerated"))) {
activity.SetAttribute("hardwareAccelerated", "http://schemas.android.com/apk/res/android", "true");
doc.Save(manifest);
Debug.LogError("adjusted AndroidManifest.xml about android:hardwareAccelerated. Please rebuild the app.");
}
var changed = false;
var androidManifest = new AndroidManifest(manifest);
changed = (androidManifest.SetHardwareAccelerated(true) || changed);
#if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA
changed = (androidManifest.AddCamera() || changed);
#endif
#if UNITY_5_6_0 || UNITY_5_6_1
if (activity != null
&& activity.GetAttribute("android:name") == "com.unity3d.player.UnityPlayerActivity") {
activity.SetAttribute("name", "http://schemas.android.com/apk/res/android", "net.gree.unitywebview.CUnityPlayerActivity");
doc.Save(manifest);
Debug.LogError("adjusted AndroidManifest.xml about android:name. Please rebuild the app.");
}
changed = (androidManifest.SetActivityName("net.gree.unitywebview.CUnityPlayerActivity") || changed);
#endif
if (changed) {
androidManifest.Save();
Debug.LogError("unitywebview: adjusted AndroidManifest.xml. Please rebuild the app.");
}
}
#endif
if (buildTarget == BuildTarget.iOS) {
Expand All @@ -88,43 +87,6 @@ public static void OnPostprocessBuild(BuildTarget buildTarget, string path) {
File.WriteAllText(projPath, proj.WriteToString());
}
}

private static XmlElement SearchActivity(XmlDocument doc) {
foreach (XmlNode node0 in doc.DocumentElement.ChildNodes) {
if (node0.Name == "application") {
foreach (XmlNode node1 in node0.ChildNodes) {
#if UNITYWEBVIEW_ANDROID_USE_ACTIVITY_NAME
if (node1.Name == "activity"
&& ((XmlElement)node1).GetAttribute("android:name") == ACTIVITY_NAME) {
return (XmlElement)node1;
}
#else
if (node1.Name == "activity") {
foreach (XmlNode node2 in node1.ChildNodes) {
if (node2.Name == "intent-filter") {
bool hasActionMain = false;
bool hasCategoryLauncher = false;
foreach (XmlNode node3 in node2.ChildNodes) {
if (node3.Name == "action"
&& ((XmlElement)node3).GetAttribute("android:name") == "android.intent.action.MAIN") {
hasActionMain = true;
} else if (node3.Name == "category"
&& ((XmlElement)node3).GetAttribute("android:name") == "android.intent.category.LAUNCHER") {
hasCategoryLauncher = true;
}
}
if (hasActionMain && hasCategoryLauncher) {
return (XmlElement)node1;
}
}
}
#endif
}
}
}
}
return null;
}
}

internal class AndroidXmlDocument : XmlDocument {
Expand Down Expand Up @@ -156,9 +118,11 @@ public string SaveAs(string path) {
}

internal class AndroidManifest : AndroidXmlDocument {
private readonly XmlElement ManifestElement;
private readonly XmlElement ApplicationElement;

public AndroidManifest(string path) : base(path) {
ManifestElement = SelectSingleNode("/manifest") as XmlElement;
ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
}

Expand All @@ -176,9 +140,43 @@ internal XmlNode GetActivityWithLaunchIntent() {
nsMgr);
}

internal void SetHardwareAccelerated(bool enabled) {
internal bool SetHardwareAccelerated(bool enabled) {
bool changed = false;
var activity = GetActivityWithLaunchIntent() as XmlElement;
activity.SetAttribute("android:hardwareAccelerated", (enabled) ? "true" : "false");
Debug.Log(activity.GetAttribute("hardwareAccelerated", AndroidXmlNamespace));
if (activity.GetAttribute("hardwareAccelerated", AndroidXmlNamespace) != ((enabled) ? "true" : "false")) {
Debug.Log("HERE");
activity.SetAttribute("hardwareAccelerated", AndroidXmlNamespace, (enabled) ? "true" : "false");
Debug.Log(activity.GetAttribute("hardwareAccelerated", AndroidXmlNamespace));
changed = true;
}
return changed;
}
}

internal bool SetActivityName(string name) {
bool changed = false;
var activity = GetActivityWithLaunchIntent() as XmlElement;
if (activity.GetAttribute("name", AndroidXmlNamespace) != name) {
activity.SetAttribute("name", AndroidXmlNamespace, name);
changed = true;
}
return changed;
}

internal bool AddCamera() {
bool changed = false;
if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.CAMERA']", nsMgr).Count == 0) {
var elem = CreateElement("uses-permission");
elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.CAMERA"));
ManifestElement.AppendChild(elem);
changed = true;
}
if (SelectNodes("/manifest/uses-feature[@android:name='android.hardware.camera']", nsMgr).Count == 0) {
var elem = CreateElement("uses-feature");
elem.Attributes.Append(CreateAndroidAttribute("name", "android.hardware.camera"));
ManifestElement.AppendChild(elem);
changed = true;
}
return changed;
}
}