├── .gitignore ├── Inf18 ├── AddInNative.cpp ├── AddInNative.h ├── ConversionWchar.cpp ├── ConversionWchar.h ├── Inf18.vcxproj ├── Inf18.vcxproj.filters ├── MainApp.cpp ├── MainApp.h └── pch.h ├── LICENSE ├── README.md ├── android ├── .gitignore ├── .idea │ ├── caches │ │ └── gradle_models.ser │ ├── codeStyles │ │ └── Project.xml │ ├── gradle.xml │ ├── misc.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── app │ ├── .cxx │ │ └── ndk_locator_record.json │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── org │ │ │ └── ripreal │ │ │ └── androidutils │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── cpp │ │ │ ├── CMakeLists.txt │ │ │ └── native-lib.cpp │ │ ├── java │ │ │ └── org │ │ │ │ └── ripreal │ │ │ │ └── androidutils │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApp.java │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── org │ │ └── ripreal │ │ └── androidutils │ │ └── ExampleUnitTest.java ├── assets │ └── icon_180x180.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── androidUtils.sln ├── demo.cf ├── include ├── AddInDefBase.h ├── ComponentBase.h ├── IAndroidComponentHelper.h ├── IMemoryManager.h ├── addinlib.h ├── com.h ├── mobile.h └── types.h ├── jni ├── jnienv.cpp └── jnienv.h └── package ├── ANDROID_MANIFEST_EXTENTIONS.XML └── MANIFEST.XML /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # BITERP defined 5 | *.apk 6 | 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.so 12 | *.zip 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Dd]ebugPublic/ 20 | [Rr]elease/ 21 | [Rr]eleases/ 22 | x64/ 23 | x86/ 24 | bld/ 25 | [Bb]in/ 26 | [Oo]bj/ 27 | [Ll]og/ 28 | 29 | # Visual Studio 2015 cache/options directory 30 | .vs/ 31 | # Uncomment if you have tasks that create the project's static files in wwwroot 32 | #wwwroot/ 33 | 34 | # MSTest test Results 35 | [Tt]est[Rr]esult*/ 36 | [Bb]uild[Ll]og.* 37 | 38 | # NUNIT 39 | *.VisualState.xml 40 | TestResult.xml 41 | 42 | # Build Results of an ATL Project 43 | [Dd]ebugPS/ 44 | [Rr]eleasePS/ 45 | dlldata.c 46 | 47 | # DNX 48 | project.lock.json 49 | project.fragment.lock.json 50 | artifacts/ 51 | 52 | *_i.c 53 | *_p.c 54 | *_i.h 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.tmp_proj 69 | *.log 70 | *.vspscc 71 | *.vssscc 72 | .builds 73 | *.pidb 74 | *.svclog 75 | *.scc 76 | 77 | # Chutzpah Test files 78 | _Chutzpah* 79 | 80 | # Visual C++ cache files 81 | ipch/ 82 | *.aps 83 | *.ncb 84 | *.opendb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | *.VC.db 89 | *.VC.VC.opendb 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | *.sap 96 | 97 | # TFS 2012 Local Workspace 98 | $tf/ 99 | 100 | # Guidance Automation Toolkit 101 | *.gpState 102 | 103 | # ReSharper is a .NET coding add-in 104 | _ReSharper*/ 105 | *.[Rr]e[Ss]harper 106 | *.DotSettings.user 107 | 108 | # JustCode is a .NET coding add-in 109 | .JustCode 110 | 111 | # TeamCity is a build add-in 112 | _TeamCity* 113 | 114 | # DotCover is a Code Coverage Tool 115 | *.dotCover 116 | 117 | # NCrunch 118 | _NCrunch_* 119 | .*crunch*.local.xml 120 | nCrunchTemp_* 121 | 122 | # MightyMoose 123 | *.mm.* 124 | AutoTest.Net/ 125 | 126 | # Web workbench (sass) 127 | .sass-cache/ 128 | 129 | # Installshield output folder 130 | [Ee]xpress/ 131 | 132 | # DocProject is a documentation generator add-in 133 | DocProject/buildhelp/ 134 | DocProject/Help/*.HxT 135 | DocProject/Help/*.HxC 136 | DocProject/Help/*.hhc 137 | DocProject/Help/*.hhk 138 | DocProject/Help/*.hhp 139 | DocProject/Help/Html2 140 | DocProject/Help/html 141 | 142 | # Click-Once directory 143 | publish/ 144 | 145 | # Publish Web Output 146 | *.[Pp]ublish.xml 147 | *.azurePubxml 148 | # TODO: Comment the next line if you want to checkin your web deploy settings 149 | # but database connection strings (with potential passwords) will be unencrypted 150 | #*.pubxml 151 | *.publishproj 152 | 153 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 154 | # checkin your Azure Web App publish settings, but sensitive information contained 155 | # in these scripts will be unencrypted 156 | PublishScripts/ 157 | 158 | # NuGet Packages 159 | *.nupkg 160 | # The packages folder can be ignored because of Package Restore 161 | **/packages/* 162 | # except build/, which is used as an MSBuild target. 163 | !**/packages/build/ 164 | # Uncomment if necessary however generally it will be regenerated when needed 165 | #!**/packages/repositories.config 166 | # NuGet v3's project.json files produces more ignoreable files 167 | *.nuget.props 168 | *.nuget.targets 169 | 170 | # Microsoft Azure Build Output 171 | csx/ 172 | *.build.csdef 173 | 174 | # Microsoft Azure Emulator 175 | ecf/ 176 | rcf/ 177 | 178 | # Windows Store app package directories and files 179 | AppPackages/ 180 | BundleArtifacts/ 181 | Package.StoreAssociation.xml 182 | _pkginfo.txt 183 | 184 | # Visual Studio cache files 185 | # files ending in .cache can be ignored 186 | *.[Cc]ache 187 | # but keep track of directories ending in .cache 188 | !*.[Cc]ache/ 189 | 190 | # Others 191 | ClientBin/ 192 | ~$* 193 | *~ 194 | *.dbmdl 195 | *.dbproj.schemaview 196 | *.jfm 197 | *.pfx 198 | *.publishsettings 199 | node_modules/ 200 | orleans.codegen.cs 201 | 202 | # Since there are multiple workflows, uncomment next line to ignore bower_components 203 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 204 | #bower_components/ 205 | 206 | # RIA/Silverlight projects 207 | Generated_Code/ 208 | 209 | # Backup & report files from converting an old project file 210 | # to a newer Visual Studio version. Backup files are not needed, 211 | # because we have git ;-) 212 | _UpgradeReport_Files/ 213 | Backup*/ 214 | UpgradeLog*.XML 215 | UpgradeLog*.htm 216 | 217 | # SQL Server files 218 | *.mdf 219 | *.ldf 220 | 221 | # Business Intelligence projects 222 | *.rdl.data 223 | *.bim.layout 224 | *.bim_*.settings 225 | 226 | # Microsoft Fakes 227 | FakesAssemblies/ 228 | 229 | # GhostDoc plugin setting file 230 | *.GhostDoc.xml 231 | 232 | # Node.js Tools for Visual Studio 233 | .ntvs_analysis.dat 234 | 235 | # Visual Studio 6 build log 236 | *.plg 237 | 238 | # Visual Studio 6 workspace options file 239 | *.opt 240 | 241 | # Visual Studio LightSwitch build output 242 | **/*.HTMLClient/GeneratedArtifacts 243 | **/*.DesktopClient/GeneratedArtifacts 244 | **/*.DesktopClient/ModelManifest.xml 245 | **/*.Server/GeneratedArtifacts 246 | **/*.Server/ModelManifest.xml 247 | _Pvt_Extensions 248 | 249 | # Paket dependency manager 250 | .paket/paket.exe 251 | paket-files/ 252 | 253 | # FAKE - F# Make 254 | .fake/ 255 | 256 | # JetBrains Rider 257 | 258 | # CodeRush 259 | .cr/ 260 | 261 | # Python Tools for Visual Studio (PTVS) 262 | __pycache__/ 263 | *.pyc 264 | 265 | # 1C:Enterprise database 266 | V8 267 | -------------------------------------------------------------------------------- /Inf18/AddInNative.cpp: -------------------------------------------------------------------------------- 1 |  2 | 3 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 4 | // 5 | // Examples for the report "Making external components for 1C mobile platform for Android"" 6 | // at the conference INFOSTART 2018 EVENT EDUCATION https://event.infostart.ru/2018/ 7 | // 8 | // Sample 1: Delay in code 9 | // Sample 2: Getting device information 10 | // Sample 3: Device blocking: receiving external event about changing of sceen 11 | // 12 | // Copyright: Igor Kisil 2018 13 | // 14 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | #include "AddInNative.h" 17 | #include "ConversionWchar.h" 18 | #include "wchar.h" 19 | #include 20 | #include 21 | #include "../jni/jnienv.h" 22 | #include "../include/IAndroidComponentHelper.h" 23 | 24 | static const wchar_t *g_PropNames[] = 25 | { 26 | L"DeviceInfo", 27 | L"Screen" 28 | }; 29 | 30 | static const wchar_t* g_PropNamesRu[] = 31 | { 32 | L"ОписаниеУстройства", 33 | }; 34 | 35 | static const wchar_t *g_MethodNames[] = 36 | { 37 | L"Delay", 38 | L"StartScreenWatch", 39 | L"StopScreenWatch" 40 | }; 41 | 42 | 43 | static const wchar_t *g_MethodNamesRu[] = 44 | { 45 | L"Пауза", 46 | L"НачатьОтслеживаниеЭкрана", 47 | L"ОстановитьОтслеживаниеЭкрана" 48 | }; 49 | 50 | static const wchar_t g_ComponentNameAddIn[] = L"ANDROIDUTILS"; 51 | static WcharWrapper s_ComponentClass(g_ComponentNameAddIn); 52 | // This component supports 2.1 version 53 | const long g_VersionAddIn = 2100; 54 | static AppCapabilities g_capabilities = eAppCapabilitiesInvalid; 55 | 56 | //---------------------------------------------------------------------------// 57 | long GetClassObject(const WCHAR_T* wsName, IComponentBase** pInterface) 58 | { 59 | if (!*pInterface) 60 | { 61 | *pInterface = new AddInNative(); 62 | return (long)*pInterface; 63 | } 64 | return 0; 65 | } 66 | 67 | //---------------------------------------------------------------------------// 68 | AppCapabilities SetPlatformCapabilities(const AppCapabilities capabilities) 69 | { 70 | g_capabilities = capabilities; 71 | return eAppCapabilitiesLast; 72 | } 73 | 74 | //---------------------------------------------------------------------------// 75 | long DestroyObject(IComponentBase** pInterface) 76 | { 77 | if (!*pInterface) 78 | return -1; 79 | 80 | delete *pInterface; 81 | *pInterface = 0; 82 | return 0; 83 | } 84 | 85 | //---------------------------------------------------------------------------// 86 | const WCHAR_T* GetClassNames() 87 | { 88 | return s_ComponentClass; 89 | } 90 | 91 | AddInNative::AddInNative() : m_iConnect(nullptr), m_iMemory(nullptr), isScreenOn(false) 92 | { 93 | } 94 | 95 | AddInNative::~AddInNative() 96 | { 97 | } 98 | 99 | ///////////////////////////////////////////////////////////////////////////// 100 | // IInitDoneBase 101 | //---------------------------------------------------------------------------// 102 | bool AddInNative::Init(void* pConnection) 103 | { 104 | m_iConnect = (IAddInDefBaseEx*)pConnection; 105 | if (m_iConnect) 106 | { 107 | //stepCounter.setIConnect(m_iConnect); 108 | javaMainApp.Initialize(m_iConnect); 109 | return true; 110 | } 111 | return m_iConnect != nullptr; 112 | } 113 | 114 | //---------------------------------------------------------------------------// 115 | bool AddInNative::setMemManager(void* mem) 116 | { 117 | m_iMemory = (IMemoryManager*)mem; 118 | return m_iMemory != nullptr; 119 | } 120 | 121 | //---------------------------------------------------------------------------// 122 | long AddInNative::GetInfo() 123 | { 124 | return g_VersionAddIn; 125 | } 126 | 127 | //---------------------------------------------------------------------------// 128 | void AddInNative::Done() 129 | { 130 | m_iConnect = nullptr; 131 | m_iMemory = nullptr; 132 | } 133 | 134 | ///////////////////////////////////////////////////////////////////////////// 135 | // ILanguageExtenderBase 136 | //---------------------------------------------------------------------------// 137 | bool AddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) 138 | { 139 | const wchar_t *wsExtension = g_ComponentNameAddIn; 140 | uint32_t iActualSize = static_cast(::wcslen(wsExtension) + 1); 141 | 142 | if (m_iMemory) 143 | { 144 | if (m_iMemory->AllocMemory((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) 145 | { 146 | convToShortWchar(wsExtensionName, wsExtension, iActualSize); 147 | return true; 148 | } 149 | } 150 | 151 | return false; 152 | } 153 | 154 | //---------------------------------------------------------------------------// 155 | long AddInNative::GetNProps() 156 | { 157 | // You may delete next lines and add your own implementation code here 158 | return ePropLast; 159 | } 160 | 161 | //---------------------------------------------------------------------------// 162 | long AddInNative::FindProp(const WCHAR_T* wsPropName) 163 | { 164 | long plPropNum = -1; 165 | wchar_t* propName = 0; 166 | convFromShortWchar(&propName, wsPropName); 167 | 168 | plPropNum = findName(g_PropNames, propName, ePropLast); 169 | 170 | if (plPropNum == -1) 171 | plPropNum = findName(g_PropNamesRu, propName, ePropLast); 172 | 173 | delete[] propName; 174 | return plPropNum; 175 | } 176 | 177 | //---------------------------------------------------------------------------// 178 | const WCHAR_T* AddInNative::GetPropName(long lPropNum, long lPropAlias) 179 | { 180 | if (lPropNum >= ePropLast) 181 | return NULL; 182 | 183 | wchar_t *wsCurrentName = NULL; 184 | WCHAR_T *wsPropName = NULL; 185 | 186 | switch (lPropAlias) 187 | { 188 | case 0: // First language (english) 189 | wsCurrentName = (wchar_t*)g_PropNames[lPropNum]; 190 | break; 191 | case 1: // Second language (local) 192 | wsCurrentName = (wchar_t*)g_PropNamesRu[lPropNum]; 193 | break; 194 | default: 195 | return 0; 196 | } 197 | 198 | uint32_t iActualSize = static_cast(wcslen(wsCurrentName) + 1); 199 | 200 | if (m_iMemory && wsCurrentName) 201 | { 202 | if (m_iMemory->AllocMemory((void**)&wsPropName, iActualSize * sizeof(WCHAR_T))) 203 | convToShortWchar(&wsPropName, wsCurrentName, iActualSize); 204 | } 205 | 206 | return wsPropName; 207 | } 208 | 209 | //---------------------------------------------------------------------------// 210 | bool AddInNative::GetPropVal(const long lPropNum, tVariant* pvarPropVal) 211 | { 212 | switch (lPropNum) 213 | { 214 | // SAMPLE 2 START - Read device manufacturer and model 215 | case ePropDevice: 216 | { 217 | IAndroidComponentHelper* helper = (IAndroidComponentHelper*)m_iConnect->GetInterface(eIAndroidComponentHelper); 218 | pvarPropVal->vt = VTYPE_EMPTY; 219 | if (helper) 220 | { 221 | WCHAR_T* className = nullptr; 222 | convToShortWchar(&className, L"android.os.Build"); 223 | jclass ccloc = helper->FindClass(className); 224 | delete[] className; 225 | className = nullptr; 226 | std::wstring wData{}; 227 | if (ccloc) 228 | { 229 | JNIEnv* env = getJniEnv(); 230 | jfieldID fldID = env->GetStaticFieldID(ccloc, "MANUFACTURER", "Ljava/lang/String;"); 231 | jstring jManufacturer = (jstring)env->GetStaticObjectField(ccloc, fldID); 232 | std::wstring wManufacturer = ToWStringJni(jManufacturer); 233 | env->DeleteLocalRef(jManufacturer); 234 | fldID = env->GetStaticFieldID(ccloc, "MODEL", "Ljava/lang/String;"); 235 | jstring jModel = static_cast(env->GetStaticObjectField(ccloc, fldID)); 236 | std::wstring wModel = ToWStringJni(jModel); 237 | env->DeleteLocalRef(jModel); 238 | if (wManufacturer.length()) 239 | wData = wManufacturer + L": " + wModel; 240 | else 241 | wData = wModel; 242 | env->DeleteLocalRef(ccloc); 243 | } 244 | if (wData.length()) 245 | ToV8String(wData.c_str(), pvarPropVal); 246 | } 247 | return true; 248 | } 249 | default: 250 | return false; 251 | } 252 | } 253 | 254 | //---------------------------------------------------------------------------// 255 | bool AddInNative::SetPropVal(const long lPropNum, tVariant *varPropVal) 256 | { 257 | switch (lPropNum) 258 | { 259 | default: 260 | return false; 261 | } 262 | } 263 | 264 | //---------------------------------------------------------------------------// 265 | bool AddInNative::IsPropReadable(const long lPropNum) 266 | { 267 | return true; 268 | } 269 | 270 | //---------------------------------------------------------------------------// 271 | bool AddInNative::IsPropWritable(const long lPropNum) 272 | { 273 | switch (lPropNum) 274 | { 275 | default: 276 | return false; 277 | } 278 | } 279 | 280 | //---------------------------------------------------------------------------// 281 | long AddInNative::GetNMethods() 282 | { 283 | return eMethLast; 284 | } 285 | 286 | //---------------------------------------------------------------------------// 287 | long AddInNative::FindMethod(const WCHAR_T* wsMethodName) 288 | { 289 | long plMethodNum = -1; 290 | wchar_t* name = 0; 291 | convFromShortWchar(&name, wsMethodName); 292 | 293 | plMethodNum = findName(g_MethodNames, name, eMethLast); 294 | 295 | if (plMethodNum == -1) 296 | plMethodNum = findName(g_MethodNamesRu, name, eMethLast); 297 | 298 | delete[] name; 299 | 300 | return plMethodNum; 301 | } 302 | 303 | //---------------------------------------------------------------------------// 304 | const WCHAR_T* AddInNative::GetMethodName(const long lMethodNum, const long lMethodAlias) 305 | { 306 | if (lMethodNum >= eMethLast) 307 | return NULL; 308 | 309 | wchar_t *wsCurrentName = NULL; 310 | WCHAR_T *wsMethodName = NULL; 311 | 312 | switch (lMethodAlias) 313 | { 314 | case 0: // First language (english) 315 | wsCurrentName = (wchar_t*)g_MethodNames[lMethodNum]; 316 | break; 317 | case 1: // Second language (local) 318 | wsCurrentName = (wchar_t*)g_MethodNamesRu[lMethodNum]; 319 | break; 320 | default: 321 | return 0; 322 | } 323 | 324 | uint32_t iActualSize = static_cast(wcslen(wsCurrentName) + 1); 325 | 326 | if (m_iMemory && wsCurrentName) 327 | { 328 | if (m_iMemory->AllocMemory((void**)&wsMethodName, iActualSize * sizeof(WCHAR_T))) 329 | convToShortWchar(&wsMethodName, wsCurrentName, iActualSize); 330 | } 331 | 332 | return wsMethodName; 333 | } 334 | 335 | //---------------------------------------------------------------------------// 336 | long AddInNative::GetNParams(const long lMethodNum) 337 | { 338 | switch (lMethodNum) 339 | { 340 | case eMethDelay: 341 | return 1; 342 | default: 343 | return 0; 344 | } 345 | } 346 | 347 | //---------------------------------------------------------------------------// 348 | bool AddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) 349 | { 350 | switch (lMethodNum) 351 | { 352 | default: 353 | return false; 354 | } 355 | } 356 | 357 | //---------------------------------------------------------------------------// 358 | bool AddInNative::HasRetVal(const long lMethodNum) 359 | { 360 | switch (lMethodNum) 361 | { 362 | default: 363 | return false; 364 | } 365 | } 366 | 367 | //---------------------------------------------------------------------------// 368 | bool AddInNative::CallAsProc(const long lMethodNum, tVariant* paParams, const long lSizeArray) 369 | { 370 | switch (lMethodNum) 371 | { 372 | // SAMPLE 1 START 373 | case eMethDelay: 374 | { 375 | long lDelay = numericValue(paParams); 376 | if (lDelay > 0) 377 | javaMainApp.sleep(lDelay); 378 | return true; 379 | } 380 | case eMethStartScreenWatch: { 381 | javaMainApp.startScreenWatch(); 382 | return true; 383 | } 384 | case eMethStopScreenWatch: { 385 | javaMainApp.stopScreenWatch(); 386 | return true; 387 | } 388 | default: 389 | return false; 390 | } 391 | } 392 | 393 | //---------------------------------------------------------------------------// 394 | bool AddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) 395 | { 396 | switch (lMethodNum) 397 | { 398 | default: 399 | return false; 400 | } 401 | 402 | return false; 403 | } 404 | 405 | ///////////////////////////////////////////////////////////////////////////// 406 | // ILocaleBase 407 | //---------------------------------------------------------------------------// 408 | void AddInNative::SetLocale(const WCHAR_T* loc) 409 | { 410 | } 411 | 412 | ///////////////////////////////////////////////////////////////////////////// 413 | // Other 414 | 415 | //---------------------------------------------------------------------------// 416 | void AddInNative::addError(uint32_t wcode, const wchar_t* source, const wchar_t* descriptor, long code) 417 | { 418 | if (m_iConnect) 419 | { 420 | WCHAR_T *err = 0; 421 | WCHAR_T *descr = 0; 422 | 423 | convToShortWchar(&err, source); 424 | convToShortWchar(&descr, descriptor); 425 | 426 | m_iConnect->AddError(wcode, err, descr, code); 427 | 428 | delete[] descr; 429 | delete[] err; 430 | } 431 | } 432 | 433 | //---------------------------------------------------------------------------// 434 | long AddInNative::findName(const wchar_t* names[], const wchar_t* name, const uint32_t size) const 435 | { 436 | long ret = -1; 437 | for (uint32_t i = 0; i < size; i++) 438 | { 439 | if (!wcscmp(names[i], name)) 440 | { 441 | ret = i; 442 | break; 443 | } 444 | } 445 | return ret; 446 | } 447 | 448 | void AddInNative::ToV8String(const wchar_t* wstr, tVariant* par) 449 | { 450 | if (wstr) 451 | { 452 | int len = wcslen(wstr); 453 | m_iMemory->AllocMemory((void**)&par->pwstrVal, (len + 1) * sizeof(WCHAR_T)); 454 | convToShortWchar(&par->pwstrVal, wstr); 455 | par->vt = VTYPE_PWSTR; 456 | par->wstrLen = len; 457 | } 458 | else 459 | par->vt = VTYPE_EMPTY; 460 | } 461 | 462 | WCHAR_T* AddInNative::ToV8StringJni(jstring jstr, int* lSize) 463 | { 464 | WCHAR_T* ret = NULL; 465 | if (jstr) 466 | { 467 | JNIEnv *jenv = getJniEnv(); 468 | *lSize = jenv->GetStringLength(jstr); 469 | const WCHAR_T* pjstr = jenv->GetStringChars(jstr, NULL); 470 | m_iMemory->AllocMemory((void**)&ret, (*lSize + 1) * sizeof(WCHAR_T)); 471 | for (auto i = 0; i < *lSize; ++i) 472 | ret[i] = pjstr[i]; 473 | ret[*lSize] = 0; 474 | jenv->ReleaseStringChars(jstr, pjstr); 475 | } 476 | return ret; 477 | } 478 | 479 | bool AddInNative::isNumericParameter(tVariant* par) 480 | { 481 | return par->vt == VTYPE_I4 || par->vt == VTYPE_UI4 || par->vt == VTYPE_R8; 482 | } 483 | 484 | long AddInNative::numericValue(tVariant* par) 485 | { 486 | long ret = 0; 487 | switch (par->vt) 488 | { 489 | case VTYPE_I4: 490 | ret = par->lVal; 491 | break; 492 | case VTYPE_UI4: 493 | ret = par->ulVal; 494 | break; 495 | case VTYPE_R8: 496 | ret = par->dblVal; 497 | break; 498 | } 499 | return ret; 500 | } 501 | 502 | std::wstring AddInNative::ToWStringJni(jstring jstr) 503 | { 504 | std::wstring ret; 505 | if (jstr) 506 | { 507 | JNIEnv* env = getJniEnv(); 508 | const jchar* jChars = env->GetStringChars(jstr, NULL); 509 | jsize jLen = env->GetStringLength(jstr); 510 | ret.assign(jChars, jChars + jLen); 511 | env->ReleaseStringChars(jstr, jChars); 512 | } 513 | return ret; 514 | } -------------------------------------------------------------------------------- /Inf18/AddInNative.h: -------------------------------------------------------------------------------- 1 |  2 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 3 | // 4 | // Examples for the report "Making external components for 1C mobile platform for Android"" 5 | // at the conference INFOSTART 2018 EVENT EDUCATION https://event.infostart.ru/2018/ 6 | // 7 | // Sample 1: Delay in code 8 | // Sample 2: Getting device information 9 | // Sample 3: Device blocking: receiving external event about changing of sceen 10 | // 11 | // Copyright: Igor Kisil 2018 12 | // 13 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | #ifndef __ADDINNATIVE_H__ 16 | #define __ADDINNATIVE_H__ 17 | 18 | #include 19 | #include "../include/ComponentBase.h" 20 | #include "../include/AddInDefBase.h" 21 | #include "../include/IMemoryManager.h" 22 | #include "MainApp.h" 23 | 24 | class AddInNative : public IComponentBase 25 | { 26 | public: 27 | enum Props 28 | { 29 | ePropDevice = 0, 30 | ePropLast // Always last 31 | }; 32 | 33 | enum Methods 34 | { 35 | eMethDelay = 0, // Sample 1 36 | eMethStartScreenWatch, 37 | eMethStopScreenWatch, 38 | eMethLast // Always last 39 | }; 40 | 41 | AddInNative(void); 42 | virtual ~AddInNative(); 43 | // IInitDoneBase 44 | virtual bool ADDIN_API Init(void*); 45 | virtual bool ADDIN_API setMemManager(void* mem); 46 | virtual long ADDIN_API GetInfo(); 47 | virtual void ADDIN_API Done(); 48 | // ILanguageExtenderBase 49 | virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T**); 50 | virtual long ADDIN_API GetNProps(); 51 | virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName); 52 | virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum, long lPropAlias); 53 | virtual bool ADDIN_API GetPropVal(const long lPropNum, tVariant* pvarPropVal); 54 | virtual bool ADDIN_API SetPropVal(const long lPropNum, tVariant* varPropVal); 55 | virtual bool ADDIN_API IsPropReadable(const long lPropNum); 56 | virtual bool ADDIN_API IsPropWritable(const long lPropNum); 57 | virtual long ADDIN_API GetNMethods(); 58 | virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName); 59 | virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum, 60 | const long lMethodAlias); 61 | virtual long ADDIN_API GetNParams(const long lMethodNum); 62 | virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, const long lParamNum, 63 | tVariant *pvarParamDefValue); 64 | virtual bool ADDIN_API HasRetVal(const long lMethodNum); 65 | virtual bool ADDIN_API CallAsProc(const long lMethodNum, 66 | tVariant* paParams, const long lSizeArray); 67 | virtual bool ADDIN_API CallAsFunc(const long lMethodNum, 68 | tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray); 69 | // ILocaleBase 70 | virtual void ADDIN_API SetLocale(const WCHAR_T* loc); 71 | 72 | private: 73 | long findName(const wchar_t* names[], const wchar_t* name, const uint32_t size) const; 74 | void addError(uint32_t wcode, const wchar_t* source, 75 | const wchar_t* descriptor, long code); 76 | 77 | bool isNumericParameter(tVariant*); 78 | long numericValue(tVariant*); 79 | 80 | void ToV8String(const wchar_t* wstr, tVariant*); 81 | WCHAR_T* ToV8StringJni(jstring jstr, int* lSize); 82 | std::wstring ToWStringJni(jstring jstr); 83 | 84 | IAddInDefBaseEx *m_iConnect; 85 | IMemoryManager *m_iMemory; 86 | 87 | // Sample 3 88 | 89 | bool isScreenOn; // current blocking state 90 | MainApp javaMainApp{}; 91 | 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /Inf18/ConversionWchar.cpp: -------------------------------------------------------------------------------- 1 |  2 | #include "ConversionWchar.h" 3 | #include 4 | 5 | //---------------------------------------------------------------------------// 6 | uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len) 7 | { 8 | if (!len) 9 | len = static_cast(::wcslen(Source) + 1); 10 | 11 | if (!*Dest) 12 | *Dest = new WCHAR_T[len]; 13 | 14 | WCHAR_T* tmpShort = *Dest; 15 | wchar_t* tmpWChar = (wchar_t*)Source; 16 | uint32_t res = 0; 17 | 18 | for (; len; --len, ++res, ++tmpWChar, ++tmpShort) 19 | { 20 | *tmpShort = (WCHAR_T)*tmpWChar; 21 | } 22 | 23 | return res; 24 | } 25 | 26 | //---------------------------------------------------------------------------// 27 | uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len) 28 | { 29 | if (!len) 30 | len = getLenShortWcharStr(Source) + 1; 31 | 32 | if (!*Dest) 33 | *Dest = new wchar_t[len]; 34 | 35 | wchar_t* tmpWChar = *Dest; 36 | WCHAR_T* tmpShort = (WCHAR_T*)Source; 37 | uint32_t res = 0; 38 | 39 | for (; len; --len, ++res, ++tmpWChar, ++tmpShort) 40 | { 41 | *tmpWChar = (wchar_t)*tmpShort; 42 | } 43 | 44 | return res; 45 | } 46 | 47 | //---------------------------------------------------------------------------// 48 | uint32_t getLenShortWcharStr(const WCHAR_T* Source) 49 | { 50 | uint32_t res = 0; 51 | WCHAR_T *tmpShort = (WCHAR_T*)Source; 52 | 53 | while (*tmpShort++) 54 | ++res; 55 | 56 | return res; 57 | } 58 | //---------------------------------------------------------------------------// 59 | 60 | 61 | //---------------------------------------------------------------------------// 62 | WcharWrapper::WcharWrapper(const wchar_t* str) : 63 | 64 | #if defined(__APPLE__) || defined(__ANDROID__) 65 | 66 | m_str_WCHAR(NULL), 67 | 68 | #endif //__APPLE__ || __ANDROID__ 69 | 70 | m_str_wchar(NULL) 71 | { 72 | if (str) 73 | { 74 | int len = static_cast(wcslen(str)); 75 | m_str_wchar = new wchar_t[len + 1]; 76 | memset(m_str_wchar, 0, sizeof(wchar_t)* (len + 1)); 77 | memcpy(m_str_wchar, str, sizeof(wchar_t)* len); 78 | 79 | #if defined(__APPLE__) || defined(__ANDROID__) 80 | 81 | convToShortWchar(&m_str_WCHAR, m_str_wchar, len + 1); 82 | 83 | #endif //__APPLE__ || __ANDROID__ 84 | 85 | } 86 | } 87 | 88 | //---------------------------------------------------------------------------// 89 | #if defined(__APPLE__) || defined(__ANDROID__) 90 | 91 | WcharWrapper::WcharWrapper(const WCHAR_T* str) : m_str_WCHAR(NULL), 92 | m_str_wchar(NULL) 93 | { 94 | if (str) 95 | { 96 | int len = getLenShortWcharStr(str); 97 | m_str_WCHAR = new WCHAR_T[len + 1]; 98 | memset(m_str_WCHAR, 0, sizeof(WCHAR_T) * (len + 1)); 99 | memcpy(m_str_WCHAR, str, sizeof(WCHAR_T) * len); 100 | convFromShortWchar(&m_str_wchar, m_str_WCHAR); 101 | } 102 | } 103 | 104 | #endif //__APPLE__ || __ANDROID__ 105 | 106 | //---------------------------------------------------------------------------// 107 | WcharWrapper::~WcharWrapper() 108 | { 109 | 110 | #if defined(__APPLE__) || defined(__ANDROID__) 111 | 112 | if (m_str_WCHAR) 113 | { 114 | delete[] m_str_WCHAR; 115 | m_str_WCHAR = NULL; 116 | } 117 | 118 | #endif //__APPLE__ || __ANDROID__ 119 | 120 | if (m_str_wchar) 121 | { 122 | delete[] m_str_wchar; 123 | m_str_wchar = NULL; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Inf18/ConversionWchar.h: -------------------------------------------------------------------------------- 1 |  2 | #ifndef __CONVERSIONWCHAR_H__ 3 | #define __CONVERSIONWCHAR_H__ 4 | 5 | #include "../include/types.h" 6 | 7 | uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len = 0); 8 | uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len = 0); 9 | uint32_t getLenShortWcharStr(const WCHAR_T* Source); 10 | 11 | class WcharWrapper 12 | { 13 | public: 14 | 15 | WcharWrapper(const WCHAR_T* str); 16 | WcharWrapper(const wchar_t* str); 17 | ~WcharWrapper(); 18 | operator const WCHAR_T*() { return m_str_WCHAR; } 19 | operator WCHAR_T*() { return m_str_WCHAR; } 20 | operator const wchar_t*() { return m_str_wchar; } 21 | operator wchar_t*() { return m_str_wchar; } 22 | private: 23 | WcharWrapper& operator = (const WcharWrapper& other) { return *this; }; 24 | WcharWrapper(const WcharWrapper& other) {}; 25 | private: 26 | 27 | WCHAR_T* m_str_WCHAR; 28 | wchar_t* m_str_wchar; 29 | }; 30 | 31 | #endif //__CONVERSIONWCHAR_H__ 32 | -------------------------------------------------------------------------------- /Inf18/Inf18.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | ARM 7 | 8 | 9 | Release 10 | ARM 11 | 12 | 13 | Debug 14 | ARM64 15 | 16 | 17 | Release 18 | ARM64 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | Debug 30 | x86 31 | 32 | 33 | Release 34 | x86 35 | 36 | 37 | 38 | {ede9ae44-3cd2-48a9-a646-4cde33d50af8} 39 | Android 40 | Inf18 41 | 15.0 42 | Android 43 | 3.0 44 | androidUtils 45 | 46 | 47 | 48 | DynamicLibrary 49 | true 50 | Clang_3_8 51 | 52 | 53 | DynamicLibrary 54 | false 55 | Gcc_4_9 56 | android-27 57 | 58 | 59 | DynamicLibrary 60 | true 61 | Clang_3_8 62 | 63 | 64 | DynamicLibrary 65 | false 66 | Gcc_4_9 67 | android-27 68 | 69 | 70 | DynamicLibrary 71 | true 72 | Clang_3_8 73 | 74 | 75 | DynamicLibrary 76 | false 77 | Clang_3_8 78 | 79 | 80 | DynamicLibrary 81 | true 82 | Clang_3_8 83 | 84 | 85 | DynamicLibrary 86 | false 87 | Gcc_4_9 88 | android-27 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | $(ProjectName)_$(Platform) 103 | 104 | 105 | 106 | 107 | $(ProjectName)_$(Platform) 108 | 109 | 110 | 111 | 112 | $(ProjectName)_$(Platform) 113 | 114 | 115 | 116 | Use 117 | pch.h 118 | 119 | 120 | 121 | 122 | Use 123 | pch.h 124 | 125 | 126 | 127 | 128 | Use 129 | pch.h 130 | 131 | 132 | 133 | 134 | Use 135 | pch.h 136 | c++11 137 | 138 | 139 | 140 | 141 | Use 142 | pch.h 143 | 144 | 145 | 146 | 147 | Use 148 | pch.h 149 | 150 | 151 | 152 | 153 | Use 154 | pch.h 155 | 156 | 157 | 158 | 159 | Use 160 | pch.h 161 | c++11 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /Inf18/Inf18.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | AddIn 7 | 8 | 9 | AddIn 10 | 11 | 12 | AddIn 13 | 14 | 15 | AddIn 16 | 17 | 18 | AddIn 19 | 20 | 21 | AddIn 22 | 23 | 24 | AddIn 25 | 26 | 27 | jni 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {92380699-5d0c-41ae-8c0b-ed56f9897483} 36 | 37 | 38 | {f42f034c-8065-4e18-be22-1d9a04fcd034} 39 | 40 | 41 | {e949da29-184e-4ead-be99-bcca93b63e7c} 42 | 43 | 44 | 45 | 46 | jni 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Package 55 | 56 | 57 | -------------------------------------------------------------------------------- /Inf18/MainApp.cpp: -------------------------------------------------------------------------------- 1 | 2 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 3 | // 4 | // Examples for the report "Making external components for 1C mobile platform for Android"" 5 | // at the conference INFOSTART 2018 EVENT EDUCATION https://event.infostart.ru/2018/ 6 | // 7 | // Sample 1: Delay in code 8 | // Sample 2: Getting device information 9 | // Sample 3: Device blocking: receiving external event about changing of sceen 10 | // 11 | // Copyright: Igor Kisil 2018 12 | // 13 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | #include 16 | #include 17 | #include "MainApp.h" 18 | #include "ConversionWchar.h" 19 | 20 | MainApp::MainApp() : cc(nullptr), obj(nullptr) 21 | { 22 | } 23 | 24 | MainApp::~MainApp() 25 | { 26 | if (obj) 27 | { 28 | stopScreenWatch(); // call to unregister broadcast receiver 29 | JNIEnv *env = getJniEnv(); 30 | env->DeleteGlobalRef(obj); 31 | env->DeleteGlobalRef(cc); 32 | } 33 | } 34 | 35 | void MainApp::Initialize(IAddInDefBaseEx* cnn) 36 | { 37 | if (!obj) 38 | { 39 | IAndroidComponentHelper* helper = (IAndroidComponentHelper*)cnn->GetInterface(eIAndroidComponentHelper); 40 | if (helper) 41 | { 42 | WCHAR_T* className = nullptr; 43 | convToShortWchar(&className, L"org.ripreal.androidutils.MainApp"); 44 | jclass ccloc = helper->FindClass(className); 45 | delete[] className; 46 | className = nullptr; 47 | if (ccloc) 48 | { 49 | JNIEnv* env = getJniEnv(); 50 | cc = static_cast(env->NewGlobalRef(ccloc)); 51 | env->DeleteLocalRef(ccloc); 52 | jobject activity = helper->GetActivity(); 53 | // call of constructor for java class 54 | jmethodID methID = env->GetMethodID(cc, "", "(Landroid/app/Activity;J)V"); 55 | jobject objloc = env->NewObject(cc, methID, activity, (jlong)cnn); 56 | obj = static_cast(env->NewGlobalRef(objloc)); 57 | env->DeleteLocalRef(objloc); 58 | methID = env->GetMethodID(cc, "show", "()V"); 59 | env->CallVoidMethod(obj, methID); 60 | env->DeleteLocalRef(activity); 61 | } 62 | } 63 | } 64 | } 65 | 66 | void MainApp::sleep(long delay) { 67 | std::this_thread::sleep_for(std::chrono::milliseconds(delay)); 68 | } 69 | 70 | void MainApp::startScreenWatch() const 71 | { 72 | if (obj) 73 | { 74 | JNIEnv* env = getJniEnv(); 75 | jmethodID methID = env->GetMethodID(cc, "startScreenWatch", "()V"); 76 | env->CallVoidMethod(obj, methID); 77 | } 78 | } 79 | 80 | void MainApp::stopScreenWatch() const 81 | { 82 | if (obj) 83 | { 84 | JNIEnv* env = getJniEnv(); 85 | jmethodID methID = env->GetMethodID(cc, "stopScreenWatch", "()V"); 86 | env->CallVoidMethod(obj, methID); 87 | } 88 | } 89 | 90 | static const wchar_t g_EventSource[] = L"org.ripreal.androidutils"; 91 | static const wchar_t g_EventName[] = L"LockChanged"; 92 | static WcharWrapper s_EventSource(g_EventSource); 93 | static WcharWrapper s_EventName(g_EventName); 94 | 95 | // name of function built according to Java native call 96 | // 97 | extern "C" JNIEXPORT void JNICALL Java_org_ripreal_androidutils_MainApp_OnLockChanged(JNIEnv* env, jclass jClass, jlong pObject) { 98 | IAddInDefBaseEx *pAddIn = (IAddInDefBaseEx *) pObject; 99 | if (pAddIn != nullptr) { 100 | pAddIn->ExternalEvent(s_EventSource, s_EventName, nullptr); 101 | } 102 | } 103 | 104 | std::wstring MainApp::jstring2wstring(JNIEnv* jenv, jstring aStr) 105 | { 106 | std::wstring result; 107 | 108 | if (aStr) 109 | { 110 | const jchar* pCh = jenv->GetStringChars(aStr, 0); 111 | jsize len = jenv->GetStringLength(aStr); 112 | const jchar* temp = pCh; 113 | while (len > 0) 114 | { 115 | result += *(temp++); 116 | --len; 117 | } 118 | jenv->ReleaseStringChars(aStr, pCh); 119 | } 120 | return result; 121 | } 122 | 123 | void MainApp::setCC(jclass _cc) { 124 | cc = _cc; 125 | } 126 | 127 | void MainApp::setOBJ(jobject _obj) { 128 | obj= _obj; 129 | } 130 | -------------------------------------------------------------------------------- /Inf18/MainApp.h: -------------------------------------------------------------------------------- 1 | 2 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 3 | // 4 | // Examples for the report "Making external components for 1C mobile platform for Android"" 5 | // at the conference INFOSTART 2018 EVENT EDUCATION https://event.infostart.ru/2018/ 6 | // 7 | // Sample 1: Delay in code 8 | // Sample 2: Getting device information 9 | // Sample 3: Device blocking: receiving external event about changing of sceen 10 | // 11 | // Copyright: Igor Kisil 2018 12 | // 13 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | #pragma once 16 | 17 | #include "../include/AddInDefBase.h" 18 | #include "../include/IAndroidComponentHelper.h" 19 | #include "../jni/jnienv.h" 20 | #include "../include/IMemoryManager.h" 21 | #include 22 | 23 | /* Wrapper calling class LockState from java build org.ripreal.androidutils */ 24 | 25 | class MainApp 26 | { 27 | private: 28 | 29 | jclass cc; 30 | jobject obj; 31 | std::wstring jstring2wstring(JNIEnv* jenv, jstring aStr); 32 | 33 | public: 34 | 35 | MainApp(); 36 | ~MainApp(); 37 | 38 | void setCC(jclass _cc); 39 | void setOBJ(jobject _obj); 40 | 41 | void Initialize(IAddInDefBaseEx*); 42 | 43 | void sleep(long delay); 44 | void startScreenWatch() const; // Start monitoring lock state 45 | void stopScreenWatch() const; // End of monitoring 46 | }; -------------------------------------------------------------------------------- /Inf18/pch.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 RIPREAL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Пример (шаблон) внешней компоненты для мобильной платформы 1С 2 | 3 | # Введение 4 | Внешняя компонента с вспомогательными функциями для мобильной платформы 1С на Android. Ид компоненты ANDROIDUTILS. Компонента готова для сборки и поставляется с sln проектом для Visual studio и .android проектом для Android Studio. Причем в Andoird Studio подключена как java, так и С++ часть компоненты, что дает возможность отладки обоих языков! Компонента может быть полезна как в учебных, так и в прикладных целях. 5 | 6 | ## Требования 7 | - Android Studio 3.5 8 | - Visual Studio 2019 9 | - Платформа 1С не ниже 8.3.10 10 | 11 | ## Ограничения 12 | - поддерживается только Android начиная с версии API 22 13 | 14 | ## API 15 | 16 | ### Список методов: 17 | 18 | Delay/Пауза - останавливает выполнение кода на заданное число миллисекунд. Процессор в период простоя не грузится 19 | 20 | Параметры: 21 | 22 | * миллисекунд - Число - число миллисекунд на которое нужно остановить выполнение кода. 23 | 24 | StartScreenWatch/НачатьОтслеживаниеЭкрана - начинает мониторинг состояния активности экрана устройства. Параметры отсутствуют. Если устройство возвращают из спящего режима блокировки, то вызывается внешнее события со следующими параметрами: 25 | 26 | * Источник - org.ripreal.androidutils 27 | * Событие - LockChanged 28 | 29 | StopScreenWatch/ОстановитьОтслеживаниеЭкрана - прекращает мониторинг активности экрана устройства. Параметры отсутствуют. 30 | 31 | ### Список свойств: 32 | 33 | DeviceInfo/ОписаниеУстройства (только чтение) - ид мобильного устройства 34 | 35 | ## Примеры 36 | ### Инициализация компоненты и вызов паузы 37 | ``` bsl 38 | Если ПодключитьВнешнююКомпоненту("ОбщийМакет.Компонента", "RIPREAL", ТипВнешнейКомпоненты.Native) Тогда 39 | Компонента = Новый("AddIn.RIPREAL.ANDROIDUTILS"); 40 | Устройство = Компонента.ОписаниеУстройства; 41 | Компонента.Пауза(3000); // Пауза на 3 секунды 42 | КонецЕсли; 43 | ``` 44 | ### Отслеживание активации устройства через внешнее событие (переход из спящего режима) 45 | 46 | ``` bsl 47 | &НаКлиенте 48 | Процедура НачатьОтслеживаниеЭкрана() 49 | Компонента.НачатьОтслеживаниеЭкрана(); 50 | КонецПроцедуры 51 | 52 | &НаКлиенте 53 | Процедура ВнешнееСобытие(Источник, Событие, Данные) 54 | 55 | Если Источник = "org.ripreal.androidutils" И Событие = "LockChanged" Тогда 56 | ПоказатьПредупреждение(, "Экран разблокирован", 5); 57 | КонецЕсли; 58 | 59 | КонецПроцедуры 60 | ``` 61 | 62 | ## Установка в конфигурацию 63 | Установить в конфигурацию 1С архив с компонентой из папки package. 64 | 65 | ## Разворачивание окружения разработки на Windows 10 66 | 67 | 1. Установить Android Studio 68 | 2. В студии перейти в Tools -> SDK Manager -> SDK Platforms и выбрать ANDROID API 28 69 | 3. В студии перейти в Tools -> SDK Manager -> SDK Tools и выбрать следующее: 70 | * Android SDK build Tools 71 | * Cmake (система сборки C++ кода) 72 | * LLDB (для отладки C++ кода) 73 | * Android Emulator 74 | * Android SDK Platform tools 75 | * Android SDK tools 76 | * Intel x86 Emulator Accelerator (для возможности запуска эмулятора из студии) 77 | * NDK (Для поддержки C++ кода в android проекте) 78 | * Support repository 79 | 4. Скачать систему ассемблерной сборки ninja https://github.com/ninja-build/ninja/releases, установить ее в любой каталог и прописать путь к каталогу в системную переменную Path 80 | 81 | ## Сборка проекта 82 | 83 | 1. Через VS Studio 2019 открыть androidUtils.sln и скомпилировать release версии для ARM и X86 платформы. Перенести скомпилированные .so либы в папку package. 84 | 85 | 2 Через Android Studio не ниже 3.5 открыть каталог android и скомпилировать apk (Build -> Build bundle / APK -> APK) и перенести скомпилированный apk в папку package. 86 | 87 | 3. Заархивировать все файлы в папке package в архив zip 88 | 89 | 4. Загрузить архив в конфигурацию в качестве макета внешней компоненты 90 | 91 | ## Отладка 92 | 93 | Отладка как java, так и c++ части компоненты возможна только в android Studio. Для отладки рекомендуется использовать следующий подход: 94 | 1. Создается юнит-тест в package org.ripreal.android (androidTest) 95 | 2. Тест вызывает из java native функцию C++ 96 | 3. Функция C++ тестирует какой-то нативный метод компоненты 97 | 98 | Пример можно посмотреть здесь [ExampleInstrumentedTest.java](android/app/src/androidTest/java/org/ripreal/androidutils/ExampleInstrumentedTest.java) 99 | 100 | ## Лицензия 101 | 102 | Лицензировано на условиях MIT. Смотрите файл [LICENSE](LICENSE) 103 | 104 | ## Используемые сторонние продукты 105 | 106 | 1. Отстутствуют 107 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | -------------------------------------------------------------------------------- /android/.idea/caches/gradle_models.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ripreal/androidUtils1cExt/4b579e91f4f58f1f6ff72d221fcfec26fba72b0a/android/.idea/caches/gradle_models.ser -------------------------------------------------------------------------------- /android/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | xmlns:android 11 | 12 | ^$ 13 | 14 | 15 | 16 |
17 |
18 | 19 | 20 | 21 | xmlns:.* 22 | 23 | ^$ 24 | 25 | 26 | BY_NAME 27 | 28 |
29 |
30 | 31 | 32 | 33 | .*:id 34 | 35 | http://schemas.android.com/apk/res/android 36 | 37 | 38 | 39 |
40 |
41 | 42 | 43 | 44 | .*:name 45 | 46 | http://schemas.android.com/apk/res/android 47 | 48 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | name 56 | 57 | ^$ 58 | 59 | 60 | 61 |
62 |
63 | 64 | 65 | 66 | style 67 | 68 | ^$ 69 | 70 | 71 | 72 |
73 |
74 | 75 | 76 | 77 | .* 78 | 79 | ^$ 80 | 81 | 82 | BY_NAME 83 | 84 |
85 |
86 | 87 | 88 | 89 | .* 90 | 91 | http://schemas.android.com/apk/res/android 92 | 93 | 94 | ANDROID_ATTRIBUTE_ORDER 95 | 96 |
97 |
98 | 99 | 100 | 101 | .* 102 | 103 | .* 104 | 105 | 106 | BY_NAME 107 | 108 |
109 |
110 |
111 |
112 |
113 |
-------------------------------------------------------------------------------- /android/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | -------------------------------------------------------------------------------- /android/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | -------------------------------------------------------------------------------- /android/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /android/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/app/.cxx/ndk_locator_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "ndkFolder": "D:\\games\\programms\\android_sdk_studio\\ndk-bundle", 3 | "messages": [ 4 | { 5 | "level": "INFO", 6 | "message": "android.ndkVersion from module build.gradle is not set" 7 | }, 8 | { 9 | "level": "INFO", 10 | "message": "ndk.dir in local.properties is D:\\games\\programms\\android_sdk_studio\\ndk-bundle" 11 | }, 12 | { 13 | "level": "INFO", 14 | "message": "ANDROID_NDK_HOME environment variable is D:\\games\\programms\\android_sdk_studio\\ndk-bundle" 15 | }, 16 | { 17 | "level": "INFO", 18 | "message": "sdkFolder is D:\\games\\programms\\android_sdk_studio" 19 | }, 20 | { 21 | "level": "WARN", 22 | "message": "Support for ANDROID_NDK_HOME is deprecated and will be removed in the future. Use android.ndkVersion in build.gradle instead." 23 | }, 24 | { 25 | "level": "INFO", 26 | "message": "Considering D:\\games\\programms\\android_sdk_studio\\ndk-bundle by ndk.dir" 27 | }, 28 | { 29 | "level": "INFO", 30 | "message": "Considering D:\\games\\programms\\android_sdk_studio\\ndk-bundle by ANDROID_NDK_HOME" 31 | }, 32 | { 33 | "level": "INFO", 34 | "message": "Considering D:\\games\\programms\\android_sdk_studio\\ndk-bundle in SDK ndk-bundle folder" 35 | }, 36 | { 37 | "level": "INFO", 38 | "message": "Found requested ndk.dir (D:\\games\\programms\\android_sdk_studio\\ndk-bundle) which has version 20.0.5594570" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "org.ripreal.androidutils" 7 | minSdkVersion 24 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | archivesBaseName = "org_ripreal_androidutils" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | sourceSets { 21 | main { 22 | manifest.srcFile '../app/src/main/AndroidManifest.xml' 23 | assets.srcDirs = ['../assets'] 24 | } 25 | } 26 | compileOptions { 27 | sourceCompatibility 1.8 28 | targetCompatibility 1.8 29 | } 30 | externalNativeBuild { 31 | cmake { 32 | path file('src/main/cpp/CMakeLists.txt') 33 | } 34 | } 35 | } 36 | 37 | dependencies { 38 | implementation fileTree(dir: 'libs', include: ['*.jar']) 39 | implementation 'com.android.support:appcompat-v7:27.1.1' 40 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 41 | testImplementation 'junit:junit:4.12' 42 | testImplementation group: 'org.mockito', name: 'mockito-all', version: '1.10.19' 43 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 44 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 45 | implementation group: 'com.rabbitmq', name: 'amqp-client', version: '5.7.3' 46 | } 47 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /android/app/src/androidTest/java/org/ripreal/androidutils/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package org.ripreal.androidutils; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | 20 | @Test 21 | public void testSleep() { 22 | System.loadLibrary("org_ripreal_androidutils"); 23 | MainApp mainApp = new MainApp(null, 0); 24 | mainApp.testSleep(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /android/app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | 13 | add_library( # Sets the name of the library. 14 | org_ripreal_androidutils 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | native-lib.cpp 21 | ../../../../../Inf18/AddInNative.cpp 22 | ../../../../../jni/jnienv.cpp 23 | ../../../../../Inf18/ConversionWchar.cpp 24 | ../../../../../Inf18/MainApp.cpp) 25 | 26 | 27 | include_directories(../../../../../include) 28 | 29 | # Searches for a specified prebuilt library and stores the path as a 30 | # variable. Because CMake includes system libraries in the search path by 31 | # default, you only need to specify the name of the public NDK library 32 | # you want to add. CMake verifies that the library exists before 33 | # completing its build. 34 | 35 | find_library( # Sets the name of the path variable. 36 | org_ripreal_androidutils 37 | 38 | # Specifies the name of the NDK library that 39 | # you want CMake to locate. 40 | log ) 41 | 42 | # Specifies libraries CMake should link to your target library. You 43 | # can link multiple libraries, such as libraries you define in this 44 | # build script, prebuilt third-party libraries, or system libraries. 45 | 46 | target_link_libraries( # Specifies the target library. 47 | org_ripreal_androidutils 48 | 49 | # Links the target library to the log library 50 | # included in the NDK. 51 | ${org_ripreal_androidutils} ) 52 | -------------------------------------------------------------------------------- /android/app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../../../../Inf18/MainApp.h" 4 | 5 | 6 | extern "C" 7 | JNIEXPORT jstring JNICALL 8 | Java_org_ripreal_androidutils_MainActivity_hello(JNIEnv *env, jobject thiz) { 9 | std::string hello = "Hello from androidutils++"; 10 | return env->NewStringUTF(hello.c_str()); 11 | } 12 | 13 | 14 | extern "C" 15 | JNIEXPORT void JNICALL 16 | Java_org_ripreal_androidutils_MainApp_testScreenActions(JNIEnv *env, jobject objloc) { 17 | jclass ccLoc = env ->GetObjectClass(objloc); 18 | jclass cc = static_cast(env->NewGlobalRef(ccLoc)); 19 | jobject obj = static_cast(env->NewGlobalRef(objloc)); 20 | 21 | MainApp mainApp{}; 22 | mainApp.setCC(cc); 23 | mainApp.setOBJ(obj); 24 | mainApp.startScreenWatch(); 25 | } 26 | 27 | 28 | extern "C" 29 | JNIEXPORT void JNICALL 30 | Java_org_ripreal_androidutils_MainApp_testSleep(JNIEnv *env, jobject objloc) { 31 | jclass ccLoc = env ->GetObjectClass(objloc); 32 | jclass cc = static_cast(env->NewGlobalRef(ccLoc)); 33 | jobject obj = static_cast(env->NewGlobalRef(objloc)); 34 | 35 | MainApp mainApp{}; 36 | mainApp.setCC(cc); 37 | mainApp.setOBJ(obj); 38 | mainApp.sleep(2000); 39 | } -------------------------------------------------------------------------------- /android/app/src/main/java/org/ripreal/androidutils/MainActivity.java: -------------------------------------------------------------------------------- 1 | package org.ripreal.androidutils; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | MainApp mainApp = new MainApp(this, 0); 15 | mainApp.show(); 16 | mainApp.startScreenWatch(); 17 | } 18 | 19 | public void loadLibOnClick(View view) { 20 | // Used to load the 'native-lib' library on application startup. 21 | System.loadLibrary("org_ripreal_androidutils"); 22 | MainApp mainApp = new MainApp(this, 0); 23 | mainApp.testScreenActions(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android/app/src/main/java/org/ripreal/androidutils/MainApp.java: -------------------------------------------------------------------------------- 1 | 2 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 3 | // 4 | // Examples for the report "Making external components for 1C mobile platform for Android"" 5 | // at the conference INFOSTART 2018 EVENT EDUCATION https://event.infostart.ru/2018/ 6 | // 7 | // Sample 1: Delay in code 8 | // Sample 2: Getting device information 9 | // Sample 3: Device blocking: receiving external event about changing of sceen 10 | // 11 | // Copyright: Igor Kisil 2018 12 | // 13 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | package org.ripreal.androidutils; 16 | 17 | import android.app.Activity; 18 | import android.content.BroadcastReceiver; 19 | import android.content.Context; 20 | import android.content.Intent; 21 | import android.content.IntentFilter; 22 | 23 | // SAMPLE 3 24 | 25 | public class MainApp implements Runnable { 26 | 27 | // in C/C++ code the function will have name Java__org_ripreal_androidutils_LockState_OnLockChanged 28 | static native void OnLockChanged(long pObject); 29 | 30 | private long m_V8Object; // 1C application context 31 | private Activity m_Activity; // custom activity of 1C:Enterprise 32 | private BroadcastReceiver m_Receiver; 33 | 34 | public MainApp(Activity activity, long v8Object) 35 | { 36 | m_Activity = activity; 37 | m_V8Object = v8Object; 38 | } 39 | 40 | public void run() 41 | { 42 | System.loadLibrary("org_ripreal_androidutils"); 43 | } 44 | 45 | public void show() 46 | { 47 | m_Activity.runOnUiThread(this); 48 | } 49 | 50 | public void startScreenWatch() 51 | { 52 | if (m_Receiver==null) 53 | { 54 | m_Receiver = new BroadcastReceiver() { 55 | @Override 56 | public void onReceive(Context context, Intent intent) { 57 | switch (intent.getAction()) 58 | { 59 | case Intent.ACTION_SCREEN_ON: 60 | OnLockChanged(m_V8Object); 61 | break; 62 | } 63 | } 64 | }; 65 | 66 | IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); 67 | m_Activity.registerReceiver(m_Receiver, filter); 68 | } 69 | } 70 | 71 | public void stopScreenWatch() 72 | { 73 | if (m_Receiver != null) 74 | { 75 | m_Activity.unregisterReceiver(m_Receiver); 76 | m_Receiver = null; 77 | } 78 | } 79 | 80 | public native void testScreenActions(); 81 | 82 | public native void testSleep(); 83 | } 84 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 |