2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "AndroidAppFile.h"
13 #include "utils/URIUtils.h"
14 #include "utils/log.h"
16 #include "platform/android/activity/XBMCApp.h"
18 #include <android/bitmap.h>
19 #include <androidjni/Bitmap.h>
20 #include <androidjni/BitmapDrawable.h>
21 #include <androidjni/Build.h>
22 #include <androidjni/Canvas.h>
23 #include <androidjni/Context.h>
24 #include <androidjni/DisplayMetrics.h>
25 #include <androidjni/Drawable.h>
26 #include <androidjni/PackageManager.h>
27 #include <androidjni/Resources.h>
30 using namespace XFILE
;
32 CFileAndroidApp::CFileAndroidApp(void)
38 CFileAndroidApp::~CFileAndroidApp(void)
43 bool CFileAndroidApp::Open(const CURL
& url
)
46 m_packageName
= URIUtils::GetFileName(url
.Get());
47 m_packageName
= m_packageName
.substr(0, m_packageName
.size() - 4);
49 const std::vector
<androidPackage
> applications
= CXBMCApp::Get().GetApplications();
50 for (const auto& i
: applications
)
52 if (i
.packageName
== m_packageName
)
54 m_packageLabel
= i
.packageLabel
;
63 bool CFileAndroidApp::Exists(const CURL
& url
)
65 std::string appname
= URIUtils::GetFileName(url
.Get());
66 appname
= appname
.substr(0, appname
.size() - 4);
68 const std::vector
<androidPackage
> applications
= CXBMCApp::Get().GetApplications();
69 for (const auto& i
: applications
)
71 if (i
.packageName
== appname
)
81 CJNIBitmap
GetBitmapFromDrawable(CJNIDrawable
& drawable
)
83 CJNIBitmap bmp
= CJNIBitmap::createBitmap(drawable
.getIntrinsicWidth(),
84 drawable
.getIntrinsicHeight(), CJNIBitmap::ARGB_8888
);
85 CJNICanvas
canvas(bmp
);
87 drawable
.setBounds(0, 0, canvas
.getWidth(), canvas
.getHeight());
88 drawable
.draw(canvas
);
95 unsigned int CFileAndroidApp::ReadIcon(unsigned char** lpBuf
, unsigned int* width
, unsigned int* height
)
97 JNIEnv
* env
= xbmc_jnienv();
98 void *bitmapBuf
= NULL
;
99 int densities
[] = { CJNIDisplayMetrics::DENSITY_XXXHIGH
, CJNIDisplayMetrics::DENSITY_XXHIGH
, CJNIDisplayMetrics::DENSITY_XHIGH
, -1 };
102 jclass cBmpDrw
= env
->FindClass("android/graphics/drawable/BitmapDrawable");
103 jclass cAidDrw
= CJNIBase::GetSDKVersion() >= 26
104 ? env
->FindClass("android/graphics/drawable/AdaptiveIconDrawable")
109 CJNIResources res
= CJNIContext::GetPackageManager().getResourcesForApplication(m_packageName
);
112 for (int i
=0; densities
[i
] != -1 && !bmp
; ++i
)
114 int density
= densities
[i
];
115 CJNIDrawable drw
= res
.getDrawableForDensity(m_icon
, density
);
116 if (xbmc_jnienv()->ExceptionCheck())
117 xbmc_jnienv()->ExceptionClear();
121 if (env
->IsInstanceOf(drw
.get_raw(), cBmpDrw
))
123 CJNIBitmapDrawable resbmp
= drw
;
125 bmp
= resbmp
.getBitmap();
127 else if (cAidDrw
&& env
->IsInstanceOf(drw
.get_raw(), cAidDrw
))
129 bmp
= GetBitmapFromDrawable(drw
);
138 CJNIDrawable drw
= CJNIContext::GetPackageManager().getApplicationIcon(m_packageName
);
139 if (xbmc_jnienv()->ExceptionCheck())
140 xbmc_jnienv()->ExceptionClear();
144 if (env
->IsInstanceOf(drw
.get_raw(), cBmpDrw
))
146 CJNIBitmapDrawable resbmp
= drw
;
148 bmp
= resbmp
.getBitmap();
150 else if (cAidDrw
&& env
->IsInstanceOf(drw
.get_raw(), cAidDrw
))
152 bmp
= GetBitmapFromDrawable(drw
);
159 AndroidBitmapInfo info
;
160 AndroidBitmap_getInfo(env
, bmp
.get_raw(), &info
);
162 if (!info
.width
|| !info
.height
)
165 if (info
.stride
!= info
.width
* 4)
167 CLog::Log(LOGWARNING
, "CFileAndroidApp::ReadIcon: Unsupported icon format {}", info
.format
);
171 AndroidBitmap_lockPixels(env
, bmp
.get_raw(), &bitmapBuf
);
174 const int imgsize
= info
.width
* info
.height
* 4;
175 *lpBuf
= new unsigned char[imgsize
];
177 *height
= info
.height
;
179 memcpy(*lpBuf
, bitmapBuf
, imgsize
);
180 AndroidBitmap_unlockPixels(env
, bmp
.get_raw());
187 void CFileAndroidApp::Close()
191 int CFileAndroidApp::GetChunkSize()
195 int CFileAndroidApp::Stat(const CURL
& url
, struct __stat64
* buffer
)
199 int CFileAndroidApp::IoControl(EIoControl request
, void* param
)
201 if(request
== IOCTRL_SEEK_POSSIBLE
)