我有一个使用JOGL进行OpenGL图形的Android应用程序。该应用程序是GearsTestDemo,用于其他地方进行测试。该应用程序在两个不同的平板设备上运行并显示,一个运行4.4.2,另一个运行4.1.2。我正在尝试添加文件访问权限。我有清单文件中指定的写入和读取权限。我可以写入本地应用程序存储(在获得正确的上下文之后)。当我尝试写入外部存储时,我打开失败:EACCES(权限被拒绝)。下面给出了一个logcat输出片段,显示错误。由于权限似乎在清单中正确设置,似乎JOGL以某种方式干扰了应用程序的编写能力。任何建议将不胜感激。
这是清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gdeb.tango.JOGL_GearsTest"
android:versionCode="19"
android:versionName="1.9" >
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="20"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:description="@string/app_descr"
android:persistent="false"
>
<activity android:name="com.gdeb.tango.JOGL_GearsTest.JOGL_GearsTestActivityLauncher"
android:theme="@android:style/Theme.NoDisplay"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
这是活动代码
/**
* Copyright 2011 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.gdeb.tango.JOGL_GearsTest;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
import com.jogamp.common.util.InterruptSource;
import com.jogamp.newt.event.MonitorEvent;
import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;
import android.os.Bundle;
import android.util.Log;
// KRF
// test of android log4j
//import de.mindpipe.android.logging.log4j.LogConfigurator;
import android.os.Environment;
import java.io.File;
//import org.apache.log4j.Level;
import java.io.OutputStream;
import java.io.FileOutputStream;
import android.content.Context;
//public class NEWTGearsES2Activity extends NewtBaseActivity {
public class JOGL_GearsTestActivity extends NewtBaseActivity {
//static String TAG = "NEWTGearsES2Activity";
static String TAG = "JOGLGearsTestActivity";
static final String forceRGBA5650 = "demo.force.rgba5650";
static final String forceECT = "demo.force.ect";
static final String forceKillProcessTest = "demo.force.killProcessTest";
// KRF
// private LogConfigurator logConfigurator;
@Override
public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
// KRF
// logConfigurator = new LogConfigurator();
//// dump
//Log.d(TAG, Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "gears_test.txt");
// logConfigurator.setFileName(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "gears_test.txt");
// // Set the root log level
// logConfigurator.setRootLevel(Level.DEBUG);
// // Set log level of a specific logger
// logConfigurator.setLevel("org.apache", Level.ERROR);
// logConfigurator.setLevel("com.gdeb", Level.INFO);
// logConfigurator.configure();
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
if( null != System.getProperty(forceRGBA5650) ) {
Log.d(TAG, "forceRGBA5650");
caps.setRedBits(5); caps.setGreenBits(6); caps.setBlueBits(5);
}
Log.d(TAG, "req caps: "+caps);
final GLWindow glWindow = GLWindow.create(caps);
glWindow.setFullscreen(true);
setContentView(getWindow(), glWindow);
//final GearsES2 demo = new GearsES2(-1);
final GearsES2 demo = new GearsES2();
// demo.enableAndroidTrace(true);
glWindow.addGLEventListener(demo);
glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
@Override
public void monitorModeChangeNotify(final MonitorEvent me) { }
@Override
public void monitorModeChanged(final MonitorEvent me, final boolean success) {
System.err.println("MonitorMode Changed (success "+success+"): "+me);
}
});
if( null != System.getProperty(forceKillProcessTest) ) {
Log.d(TAG, "not forceKillProcessTest");
}
else {
Log.d(TAG, "forceKillProcessTest");
}
Log.d(TAG, "force forceKillProcessTest");
glWindow.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(final MouseEvent e) {
if( e.getPointerCount() == 3 ) {
Log.d(TAG, "MemoryHog");
new InterruptSource.Thread(null, new Runnable() {
public void run() {
final ArrayList<Buffer> buffers = new ArrayList<Buffer>();
while(true) {
//final int halfMB = 512 * 1024;
final int tenMB = 10 * 1024 * 1024;
final float osizeMB = buffers.size() * 10.0f;
final float nsizeMB = osizeMB + 10.0f;
System.err.println("MemoryHog: ****** +4k: "+osizeMB+" MB +"+nsizeMB+" MB - Try");
//buffers.add(ByteBuffer.allocateDirect(halfMB)); // 0.5 MB each
buffers.add(ByteBuffer.allocateDirect(tenMB)); // 10.0 MB each
System.err.println("MemoryHog: ****** +4k: "+osizeMB+" MB +"+nsizeMB+" MB - Done");
try {
Thread.sleep(200);
} catch (final Exception e) { e.printStackTrace(); };
}
} }, "MemoryHog").start();
} else if( e.getPointerCount() == 4 ) {
Log.d(TAG, "ForceKill");
android.os.Process.killProcess( android.os.Process.myPid() );
}
}
});
//}
final Animator animator = new Animator(glWindow);
// animator.setRunAsFastAsPossible(true);
// glWindow.setSkipContextReleaseThread(animator.getThread());
if( null != System.getProperty(forceECT) ) {
Log.d(TAG, "forceECT");
animator.setExclusiveContext(true);
}
glWindow.setVisible(true);
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
//================================
// KRF
// ??? filenotfound error, permissions?
Log.d(TAG, Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "markar" + File.separator + "test1.txt");
File tFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "markar" + File.separator + "test1.txt");
//File tFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test.txt");
try {
OutputStream outS = new FileOutputStream(tFile);
outS.write((int) 5);
outS.close();
Log.d(TAG, "writing to external test.txt");
} catch (final Exception e) { e.printStackTrace(); };
// Try internal storage
try {
//File tLFile = this.getFileStreamPath("test.txt");
//Log.d(TAG, tLFile.getAbsolutePath());
//OutputStream outLS = new FileOutputStream(tLFile);
//Context ctx = createPackageContext("com.gdeb.tango.JOGL_GearsTest", CONTEXT_IGNORE_SECURITY);
Context ctx = getActivity().getApplicationContext();
OutputStream outLS = ctx.openFileOutput("test.txt",MODE_PRIVATE);
outLS.write((int) 5);
outLS.close();
Log.d(TAG, "writing to internal test.txt");
} catch (final Exception e) { e.printStackTrace(); };
// Checks if external storage is available for read and write
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
Log.d(TAG, "External storage available");
}
else {
Log.d(TAG, "External storage NOT available");
}
// Checks if external storage is available to at least read
String st = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(st) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(st)) {
Log.d(TAG, "External storage readable");
}
else {
Log.d(TAG, "External storage NOT readable");
}
//================================
Log.d(TAG, "onCreate - X");
}
}
这是logcat输出的片段,显示错误。请注意,这指向onCreate(JOGL_GearsTestActivity.java:176)作为错误的来源。
...
...
04-15 14:26:36.023: W/System.err(7281): GLWindow.setVisibleActionPost(true, false) main-Display-.android_nil-1-EDT-5, start
04-15 14:26:36.023: W/System.err(7281): GLWindow.setVisibleActionPost(true, false) main-Display-.android_nil-1-EDT-5, fin: dt 0.144334ms
04-15 14:26:36.023: W/System.err(7281): Window setVisible: END (main-Display-.android_nil-1-EDT-5) state [visible, autopos, fullscreen, ], nativeWindowCreated: false, madeVisible: -1, geom 0/0 0x0, windowHandle 0x0
04-15 14:26:36.023: W/System.err(7281): GLWindow.resetCounter() main-Display-.android_nil-1-EDT-5
04-15 14:26:36.024: D/JOGLGearsTestActivity(7281): /storage/emulated/0/markar/test1.txt
04-15 14:26:36.024: W/System.err(7281): java.io.FileNotFoundException: /storage/emulated/0/markar/test1.txt: open failed: EACCES (Permission denied)
04-15 14:26:36.024: W/System.err(7281): at libcore.io.IoBridge.open(IoBridge.java:409)
04-15 14:26:36.024: W/System.err(7281): at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
04-15 14:26:36.025: W/System.err(7281): at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
04-15 14:26:36.025: W/System.err(7281): at com.gdeb.tango.JOGL_GearsTest.JOGL_GearsTestActivity.onCreate(JOGL_GearsTestActivity.java:176)
04-15 14:26:36.025: W/System.err(7281): at java.lang.reflect.Method.invoke(Native Method)
04-15 14:26:36.025: W/System.err(7281): at jogamp.android.launcher.ActivityLauncher.callMethod(ActivityLauncher.java:237)
04-15 14:26:36.025: W/System.err(7281): at jogamp.android.launcher.ActivityLauncher.onCreate(ActivityLauncher.java:91)
04-15 14:26:36.025: W/System.err(7281): at android.app.Activity.performCreate(Activity.java:5231)
04-15 14:26:36.025: W/System.err(7281): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
04-15 14:26:36.025: W/System.err(7281): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2160)
04-15 14:26:36.025: W/System.err(7281): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2246)
04-15 14:26:36.025: W/System.err(7281): at android.app.ActivityThread.access$800(ActivityThread.java:136)
04-15 14:26:36.026: W/System.err(7281): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1197)
04-15 14:26:36.026: W/System.err(7281): at android.os.Handler.dispatchMessage(Handler.java:102)
04-15 14:26:36.026: W/System.err(7281): at android.os.Looper.loop(Looper.java:136)
04-15 14:26:36.026: W/System.err(7281): at android.app.ActivityThread.main(ActivityThread.java:5030)
04-15 14:26:36.026: W/System.err(7281): at java.lang.reflect.Method.invoke(Native Method)
04-15 14:26:36.026: W/System.err(7281): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
04-15 14:26:36.026: W/System.err(7281): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
04-15 14:26:36.026: W/System.err(7281): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
04-15 14:26:36.026: W/System.err(7281): at libcore.io.Posix.open(Native Method)
04-15 14:26:36.026: W/System.err(7281): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
04-15 14:26:36.027: W/System.err(7281): at libcore.io.IoBridge.open(IoBridge.java:393)
04-15 14:26:36.027: W/System.err(7281): ... 18 more
04-15 14:26:36.027: D/JOGLGearsTestActivity(7281): writing to internal test.txt
04-15 14:26:36.028: D/JOGLGearsTestActivity(7281): External storage available
04-15 14:26:36.028: D/JOGLGearsTestActivity(7281): External storage readable
04-15 14:26:36.028: D/JOGLGearsTestActivity(7281): onCreate - X
04-15 14:26:36.029: D/JogAmp-ActivityLauncher(7281): onCreate - X
04-15 14:26:36.029: D/JogAmp-ActivityLauncher(7281): onStart - S
...
...
是的,外部存储显示为getExternalStorageState()可读。 是的,存在外部文件“markar”中指定的中间目录 我在onCreate()的另一个项目中剪切/粘贴此代码,它工作正常。 使用Eclipse。通过USB连接到ADB设备,作为媒体设备连接。 JOGL问题?