5package org.qtproject.qt.android;
7import android.content.Context;
8import android.content.res.AssetFileDescriptor;
9import android.content.res.AssetManager;
10import android.os.Build;
11import android.content.pm.ApplicationInfo;
12import android.content.pm.PackageManager;
14import java.io.FileInputStream;
15import java.io.ByteArrayOutputStream;
16import java.io.IOException;
18import java.util.zip.ZipFile;
19import java.util.Enumeration;
20import java.util.zip.ZipEntry;
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.HashSet;
24import java.util.Comparator;
26import android.util.Log;
28import java.nio.channels.FileChannel;
29import java.nio.channels.FileChannel.MapMode;
30import java.nio.MappedByteBuffer;
31import java.nio.ByteOrder;
34class QtApkFileEngine {
35 private final static String QtTAG = QtApkFileEngine.class.getSimpleName();
36 private static String m_appApkPath;
38 private AssetFileDescriptor m_assetFd;
39 private final AssetManager m_assetManager;
40 private FileInputStream m_assetInputStream;
41 private long m_pos = -1;
45 m_assetManager =
context.getAssets();
48 boolean open(
String fileName)
51 m_assetFd = m_assetManager.openNonAssetFd(fileName);
52 m_assetInputStream = m_assetFd.createInputStream();
53 }
catch (IOException e) {
54 Log.e(QtTAG,
"Failed to open the app APK with " + e);
57 return m_assetInputStream !=
null;
63 if (m_assetInputStream !=
null)
64 m_assetInputStream.close();
65 if (m_assetFd !=
null)
67 }
catch (IOException e) {
68 Log.e(QtTAG,
"Failed to close resources with " + e);
71 return m_assetInputStream ==
null && m_assetFd ==
null;
81 if (m_assetInputStream !=
null && m_assetInputStream.markSupported()) {
83 m_assetInputStream.mark(pos);
84 m_assetInputStream.reset();
87 }
catch (IOException ignored) { }
93 MappedByteBuffer getMappedByteBuffer(
long offset,
long size)
96 FileChannel fileChannel = m_assetInputStream.getChannel();
99 mapped.order(ByteOrder.LITTLE_ENDIAN);
103 }
catch (Exception e) {
104 Log.e(QtTAG,
"Failed to map APK file to memory with " + e);
110 byte[] read(
long maxlen)
112 if (m_assetInputStream ==
null)
115 ByteArrayOutputStream outputStream =
new ByteArrayOutputStream();
117 int totalBytesRead = 0;
118 byte[]
buffer =
new byte[1024];
120 while (totalBytesRead < maxlen) {
121 int remainingBytes = (int) maxlen - totalBytesRead;
122 int bytesToRead = Math.min(
buffer.length, remainingBytes);
123 if ((bytesRead = m_assetInputStream.read(
buffer, 0, bytesToRead)) == -1)
125 outputStream.write(
buffer, 0, bytesRead);
126 totalBytesRead += bytesRead;
129 outputStream.close();
130 }
catch (IOException e) {
131 Log.e(QtTAG,
"Failed to read content with " + e);
134 return outputStream.toByteArray();
137 static String getAppApkFilePath()
139 if (m_appApkPath !=
null)
144 PackageManager pm =
context.getPackageManager();
145 ApplicationInfo applicationInfo = pm.getApplicationInfo(
context.getPackageName(), 0);
146 if (applicationInfo.splitSourceDirs !=
null) {
147 m_appApkPath = Arrays.stream(applicationInfo.splitSourceDirs)
148 .filter(
file -> Arrays.stream(Build.SUPPORTED_ABIS)
149 .anyMatch(abi ->
file.endsWith(abi.replace(
'-',
'_') +
".apk")))
153 if (m_appApkPath ==
null)
154 Log.d(QtTAG,
"No ABI specific split APK found, defaulting to the main APK.");
157 if (m_appApkPath ==
null)
158 m_appApkPath = applicationInfo.sourceDir;
159 }
catch (PackageManager.NameNotFoundException e) {
160 Log.e(QtTAG,
"Failed to get the app APK path with " + e);
166 static class JFileInfo
173 static ArrayList<JFileInfo> getApkFileInfos(
String apkPath)
175 ArrayList<JFileInfo> fileInfos =
new ArrayList<>();
176 HashSet<String> dirSet =
new HashSet<>();
177 HashSet<String> allDirsSet =
new HashSet<>();
179 try (ZipFile zipFile =
new ZipFile(apkPath)) {
180 Enumeration<? extends ZipEntry> enumerator = zipFile.entries();
181 while (enumerator.hasMoreElements()) {
182 ZipEntry
entry = enumerator.nextElement();
186 if (
name.startsWith(
"lib/")) {
187 JFileInfo
info =
new JFileInfo();
188 info.relativePath =
name;
189 info.isDir =
entry.isDirectory();
190 info.size =
entry.getSize();
194 dirSet.add(
name.substring(0,
name.lastIndexOf(
"/") + 1));
207 for (
String dir : allDirsSet) {
208 JFileInfo
info =
new JFileInfo();
209 info.relativePath = dir;
216 fileInfos.sort(Comparator.comparing(
info ->
info.relativePath));
217 }
catch (Exception e) {
218 Log.e(QtTAG,
"Failed to list App's APK files with " + e);
static const QString context()
QFuture< QtPrivate::MapResultType< Sequence, MapFunctor > > mapped(QThreadPool *pool, Sequence &&sequence, MapFunctor &&map)
GLenum GLuint GLintptr GLsizeiptr size
GLenum GLuint GLintptr offset
GLsizei const GLchar *const * path
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
EGLImageKHR EGLint * name