线上ab
This commit is contained in:
parent
048673a261
commit
d2b48e6f8d
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,3 +13,5 @@
|
|||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
.cxx
|
.cxx
|
||||||
local.properties
|
local.properties
|
||||||
|
/app/release/
|
||||||
|
/app/debug/
|
||||||
|
|||||||
3
.idea/.gitignore
generated
vendored
3
.idea/.gitignore
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
1
.idea/.name
generated
1
.idea/.name
generated
@ -1 +0,0 @@
|
|||||||
CakePainting Helper
|
|
||||||
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompilerConfiguration">
|
|
||||||
<bytecodeTargetLevel target="21" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
440
.idea/dbnavigator.xml
generated
440
.idea/dbnavigator.xml
generated
@ -1,440 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DBNavigator.Project.DDLFileAttachmentManager">
|
|
||||||
<mappings />
|
|
||||||
<preferences />
|
|
||||||
</component>
|
|
||||||
<component name="DBNavigator.Project.DatabaseAssistantManager">
|
|
||||||
<assistants />
|
|
||||||
</component>
|
|
||||||
<component name="DBNavigator.Project.DatabaseFileManager">
|
|
||||||
<open-files />
|
|
||||||
</component>
|
|
||||||
<component name="DBNavigator.Project.Settings">
|
|
||||||
<connections />
|
|
||||||
<browser-settings>
|
|
||||||
<general>
|
|
||||||
<display-mode value="TABBED" />
|
|
||||||
<navigation-history-size value="100" />
|
|
||||||
<show-object-details value="false" />
|
|
||||||
<enable-sticky-paths value="true" />
|
|
||||||
<enable-quick-filters value="false" />
|
|
||||||
</general>
|
|
||||||
<filters>
|
|
||||||
<object-type-filter>
|
|
||||||
<object-type name="SCHEMA" enabled="true" />
|
|
||||||
<object-type name="USER" enabled="true" />
|
|
||||||
<object-type name="ROLE" enabled="true" />
|
|
||||||
<object-type name="PRIVILEGE" enabled="true" />
|
|
||||||
<object-type name="CHARSET" enabled="true" />
|
|
||||||
<object-type name="TABLE" enabled="true" />
|
|
||||||
<object-type name="VIEW" enabled="true" />
|
|
||||||
<object-type name="JSON_VIEW" enabled="true" />
|
|
||||||
<object-type name="MATERIALIZED_VIEW" enabled="true" />
|
|
||||||
<object-type name="NESTED_TABLE" enabled="true" />
|
|
||||||
<object-type name="COLUMN" enabled="true" />
|
|
||||||
<object-type name="INDEX" enabled="true" />
|
|
||||||
<object-type name="CONSTRAINT" enabled="true" />
|
|
||||||
<object-type name="DATASET_TRIGGER" enabled="true" />
|
|
||||||
<object-type name="DATABASE_TRIGGER" enabled="true" />
|
|
||||||
<object-type name="SYNONYM" enabled="true" />
|
|
||||||
<object-type name="SEQUENCE" enabled="true" />
|
|
||||||
<object-type name="PROCEDURE" enabled="true" />
|
|
||||||
<object-type name="FUNCTION" enabled="true" />
|
|
||||||
<object-type name="PACKAGE" enabled="true" />
|
|
||||||
<object-type name="TYPE" enabled="true" />
|
|
||||||
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
|
|
||||||
<object-type name="ARGUMENT" enabled="true" />
|
|
||||||
<object-type name="JAVA_CLASS" enabled="true" />
|
|
||||||
<object-type name="JAVA_FIELD" enabled="true" />
|
|
||||||
<object-type name="JAVA_METHOD" enabled="true" />
|
|
||||||
<object-type name="JAVA_RESOURCE" enabled="true" />
|
|
||||||
<object-type name="DIMENSION" enabled="true" />
|
|
||||||
<object-type name="CLUSTER" enabled="true" />
|
|
||||||
<object-type name="DBLINK" enabled="true" />
|
|
||||||
<object-type name="CREDENTIAL" enabled="true" />
|
|
||||||
<object-type name="AI_PROFILE" enabled="true" />
|
|
||||||
</object-type-filter>
|
|
||||||
</filters>
|
|
||||||
<sorting>
|
|
||||||
<object-type name="COLUMN" sorting-type="NAME" />
|
|
||||||
<object-type name="FUNCTION" sorting-type="NAME" />
|
|
||||||
<object-type name="PROCEDURE" sorting-type="NAME" />
|
|
||||||
<object-type name="ARGUMENT" sorting-type="POSITION" />
|
|
||||||
<object-type name="TYPE ATTRIBUTE" sorting-type="POSITION" />
|
|
||||||
</sorting>
|
|
||||||
<default-editors>
|
|
||||||
<object-type name="VIEW" editor-type="SELECTION" />
|
|
||||||
<object-type name="PACKAGE" editor-type="SELECTION" />
|
|
||||||
<object-type name="TYPE" editor-type="SELECTION" />
|
|
||||||
</default-editors>
|
|
||||||
</browser-settings>
|
|
||||||
<navigation-settings>
|
|
||||||
<lookup-filters>
|
|
||||||
<lookup-objects>
|
|
||||||
<object-type name="SCHEMA" enabled="true" />
|
|
||||||
<object-type name="USER" enabled="false" />
|
|
||||||
<object-type name="ROLE" enabled="false" />
|
|
||||||
<object-type name="PRIVILEGE" enabled="false" />
|
|
||||||
<object-type name="CHARSET" enabled="false" />
|
|
||||||
<object-type name="TABLE" enabled="true" />
|
|
||||||
<object-type name="VIEW" enabled="true" />
|
|
||||||
<object-type name="JSON VIEW" enabled="true" />
|
|
||||||
<object-type name="MATERIALIZED VIEW" enabled="true" />
|
|
||||||
<object-type name="INDEX" enabled="true" />
|
|
||||||
<object-type name="CONSTRAINT" enabled="true" />
|
|
||||||
<object-type name="DATASET TRIGGER" enabled="true" />
|
|
||||||
<object-type name="DATABASE TRIGGER" enabled="true" />
|
|
||||||
<object-type name="SYNONYM" enabled="false" />
|
|
||||||
<object-type name="SEQUENCE" enabled="true" />
|
|
||||||
<object-type name="PROCEDURE" enabled="true" />
|
|
||||||
<object-type name="FUNCTION" enabled="true" />
|
|
||||||
<object-type name="PACKAGE" enabled="true" />
|
|
||||||
<object-type name="TYPE" enabled="true" />
|
|
||||||
<object-type name="JAVA CLASS" enabled="true" />
|
|
||||||
<object-type name="INNER CLASS" enabled="true" />
|
|
||||||
<object-type name="JAVA FIELD" enabled="true" />
|
|
||||||
<object-type name="JAVA METHOD" enabled="true" />
|
|
||||||
<object-type name="JAVA PARAMETER" enabled="true" />
|
|
||||||
<object-type name="JAVA RESOURCE" enabled="true" />
|
|
||||||
<object-type name="DIMENSION" enabled="false" />
|
|
||||||
<object-type name="CLUSTER" enabled="false" />
|
|
||||||
<object-type name="DBLINK" enabled="true" />
|
|
||||||
<object-type name="CREDENTIAL" enabled="false" />
|
|
||||||
</lookup-objects>
|
|
||||||
<force-database-load value="false" />
|
|
||||||
<prompt-connection-selection value="true" />
|
|
||||||
<prompt-schema-selection value="true" />
|
|
||||||
</lookup-filters>
|
|
||||||
</navigation-settings>
|
|
||||||
<dataset-grid-settings>
|
|
||||||
<general>
|
|
||||||
<enable-zooming value="true" />
|
|
||||||
<enable-column-tooltip value="true" />
|
|
||||||
</general>
|
|
||||||
<sorting>
|
|
||||||
<nulls-first value="true" />
|
|
||||||
<max-sorting-columns value="4" />
|
|
||||||
</sorting>
|
|
||||||
<audit-columns>
|
|
||||||
<column-names value="" />
|
|
||||||
<visible value="true" />
|
|
||||||
<editable value="false" />
|
|
||||||
</audit-columns>
|
|
||||||
</dataset-grid-settings>
|
|
||||||
<dataset-editor-settings>
|
|
||||||
<text-editor-popup>
|
|
||||||
<active value="false" />
|
|
||||||
<active-if-empty value="false" />
|
|
||||||
<data-length-threshold value="100" />
|
|
||||||
<popup-delay value="1000" />
|
|
||||||
</text-editor-popup>
|
|
||||||
<values-actions-popup>
|
|
||||||
<show-popup-button value="true" />
|
|
||||||
<element-count-threshold value="1000" />
|
|
||||||
<data-length-threshold value="250" />
|
|
||||||
</values-actions-popup>
|
|
||||||
<general>
|
|
||||||
<fetch-block-size value="100" />
|
|
||||||
<fetch-timeout value="30" />
|
|
||||||
<trim-whitespaces value="true" />
|
|
||||||
<convert-empty-strings-to-null value="true" />
|
|
||||||
<select-content-on-cell-edit value="true" />
|
|
||||||
<large-value-preview-active value="true" />
|
|
||||||
</general>
|
|
||||||
<filters>
|
|
||||||
<prompt-filter-dialog value="true" />
|
|
||||||
<default-filter-type value="BASIC" />
|
|
||||||
</filters>
|
|
||||||
<qualified-text-editor text-length-threshold="300">
|
|
||||||
<content-types>
|
|
||||||
<content-type name="Text" enabled="true" />
|
|
||||||
<content-type name="Properties" enabled="true" />
|
|
||||||
<content-type name="XML" enabled="true" />
|
|
||||||
<content-type name="DTD" enabled="true" />
|
|
||||||
<content-type name="HTML" enabled="true" />
|
|
||||||
<content-type name="XHTML" enabled="true" />
|
|
||||||
<content-type name="Java" enabled="true" />
|
|
||||||
<content-type name="SQL" enabled="true" />
|
|
||||||
<content-type name="PL/SQL" enabled="true" />
|
|
||||||
<content-type name="JSON" enabled="true" />
|
|
||||||
<content-type name="JSON5" enabled="true" />
|
|
||||||
<content-type name="Groovy" enabled="true" />
|
|
||||||
<content-type name="AIDL" enabled="true" />
|
|
||||||
<content-type name="YAML" enabled="true" />
|
|
||||||
<content-type name="Manifest" enabled="true" />
|
|
||||||
</content-types>
|
|
||||||
</qualified-text-editor>
|
|
||||||
<record-navigation>
|
|
||||||
<navigation-target value="VIEWER" />
|
|
||||||
</record-navigation>
|
|
||||||
</dataset-editor-settings>
|
|
||||||
<code-editor-settings>
|
|
||||||
<general>
|
|
||||||
<show-object-navigation-gutter value="false" />
|
|
||||||
<show-spec-declaration-navigation-gutter value="true" />
|
|
||||||
<enable-spellchecking value="true" />
|
|
||||||
<enable-reference-spellchecking value="false" />
|
|
||||||
</general>
|
|
||||||
<confirmations>
|
|
||||||
<save-changes value="false" />
|
|
||||||
<revert-changes value="true" />
|
|
||||||
<exit-on-changes value="ASK" />
|
|
||||||
</confirmations>
|
|
||||||
</code-editor-settings>
|
|
||||||
<code-completion-settings>
|
|
||||||
<filters>
|
|
||||||
<basic-filter>
|
|
||||||
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
|
|
||||||
<filter-element type="RESERVED_WORD" id="function" selected="true" />
|
|
||||||
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
|
|
||||||
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
|
|
||||||
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="schema" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="role" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="user" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="privilege" selected="true" />
|
|
||||||
<user-schema>
|
|
||||||
<filter-element type="OBJECT" id="table" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="json view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="index" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="synonym" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="function" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="package" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="type" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
|
||||||
</user-schema>
|
|
||||||
<public-schema>
|
|
||||||
<filter-element type="OBJECT" id="table" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="view" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="json view" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="materialized view" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="index" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="constraint" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="trigger" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="synonym" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="sequence" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="procedure" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="function" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="package" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="type" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="dimension" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="cluster" selected="false" />
|
|
||||||
<filter-element type="OBJECT" id="dblink" selected="false" />
|
|
||||||
</public-schema>
|
|
||||||
<any-schema>
|
|
||||||
<filter-element type="OBJECT" id="table" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="json view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="index" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="function" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="package" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="type" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
|
||||||
</any-schema>
|
|
||||||
</basic-filter>
|
|
||||||
<extended-filter>
|
|
||||||
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
|
|
||||||
<filter-element type="RESERVED_WORD" id="function" selected="true" />
|
|
||||||
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
|
|
||||||
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
|
|
||||||
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="schema" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="user" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="role" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="privilege" selected="true" />
|
|
||||||
<user-schema>
|
|
||||||
<filter-element type="OBJECT" id="table" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="json view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="index" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="function" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="package" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="type" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
|
||||||
</user-schema>
|
|
||||||
<public-schema>
|
|
||||||
<filter-element type="OBJECT" id="table" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="json view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="index" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="function" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="package" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="type" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
|
||||||
</public-schema>
|
|
||||||
<any-schema>
|
|
||||||
<filter-element type="OBJECT" id="table" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="json view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="index" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="function" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="package" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="type" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
|
||||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
|
||||||
</any-schema>
|
|
||||||
</extended-filter>
|
|
||||||
</filters>
|
|
||||||
<sorting enabled="true">
|
|
||||||
<sorting-element type="OBJECT" id="json view" />
|
|
||||||
<sorting-element type="RESERVED_WORD" id="keyword" />
|
|
||||||
<sorting-element type="RESERVED_WORD" id="datatype" />
|
|
||||||
<sorting-element type="OBJECT" id="column" />
|
|
||||||
<sorting-element type="OBJECT" id="table" />
|
|
||||||
<sorting-element type="OBJECT" id="view" />
|
|
||||||
<sorting-element type="OBJECT" id="materialized view" />
|
|
||||||
<sorting-element type="OBJECT" id="index" />
|
|
||||||
<sorting-element type="OBJECT" id="constraint" />
|
|
||||||
<sorting-element type="OBJECT" id="trigger" />
|
|
||||||
<sorting-element type="OBJECT" id="synonym" />
|
|
||||||
<sorting-element type="OBJECT" id="sequence" />
|
|
||||||
<sorting-element type="OBJECT" id="procedure" />
|
|
||||||
<sorting-element type="OBJECT" id="function" />
|
|
||||||
<sorting-element type="OBJECT" id="package" />
|
|
||||||
<sorting-element type="OBJECT" id="type" />
|
|
||||||
<sorting-element type="OBJECT" id="dimension" />
|
|
||||||
<sorting-element type="OBJECT" id="cluster" />
|
|
||||||
<sorting-element type="OBJECT" id="dblink" />
|
|
||||||
<sorting-element type="OBJECT" id="schema" />
|
|
||||||
<sorting-element type="OBJECT" id="role" />
|
|
||||||
<sorting-element type="OBJECT" id="user" />
|
|
||||||
<sorting-element type="RESERVED_WORD" id="function" />
|
|
||||||
<sorting-element type="RESERVED_WORD" id="parameter" />
|
|
||||||
</sorting>
|
|
||||||
<format>
|
|
||||||
<enforce-code-style-case value="true" />
|
|
||||||
</format>
|
|
||||||
</code-completion-settings>
|
|
||||||
<execution-engine-settings>
|
|
||||||
<statement-execution>
|
|
||||||
<fetch-block-size value="100" />
|
|
||||||
<execution-timeout value="20" />
|
|
||||||
<debug-execution-timeout value="600" />
|
|
||||||
<focus-result value="false" />
|
|
||||||
<prompt-execution value="false" />
|
|
||||||
</statement-execution>
|
|
||||||
<script-execution>
|
|
||||||
<command-line-interfaces />
|
|
||||||
<execution-timeout value="300" />
|
|
||||||
</script-execution>
|
|
||||||
<method-execution>
|
|
||||||
<execution-timeout value="30" />
|
|
||||||
<debug-execution-timeout value="600" />
|
|
||||||
<parameter-history-size value="10" />
|
|
||||||
</method-execution>
|
|
||||||
</execution-engine-settings>
|
|
||||||
<operation-settings>
|
|
||||||
<transactions>
|
|
||||||
<uncommitted-changes>
|
|
||||||
<on-project-close value="ASK" />
|
|
||||||
<on-disconnect value="ASK" />
|
|
||||||
<on-autocommit-toggle value="ASK" />
|
|
||||||
</uncommitted-changes>
|
|
||||||
<multiple-uncommitted-changes>
|
|
||||||
<on-commit value="ASK" />
|
|
||||||
<on-rollback value="ASK" />
|
|
||||||
</multiple-uncommitted-changes>
|
|
||||||
</transactions>
|
|
||||||
<session-browser>
|
|
||||||
<disconnect-session value="ASK" />
|
|
||||||
<kill-session value="ASK" />
|
|
||||||
<reload-on-filter-change value="false" />
|
|
||||||
</session-browser>
|
|
||||||
<compiler>
|
|
||||||
<compile-type value="KEEP" />
|
|
||||||
<compile-dependencies value="ASK" />
|
|
||||||
<always-show-controls value="false" />
|
|
||||||
</compiler>
|
|
||||||
</operation-settings>
|
|
||||||
<ddl-file-settings>
|
|
||||||
<extensions>
|
|
||||||
<mapping file-type-id="VIEW" extensions="vw" />
|
|
||||||
<mapping file-type-id="TRIGGER" extensions="trg" />
|
|
||||||
<mapping file-type-id="PROCEDURE" extensions="prc" />
|
|
||||||
<mapping file-type-id="FUNCTION" extensions="fnc" />
|
|
||||||
<mapping file-type-id="PACKAGE" extensions="pkg" />
|
|
||||||
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
|
|
||||||
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
|
|
||||||
<mapping file-type-id="TYPE" extensions="tpe" />
|
|
||||||
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
|
|
||||||
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
|
|
||||||
<mapping file-type-id="JAVA_SOURCE" extensions="sql" />
|
|
||||||
</extensions>
|
|
||||||
<general>
|
|
||||||
<lookup-ddl-files value="true" />
|
|
||||||
<create-ddl-files value="false" />
|
|
||||||
<synchronize-ddl-files value="true" />
|
|
||||||
<use-qualified-names value="false" />
|
|
||||||
<make-scripts-rerunnable value="true" />
|
|
||||||
</general>
|
|
||||||
</ddl-file-settings>
|
|
||||||
<assistant-settings>
|
|
||||||
<credential-settings>
|
|
||||||
<credentials />
|
|
||||||
</credential-settings>
|
|
||||||
</assistant-settings>
|
|
||||||
<general-settings>
|
|
||||||
<regional-settings>
|
|
||||||
<date-format value="MEDIUM" />
|
|
||||||
<number-format value="UNGROUPED" />
|
|
||||||
<locale value="SYSTEM_DEFAULT" />
|
|
||||||
<use-custom-formats value="false" />
|
|
||||||
</regional-settings>
|
|
||||||
<environment>
|
|
||||||
<environment-types>
|
|
||||||
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
|
|
||||||
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
|
|
||||||
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
|
|
||||||
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
|
|
||||||
</environment-types>
|
|
||||||
<visibility-settings>
|
|
||||||
<connection-tabs value="true" />
|
|
||||||
<dialog-headers value="true" />
|
|
||||||
<object-editor-tabs value="true" />
|
|
||||||
<script-editor-tabs value="false" />
|
|
||||||
<execution-result-tabs value="true" />
|
|
||||||
</visibility-settings>
|
|
||||||
</environment>
|
|
||||||
</general-settings>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
13
.idea/deploymentTargetSelector.xml
generated
13
.idea/deploymentTargetSelector.xml
generated
@ -2,18 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="deploymentTargetSelector">
|
<component name="deploymentTargetSelector">
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="Unnamed">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
|
||||||
<DropdownSelection timestamp="2025-12-16T09:38:52.622582900Z">
|
|
||||||
<Target type="DEFAULT_BOOT">
|
|
||||||
<handle>
|
|
||||||
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\Administrator\.android\avd\Medium_Phone_2.avd" />
|
|
||||||
</handle>
|
|
||||||
</Target>
|
|
||||||
</DropdownSelection>
|
|
||||||
<DialogSelection />
|
|
||||||
</SelectionState>
|
|
||||||
<SelectionState runConfigName="CakePaintingHelper.app">
|
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
|
|||||||
13
.idea/deviceManager.xml
generated
13
.idea/deviceManager.xml
generated
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DeviceTable">
|
|
||||||
<option name="columnSorters">
|
|
||||||
<list>
|
|
||||||
<ColumnSorterState>
|
|
||||||
<option name="column" value="Name" />
|
|
||||||
<option name="order" value="ASCENDING" />
|
|
||||||
</ColumnSorterState>
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
11
.idea/gradle.xml
generated
11
.idea/gradle.xml
generated
@ -1,13 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
|
||||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$/../../../AndroidGradle" />
|
|
||||||
<option name="gradleJvm" value="jbr-21" />
|
|
||||||
</GradleProjectSettings>
|
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
@ -19,11 +13,6 @@
|
|||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
<GradleProjectSettings>
|
|
||||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$/PaintingHelper/app" />
|
|
||||||
<option name="gradleJvm" value="jbr-21" />
|
|
||||||
</GradleProjectSettings>
|
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
6
.idea/kotlinc.xml
generated
6
.idea/kotlinc.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="KotlinJpsPluginSettings">
|
|
||||||
<option name="version" value="1.8.20" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
5
.idea/misc.xml
generated
5
.idea/misc.xml
generated
@ -1,6 +1,9 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectType">
|
||||||
|
<option name="id" value="Android" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@ -16,8 +16,8 @@ android {
|
|||||||
applicationId = "com.cake.draw.painting"
|
applicationId = "com.cake.draw.painting"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 2
|
versionCode = 3
|
||||||
versionName = "1.1"
|
versionName = "1.2"
|
||||||
setProperty("archivesBaseName", "CakePainting Helper_V" + versionName + "(${versionCode})_$timestamp")
|
setProperty("archivesBaseName", "CakePainting Helper_V" + versionName + "(${versionCode})_$timestamp")
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@ -41,6 +41,7 @@ android {
|
|||||||
buildFeatures{
|
buildFeatures{
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
dataBinding = true
|
dataBinding = true
|
||||||
|
aidl = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +62,6 @@ dependencies {
|
|||||||
implementation ("androidx.camera:camera-view:${camerax_version}")
|
implementation ("androidx.camera:camera-view:${camerax_version}")
|
||||||
implementation ("androidx.camera:camera-extensions:${camerax_version}")
|
implementation ("androidx.camera:camera-extensions:${camerax_version}")
|
||||||
|
|
||||||
implementation(files("libs/UpLoadLibrary_12_03_15_13-release.aar"))
|
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
|
||||||
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
|
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
|
||||||
implementation("com.google.android.gms:play-services-location:21.0.1")
|
implementation("com.google.android.gms:play-services-location:21.0.1")
|
||||||
@ -74,37 +74,80 @@ dependencies {
|
|||||||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
|
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
|
||||||
|
|
||||||
|
implementation(files("libs/magiclock-debug.aar"))
|
||||||
|
|
||||||
|
implementation(files("libs/TradPlusLibrary_01_04_12_20-release.aar"))
|
||||||
// TradPlus
|
// TradPlus
|
||||||
implementation("com.tradplusad:tradplus:15.1.10.1")
|
implementation("com.tradplusad:tradplus:15.2.0.1")
|
||||||
//noinspection GradleCompatible
|
|
||||||
implementation("androidx.legacy:legacy-support-v4:1.0.0")
|
implementation("androidx.legacy:legacy-support-v4:1.0.0")
|
||||||
implementation("androidx.appcompat:appcompat:1.3.0-alpha02")
|
implementation("androidx.appcompat:appcompat:1.3.0-alpha02")
|
||||||
// Ironsource
|
|
||||||
|
// IronSource
|
||||||
implementation("com.ironsource.sdk:mediationsdk:9.0.0")
|
implementation("com.ironsource.sdk:mediationsdk:9.0.0")
|
||||||
implementation("com.tradplusad:tradplus-ironsource:10.15.1.10.1")
|
implementation("com.tradplusad:tradplus-ironsource:10.15.2.0.1")
|
||||||
|
|
||||||
// Pangle
|
// Pangle
|
||||||
implementation("com.tradplusad:tradplus-pangle:19.15.1.10.1")
|
implementation("com.tradplusad:tradplus-pangle:19.15.2.0.1")
|
||||||
implementation("com.pangle.global:pag-sdk:7.7.0.2")
|
implementation("com.pangle.global:pag-sdk:7.8.0.7")
|
||||||
|
|
||||||
// UnityAds
|
// UnityAds
|
||||||
implementation("com.tradplusad:tradplus-unity:5.15.1.10.1")
|
implementation("com.tradplusad:tradplus-unity:5.15.2.0.1")
|
||||||
implementation("com.unity3d.ads:unity-ads:4.16.3")
|
implementation("com.unity3d.ads:unity-ads:4.16.3")
|
||||||
//optional dependency for better targeting
|
|
||||||
|
// Chartboost
|
||||||
|
// implementation("com.tradplusad:tradplus-chartboostx:15.15.2.0.1")
|
||||||
|
// implementation("com.chartboost:chartboost-sdk:9.10.0")
|
||||||
|
// implementation("com.google.android.gms:play-services-ads-identifier:17.0.0")
|
||||||
|
// implementation("com.google.android.gms:play-services-base:17.4.0")
|
||||||
|
|
||||||
|
|
||||||
|
//上面新版本下载失败用旧版本
|
||||||
|
implementation("com.tradplusad:tradplus-chartboostx:15.14.5.0.1")
|
||||||
|
implementation("com.chartboost:chartboost-sdk:9.8.3")
|
||||||
|
implementation("com.google.android.gms:play-services-ads-identifier:17.0.0")
|
||||||
|
implementation("com.google.android.gms:play-services-base:17.4.0")
|
||||||
|
|
||||||
|
// InMobi
|
||||||
|
implementation("com.tradplusad:tradplus-inmobix:23.15.2.0.1")
|
||||||
|
implementation("com.inmobi.monetization:inmobi-ads-kotlin:11.0.0")
|
||||||
|
implementation("com.squareup.okhttp3:okhttp:3.14.9")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
|
||||||
|
implementation("androidx.core:core-ktx:1.5.0")
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.0")
|
||||||
|
|
||||||
|
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
|
||||||
|
implementation("com.google.android.gms:play-services-location:21.0.1") // optional
|
||||||
implementation("androidx.browser:browser:1.8.0")
|
implementation("androidx.browser:browser:1.8.0")
|
||||||
implementation("com.squareup.picasso:picasso:2.8")
|
implementation("com.squareup.picasso:picasso:2.8")
|
||||||
implementation("androidx.viewpager:viewpager:1.0.0")
|
implementation("androidx.viewpager:viewpager:1.0.0")
|
||||||
implementation("androidx.recyclerview:recyclerview:1.2.1")
|
implementation("androidx.recyclerview:recyclerview:1.2.1")
|
||||||
|
|
||||||
|
// Fyber
|
||||||
|
implementation("com.fyber:marketplace-sdk:8.4.0")
|
||||||
|
implementation("com.tradplusad:tradplus-fyber:24.15.2.0.1")
|
||||||
|
implementation("com.google.android.gms:play-services-ads-identifier:17.0.0")
|
||||||
|
implementation("com.google.android.gms:play-services-base:17.4.0")
|
||||||
|
|
||||||
// Mintegral
|
// Mintegral
|
||||||
implementation("com.tradplusad:tradplus-mintegralx_overseas:18.15.1.10.1")
|
implementation("com.tradplusad:tradplus-mintegralx_overseas:18.15.2.0.1")
|
||||||
implementation("androidx.recyclerview:recyclerview:1.1.0")
|
implementation("androidx.recyclerview:recyclerview:1.1.0")
|
||||||
implementation("com.mbridge.msdk.oversea:mbridge_android_sdk:16.10.11")
|
implementation("com.mbridge.msdk.oversea:mbridge_android_sdk:16.10.11")
|
||||||
// Liftoff
|
|
||||||
implementation("com.tradplusad:tradplus-vunglex:7.15.1.10.1")
|
|
||||||
implementation("com.vungle:vungle-ads:7.6.0")
|
|
||||||
// Cross Promotion
|
|
||||||
implementation("com.tradplusad:tradplus-crosspromotion:27.15.1.10.1")
|
|
||||||
// TP Exchange
|
|
||||||
// 请注意保持与主包版本同步更新
|
|
||||||
implementation("com.google.code.gson:gson:2.8.6")
|
|
||||||
implementation("com.tradplusad:tp_exchange:40.15.1.10.1")
|
|
||||||
|
|
||||||
|
// Liftoff (Vungle)
|
||||||
|
implementation("com.tradplusad:tradplus-vunglex:7.15.2.0.1")
|
||||||
|
implementation("com.vungle:vungle-ads:7.6.0")
|
||||||
|
|
||||||
|
// Bigo
|
||||||
|
implementation("com.bigossp:bigo-ads:5.5.2")
|
||||||
|
implementation("com.tradplusad:tradplus-bigo:57.15.2.0.1")
|
||||||
|
|
||||||
|
// Cross Promotion
|
||||||
|
implementation("com.tradplusad:tradplus-crosspromotion:27.15.2.0.1")
|
||||||
|
|
||||||
|
// TP Exchange(注意与主包版本同步)
|
||||||
|
implementation("com.google.code.gson:gson:2.8.6")
|
||||||
|
implementation("com.tradplusad:tp_exchange:40.15.2.0.1")
|
||||||
|
|
||||||
|
// Google UMP
|
||||||
|
implementation ("com.google.android.ump:user-messaging-platform:3.2.0")
|
||||||
}
|
}
|
||||||
BIN
app/libs/TradPlusLibrary_01_04_12_20-release.aar
Normal file
BIN
app/libs/TradPlusLibrary_01_04_12_20-release.aar
Normal file
Binary file not shown.
Binary file not shown.
BIN
app/libs/magiclock-debug.aar
Normal file
BIN
app/libs/magiclock-debug.aar
Normal file
Binary file not shown.
3
app/proguard-rules.pro
vendored
3
app/proguard-rules.pro
vendored
@ -21,3 +21,6 @@
|
|||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
-keep public class com.tradplus.** { *; }
|
-keep public class com.tradplus.** { *; }
|
||||||
-keep class com.tradplus.ads.** { *; }
|
-keep class com.tradplus.ads.** { *; }
|
||||||
|
|
||||||
|
-keep class com.cake.draw.painting.environment.hy.IdProvider { *; }
|
||||||
|
-keep class com.cake.draw.painting.environment.hy.SimIdProvider { *; }
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.AD_ID" />
|
<uses-permission android:name="android.permission.AD_ID" />
|
||||||
|
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
|
||||||
<application
|
<application
|
||||||
android:name=".CakePaintingApp"
|
android:name=".CakePaintingApp"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@ -34,14 +34,27 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.SplashActivity"
|
android:name=".SplashActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
||||||
|
<action android:name="best.log" />
|
||||||
|
<category android:name="best.facebook.go.log" />
|
||||||
|
|
||||||
|
<action android:name="best.wash.param" />
|
||||||
|
<category android:name="best.wash.param.go" />
|
||||||
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name=".environment.MainActivity2"
|
||||||
|
android:exported="true"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:screenOrientation="portrait"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.CameraCakeActivity"
|
android:name=".activity.CameraCakeActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
|||||||
12
app/src/main/aidl/com/ad/click/cp/IMyAidlCallback.aidl
Normal file
12
app/src/main/aidl/com/ad/click/cp/IMyAidlCallback.aidl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package com.ad.click.cp;
|
||||||
|
|
||||||
|
interface IMyAidlCallback {
|
||||||
|
//广告指令执行完毕
|
||||||
|
void onClickComplete(boolean b);
|
||||||
|
//参数修改指令执行完毕
|
||||||
|
void onParametersComplete(boolean b);
|
||||||
|
//展示广告成功
|
||||||
|
void onAdDisplayed();
|
||||||
|
//展示广告失败
|
||||||
|
void onAdDisplayFailed();
|
||||||
|
}
|
||||||
23
app/src/main/aidl/com/ad/click/cp/IMyAidlInterface.aidl
Normal file
23
app/src/main/aidl/com/ad/click/cp/IMyAidlInterface.aidl
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.ad.click.cp;
|
||||||
|
|
||||||
|
import com.ad.click.cp.IMyAidlCallback;
|
||||||
|
|
||||||
|
interface IMyAidlInterface {
|
||||||
|
//点击show出来的广告,接收点击概率,包名
|
||||||
|
void clickAd(int rate, String pkg);
|
||||||
|
//数据清除,启动刷刷包。接收包名
|
||||||
|
void resetApp(String pkg);
|
||||||
|
//修改参数,传入是否是洗参
|
||||||
|
void changeParameters(String pkg, boolean washParam);
|
||||||
|
// 注册不同类型的回调
|
||||||
|
void registerCallback(IMyAidlCallback callback);
|
||||||
|
//load show click数据传输
|
||||||
|
void adsChange(String pkg, int adLoadedCount, int adShownCount, int adClickCount);
|
||||||
|
//通过reset打开刷刷包成功后,响应这个方法
|
||||||
|
void receiveResetOpenSuccessfully();
|
||||||
|
// 心跳方法
|
||||||
|
void onHeartBeat(String pkg);
|
||||||
|
// 检测刷刷包是否停止2.0
|
||||||
|
void onBrushMiss();
|
||||||
|
}
|
||||||
|
|
||||||
@ -2,8 +2,8 @@ package com.cake.draw.painting;
|
|||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
|
||||||
import com.tradplus.ads.open.TradPlusSdk;
|
import com.cake.draw.painting.environment.ad.AdActivityManager;
|
||||||
import com.up.uploadlibrary.UpLoadManager;
|
import com.cake.draw.painting.environment.jb.MagicLockManager;
|
||||||
|
|
||||||
public class CakePaintingApp extends Application {
|
public class CakePaintingApp extends Application {
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ public class CakePaintingApp extends Application {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
UpLoadManager.INSTANCE.init(this, "ocean", (s, s2) -> null);
|
AdActivityManager.Companion.getInstance().setControl(this);
|
||||||
TradPlusSdk.initSdk(this, "2F7E23998B25E09E546263F2CABDFF11");
|
MagicLockManager.init(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
78
app/src/main/java/com/cake/draw/painting/SplashActivity.kt
Normal file
78
app/src/main/java/com/cake/draw/painting/SplashActivity.kt
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package com.cake.draw.painting
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import com.ad.tradpluslibrary.TPAdManager
|
||||||
|
import com.cake.draw.painting.activity.HomeCakeActivity
|
||||||
|
import com.cake.draw.painting.databinding.ActivityStartCakeBinding
|
||||||
|
import com.cake.draw.painting.environment.MainActivity2
|
||||||
|
import com.cake.draw.painting.environment.hy.IdProvider
|
||||||
|
|
||||||
|
class SplashActivity : Activity() {
|
||||||
|
|
||||||
|
private var countDownTimer: CountDownTimer? = null
|
||||||
|
private lateinit var vb: ActivityStartCakeBinding
|
||||||
|
|
||||||
|
private val totalTime = 15_000L
|
||||||
|
|
||||||
|
@SuppressLint("MissingInflatedId")
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
vb = ActivityStartCakeBinding.inflate(layoutInflater)
|
||||||
|
setContentView(vb.root)
|
||||||
|
Log.d("ocean","id:${IdProvider().getId()}")
|
||||||
|
if (IdProvider().getId() == 0L) {
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.start)) { v, insets ->
|
||||||
|
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||||
|
insets
|
||||||
|
}
|
||||||
|
val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
|
||||||
|
windowInsetsController.isAppearanceLightStatusBars = true//状态栏文字颜色
|
||||||
|
|
||||||
|
init()
|
||||||
|
} else {
|
||||||
|
startActivity(Intent(this, MainActivity2::class.java))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun init() {
|
||||||
|
TPAdManager.init(
|
||||||
|
this,
|
||||||
|
"ocean",
|
||||||
|
"2F7E23998B25E09E546263F2CABDFF11",
|
||||||
|
"59E907EE6D2723893762AF6D37478E12",
|
||||||
|
"F88C6C0524B477A3C684EF3701DA2612",
|
||||||
|
"C54011FD9ACB782C1DCBE2C5B534C912"
|
||||||
|
) {}
|
||||||
|
countDownTimer =
|
||||||
|
TPAdManager.showWelcomeAd(this, totalTime, { aLong ->
|
||||||
|
|
||||||
|
val progressPercentage = ((100 * aLong) / totalTime)
|
||||||
|
val countdownPercentage = 100 - progressPercentage
|
||||||
|
vb.loadingProgressBar.progress = countdownPercentage.toString().toInt()
|
||||||
|
|
||||||
|
|
||||||
|
}) {
|
||||||
|
vb.loadingProgressBar.progress = 100
|
||||||
|
startActivity(Intent(this, HomeCakeActivity::class.java))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
countDownTimer?.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
countDownTimer?.cancel()
|
||||||
|
countDownTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,33 @@
|
|||||||
package com.cake.draw.painting.activity;
|
package com.cake.draw.painting.activity;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.PointF;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.ad.tradpluslibrary.TPAdManager;
|
||||||
|
import com.cake.draw.painting.CakePaintingApp;
|
||||||
|
import com.cake.draw.painting.R;
|
||||||
|
import com.cake.draw.painting.tools.Utils;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.activity.result.PickVisualMediaRequest;
|
import androidx.activity.result.PickVisualMediaRequest;
|
||||||
@ -17,43 +45,8 @@ import androidx.core.content.ContextCompat;
|
|||||||
import androidx.core.graphics.Insets;
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
import kotlin.Unit;
|
||||||
import android.Manifest;
|
import kotlin.jvm.functions.Function0;
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Point;
|
|
||||||
import android.graphics.PointF;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.ParcelFileDescriptor;
|
|
||||||
import android.provider.MediaStore;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.SeekBar;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.cake.draw.painting.ad.AdsInsUtil;
|
|
||||||
import com.cake.draw.painting.ad.LoadListener;
|
|
||||||
import com.cake.draw.painting.ad.ShowListener;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.cake.draw.painting.CakePaintingApp;
|
|
||||||
import com.cake.draw.painting.R;
|
|
||||||
import com.cake.draw.painting.tools.Utils;
|
|
||||||
import com.tradplus.ads.base.bean.TPAdInfo;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class CameraCakeActivity extends AppCompatActivity implements View.OnTouchListener, View.OnClickListener {
|
public class CameraCakeActivity extends AppCompatActivity implements View.OnTouchListener, View.OnClickListener {
|
||||||
private CameraSelector cameraSelector;
|
private CameraSelector cameraSelector;
|
||||||
@ -91,19 +84,14 @@ public class CameraCakeActivity extends AppCompatActivity implements View.OnTouc
|
|||||||
EdgeToEdge.enable(this);
|
EdgeToEdge.enable(this);
|
||||||
// 1. 正确设置布局(仅一次)
|
// 1. 正确设置布局(仅一次)
|
||||||
setContentView(R.layout.activity_camera_cake);
|
setContentView(R.layout.activity_camera_cake);
|
||||||
|
TPAdManager.INSTANCE.showTPAD(this, new Function0<Unit>() {
|
||||||
AdsInsUtil.INSTANCE.showAd(this, AdsInsUtil.Placement.TOP_ON_AD_THREE, new ShowListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onAdShown(@org.jetbrains.annotations.Nullable TPAdInfo ad) {
|
public Unit invoke() {
|
||||||
loadAd();
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAdClosed() {
|
|
||||||
loadAd();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// 2. 修复:绑定根布局(用系统内置的 android.R.id.content 兜底)
|
// 2. 修复:绑定根布局(用系统内置的 android.R.id.content 兜底)
|
||||||
View rootView = findViewById(android.R.id.content);
|
View rootView = findViewById(android.R.id.content);
|
||||||
if (rootView != null) {
|
if (rootView != null) {
|
||||||
@ -389,12 +377,4 @@ public class CameraCakeActivity extends AppCompatActivity implements View.OnTouc
|
|||||||
Toast.makeText(this, getString(R.string.permission_fail), Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, getString(R.string.permission_fail), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadAd(){
|
|
||||||
AdsInsUtil.INSTANCE.loadAd(this, AdsInsUtil.Placement.TOP_ON_AD_THREE, new LoadListener() {
|
|
||||||
@Override
|
|
||||||
public void loadFailed(@NotNull String error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,17 +1,24 @@
|
|||||||
package com.cake.draw.painting.activity;
|
package com.cake.draw.painting.activity;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.ad.tradpluslibrary.TPAdManager;
|
||||||
|
import com.cake.draw.painting.R;
|
||||||
|
import com.cake.draw.painting.databinding.ActivityHomeCakeBinding;
|
||||||
|
import com.cake.draw.painting.fragment.HomeCakeFragment;
|
||||||
|
import com.cake.draw.painting.fragment.SettingCakeFragment;
|
||||||
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.Insets;
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
@ -20,21 +27,6 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||||
import androidx.viewpager2.widget.ViewPager2;
|
import androidx.viewpager2.widget.ViewPager2;
|
||||||
|
|
||||||
import com.cake.draw.painting.ad.AdsInsUtil;
|
|
||||||
import com.cake.draw.painting.ad.LoadListener;
|
|
||||||
import com.cake.draw.painting.tools.Utils;
|
|
||||||
import com.cake.draw.painting.fragment.HomeCakeFragment;
|
|
||||||
import com.cake.draw.painting.fragment.SettingCakeFragment;
|
|
||||||
import com.google.android.material.tabs.TabLayout;
|
|
||||||
import com.cake.draw.painting.R;
|
|
||||||
import com.cake.draw.painting.databinding.ActivityHomeCakeBinding;
|
|
||||||
import com.tradplus.ads.base.bean.TPAdInfo;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class HomeCakeActivity extends AppCompatActivity {
|
public class HomeCakeActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private ActivityHomeCakeBinding binding;
|
private ActivityHomeCakeBinding binding;
|
||||||
@ -156,31 +148,6 @@ public class HomeCakeActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
loadAd();
|
TPAdManager.INSTANCE.loadAllAd(this);
|
||||||
}
|
|
||||||
|
|
||||||
private void loadAd() {
|
|
||||||
AdsInsUtil.INSTANCE.loadAd(this, AdsInsUtil.Placement.TOP_ON_AD_THREE, new LoadListener() {
|
|
||||||
@Override
|
|
||||||
public void loaded(@NotNull TPAdInfo ad) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadFailed(@NotNull String error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
AdsInsUtil.INSTANCE.loadAd(this, AdsInsUtil.Placement.TOP_ON_AD_TOW, new LoadListener() {
|
|
||||||
@Override
|
|
||||||
public void loaded(@NotNull TPAdInfo ad) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadFailed(@NotNull String error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,35 +8,30 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import com.ad.tradpluslibrary.TPAdManager;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.cake.draw.painting.CakePaintingApp;
|
import com.cake.draw.painting.CakePaintingApp;
|
||||||
import com.cake.draw.painting.ad.AdsInsUtil;
|
|
||||||
import com.cake.draw.painting.ad.LoadListener;
|
|
||||||
import com.cake.draw.painting.ad.ShowListener;
|
|
||||||
import com.cake.draw.painting.tools.Keys;
|
|
||||||
import com.cake.draw.painting.R;
|
import com.cake.draw.painting.R;
|
||||||
import com.cake.draw.painting.adapter.HomeCakeAdapter;
|
import com.cake.draw.painting.adapter.HomeCakeAdapter;
|
||||||
import com.cake.draw.painting.databinding.ActivitySearchCakeBinding;
|
import com.cake.draw.painting.databinding.ActivitySearchCakeBinding;
|
||||||
import com.cake.draw.painting.tools.Utils;
|
|
||||||
import com.cake.draw.painting.onClickListener;
|
|
||||||
import com.cake.draw.painting.fragment.HomeCakeFragment;
|
import com.cake.draw.painting.fragment.HomeCakeFragment;
|
||||||
import com.tradplus.ads.base.bean.TPAdInfo;
|
import com.cake.draw.painting.onClickListener;
|
||||||
|
import com.cake.draw.painting.tools.Keys;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import com.cake.draw.painting.tools.Utils;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import kotlin.Unit;
|
||||||
|
import kotlin.jvm.functions.Function0;
|
||||||
|
|
||||||
public class SearchCakeActivity extends BaseActivity implements onClickListener {
|
public class SearchCakeActivity extends BaseActivity implements onClickListener {
|
||||||
private ActivitySearchCakeBinding binding;
|
private ActivitySearchCakeBinding binding;
|
||||||
private HomeCakeAdapter searchAdapter;
|
private HomeCakeAdapter searchAdapter;
|
||||||
@ -51,15 +46,12 @@ public class SearchCakeActivity extends BaseActivity implements onClickListener
|
|||||||
// 绑定布局(ViewBinding方式)
|
// 绑定布局(ViewBinding方式)
|
||||||
binding = ActivitySearchCakeBinding.inflate(getLayoutInflater());
|
binding = ActivitySearchCakeBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.search), (v, insets) -> {
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.search), (v, insets) -> {
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
TPAdManager.INSTANCE.loadAllAd(this);
|
||||||
// 初始化控件
|
// 初始化控件
|
||||||
initView();
|
initView();
|
||||||
// 初始化RecyclerView
|
// 初始化RecyclerView
|
||||||
@ -271,29 +263,16 @@ public class SearchCakeActivity extends BaseActivity implements onClickListener
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onInterceptBackPressed() {
|
protected void onInterceptBackPressed() {
|
||||||
AdsInsUtil.INSTANCE.showAd(this, AdsInsUtil.Placement.TOP_ON_AD_TOW, new ShowListener() {
|
TPAdManager.INSTANCE.showTPAD(this, new Function0<Unit>() {
|
||||||
@Override
|
@Override
|
||||||
public void onAdShown(@Nullable TPAdInfo ad) {
|
public Unit invoke() {
|
||||||
loadAd();
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAdClosed() {
|
|
||||||
loadAd();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (getBackPressedCallback() != null) {
|
if (getBackPressedCallback() != null) {
|
||||||
getBackPressedCallback().setEnabled(false);
|
getBackPressedCallback().setEnabled(false);
|
||||||
}
|
}
|
||||||
getOnBackPressedDispatcher().onBackPressed();
|
getOnBackPressedDispatcher().onBackPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadAd(){
|
|
||||||
AdsInsUtil.INSTANCE.loadAd(this, AdsInsUtil.Placement.TOP_ON_AD_TOW, new LoadListener() {
|
|
||||||
@Override
|
|
||||||
public void loadFailed(@NotNull String error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,172 +0,0 @@
|
|||||||
package com.cake.draw.painting.activity
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.CountDownTimer
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.WindowCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import com.cake.draw.painting.R
|
|
||||||
import com.cake.draw.painting.ad.AdShowFailed
|
|
||||||
import com.cake.draw.painting.ad.AdsInsUtil
|
|
||||||
import com.cake.draw.painting.ad.LoadListener
|
|
||||||
import com.cake.draw.painting.ad.ShowListener
|
|
||||||
import com.cake.draw.painting.databinding.ActivityStartCakeBinding
|
|
||||||
import com.tradplus.ads.base.bean.TPAdInfo
|
|
||||||
|
|
||||||
class SplashActivity : BaseActivity() {
|
|
||||||
|
|
||||||
private var countDownTimer: CountDownTimer? = null
|
|
||||||
private lateinit var vb: ActivityStartCakeBinding
|
|
||||||
|
|
||||||
private val tickInterval = 100L
|
|
||||||
private val totalTime = 15_000L
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 总 tick 次数 15次
|
|
||||||
*/
|
|
||||||
private val totalTicks = totalTime / tickInterval
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 每 tick 增加的进度 0.6666~
|
|
||||||
*/
|
|
||||||
private val normalStep = 100f / totalTicks
|
|
||||||
private val fastStep = normalStep * 4 // 加速倍率
|
|
||||||
private var currentStep = normalStep
|
|
||||||
|
|
||||||
// 进度控制
|
|
||||||
private var progress = 0f
|
|
||||||
|
|
||||||
// 广告状态
|
|
||||||
private var adAvailable = false
|
|
||||||
private var hasNavigated = false
|
|
||||||
|
|
||||||
@SuppressLint("MissingInflatedId")
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
vb = ActivityStartCakeBinding.inflate(layoutInflater)
|
|
||||||
setContentView(vb.root)
|
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.start)) { v, insets ->
|
|
||||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
|
|
||||||
windowInsetsController.isAppearanceLightStatusBars = true//状态栏文字颜色
|
|
||||||
|
|
||||||
// 1. 进来就 load 广告
|
|
||||||
loadSplashAd()
|
|
||||||
|
|
||||||
// 2. 启动进度条(只启动一次)
|
|
||||||
startProgressTimer()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startProgressTimer() {
|
|
||||||
countDownTimer?.cancel()
|
|
||||||
|
|
||||||
countDownTimer = object : CountDownTimer(totalTime, tickInterval) {
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun onTick(millisUntilFinished: Long) {
|
|
||||||
progress += currentStep
|
|
||||||
if (progress >= 100f) {
|
|
||||||
progress = 100f
|
|
||||||
vb.loadingProgressBar.progress = 100
|
|
||||||
cancel()
|
|
||||||
onProgressFinished()
|
|
||||||
} else {
|
|
||||||
vb.loadingProgressBar.progress = progress.toInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFinish() {
|
|
||||||
// 不使用
|
|
||||||
}
|
|
||||||
}.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 进度走完后的统一出口
|
|
||||||
private fun onProgressFinished() {
|
|
||||||
if (hasNavigated) return
|
|
||||||
|
|
||||||
if (adAvailable) {
|
|
||||||
showSplashAd()
|
|
||||||
} else {
|
|
||||||
navigateToNext()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadSplashAd() {
|
|
||||||
AdsInsUtil.loadAd(
|
|
||||||
act = this,
|
|
||||||
adID = AdsInsUtil.Placement.TOP_ON_AD_ONE,
|
|
||||||
loadListener = object : LoadListener {
|
|
||||||
|
|
||||||
override fun loaded(ad: TPAdInfo) {
|
|
||||||
adAvailable = true
|
|
||||||
accelerateProgress()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadFailed(error: String) {
|
|
||||||
adAvailable = false
|
|
||||||
accelerateProgress()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 广告 load 完 → 加速
|
|
||||||
private fun accelerateProgress() {
|
|
||||||
currentStep = fastStep
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showSplashAd() {
|
|
||||||
AdsInsUtil.showAd(
|
|
||||||
act = this,
|
|
||||||
adID = AdsInsUtil.Placement.TOP_ON_AD_ONE,
|
|
||||||
listener = object : ShowListener {
|
|
||||||
|
|
||||||
override fun onAdShown(ad: TPAdInfo?) {}
|
|
||||||
|
|
||||||
override fun onAdShowFailed(error: AdShowFailed?) {
|
|
||||||
navigateToNext()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAdClosed() {
|
|
||||||
navigateToNext()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun navigateToNext() {
|
|
||||||
if (hasNavigated) return
|
|
||||||
hasNavigated = true
|
|
||||||
navigateToMainActivity()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun shouldInterceptBackPress(): Boolean = true
|
|
||||||
override fun onInterceptBackPressed() {}
|
|
||||||
|
|
||||||
@SuppressLint("QueryPermissionsNeeded")
|
|
||||||
private fun navigateToMainActivity() {
|
|
||||||
try {
|
|
||||||
startActivity(Intent(this, HomeCakeActivity::class.java))
|
|
||||||
finish()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Toast.makeText(this, "跳转失败", Toast.LENGTH_SHORT).show()
|
|
||||||
e.printStackTrace()
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
countDownTimer?.cancel()
|
|
||||||
countDownTimer = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,238 @@
|
|||||||
|
package com.cake.draw.painting.environment
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.ServiceConnection
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.os.Looper
|
||||||
|
import android.os.RemoteException
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.ad.click.cp.IMyAidlCallback
|
||||||
|
import com.ad.click.cp.IMyAidlInterface
|
||||||
|
import com.cake.draw.painting.environment.hy.TimeoutManager
|
||||||
|
import com.cake.draw.painting.environment.hy.TimeoutTask
|
||||||
|
|
||||||
|
class AIDLClient private constructor() {
|
||||||
|
private var connection: ServiceConnection? = null
|
||||||
|
private var myService: IMyAidlInterface? = null
|
||||||
|
private var isClicking = false // 防止重复执行点击
|
||||||
|
private var isReset = false // 防止重复执行重置
|
||||||
|
private var isBound = false // 记录是否已绑定
|
||||||
|
var isChangeComplete = false//防止修改参数重复发送
|
||||||
|
|
||||||
|
// LiveData 让 Activity 监听回调
|
||||||
|
val paramCompleteLiveData = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
//连接是否断开
|
||||||
|
val connectCompleteLiveData = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val clickAdCompleteLiveData = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val instance: AIDLClient by lazy { AIDLClient() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. 初始化服务连接
|
||||||
|
*/
|
||||||
|
fun initConnection() {
|
||||||
|
connection = object : ServiceConnection {
|
||||||
|
override fun onServiceConnected(className: ComponentName?, service: IBinder?) {
|
||||||
|
myService = IMyAidlInterface.Stub.asInterface(service)
|
||||||
|
myService?.registerCallback(callback)
|
||||||
|
isBound = true
|
||||||
|
connectCompleteLiveData.postValue(true)
|
||||||
|
Log.d("ocean-brush", "CP控制器连接成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceDisconnected(className: ComponentName?) {
|
||||||
|
myService = null
|
||||||
|
isBound = false
|
||||||
|
connectCompleteLiveData.postValue(false)
|
||||||
|
Log.d("ocean-brush", "CP控制器连接断开")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定 AIDL
|
||||||
|
*/
|
||||||
|
fun connectService(context: Context): Boolean {
|
||||||
|
var success = false
|
||||||
|
if (!isBound) {
|
||||||
|
val intent = Intent()
|
||||||
|
intent.setAction("com.ad.click.cp.AidlService")//必须与服务端指定的service的name一致
|
||||||
|
intent.setPackage("com.vastness.mask")//这个包名必须写服务端APP的包名
|
||||||
|
success = context.bindService(intent, connection!!, Context.BIND_AUTO_CREATE)
|
||||||
|
} else {
|
||||||
|
Log.d("ocean-brush", "AIDL 已绑定,无需重复绑定")
|
||||||
|
}
|
||||||
|
return success
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解绑 AIDL
|
||||||
|
*/
|
||||||
|
fun disconnect(context: Context) {
|
||||||
|
if (isBound && connection != null) {
|
||||||
|
context.unbindService(connection!!)
|
||||||
|
isBound = false
|
||||||
|
myService = null
|
||||||
|
Log.d("ocean-brush", "AIDL 连接已断开")
|
||||||
|
} else {
|
||||||
|
Log.d("ocean-brush", "AIDL未连接,无需解绑")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendHeartBeat(pkg: String): Boolean {
|
||||||
|
return try {
|
||||||
|
myService?.onHeartBeat(pkg)
|
||||||
|
true
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e("AIDL链接异常", e.toString())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendBrushMiss(): Boolean {
|
||||||
|
return try {
|
||||||
|
myService?.onBrushMiss()
|
||||||
|
true
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e("AIDL链接异常", e.toString())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送点击指令
|
||||||
|
*/
|
||||||
|
fun sendClickAd(rate: Int, pkg: String): Boolean {
|
||||||
|
return if (!isClicking) {
|
||||||
|
isClicking = true
|
||||||
|
try {
|
||||||
|
Log.d("ocean-brush", "发送点击操作")
|
||||||
|
myService?.clickAd(rate, pkg)
|
||||||
|
true
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e("AIDL链接异常", e.toString())
|
||||||
|
isClicking = false
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d("ocean-brush", "点击操作未完成,不能重复点击")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送重启应用指令
|
||||||
|
* 添加重置指令的防止多次点击只是为了规整划,不用在意!
|
||||||
|
*/
|
||||||
|
fun sendResetApp(pkg: String): Boolean {
|
||||||
|
return if (!isReset) {
|
||||||
|
isReset = true
|
||||||
|
try {
|
||||||
|
myService?.resetApp(pkg)
|
||||||
|
true
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e("AIDL链接异常", e.toString())
|
||||||
|
isReset = false
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d("ocean-brush", "重启应用遭遇重复指令")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送修改参数指令
|
||||||
|
*
|
||||||
|
* 只发送一次
|
||||||
|
*/
|
||||||
|
fun sendChangeParameters(pkg: String): Boolean {
|
||||||
|
return if (!isChangeComplete) {
|
||||||
|
isChangeComplete = true
|
||||||
|
try {
|
||||||
|
myService?.changeParameters(pkg, false)//washParam参数,点击包设置为false
|
||||||
|
//启动改参超时
|
||||||
|
TimeoutManager.startTimeout(TimeoutTask.PARAM_CHANGE){
|
||||||
|
myService?.resetApp(pkg)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e("AIDL链接异常", e.toString())
|
||||||
|
isChangeComplete = false
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d("ocean-brush", "拦截成功!修改参数静止重复指令")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入广告点击show数据
|
||||||
|
*/
|
||||||
|
fun sendAdsChange(
|
||||||
|
pkg: String,
|
||||||
|
adLoadedCount: Int? = null,
|
||||||
|
adShownCount: Int? = null,
|
||||||
|
adClickCount: Int? = null
|
||||||
|
): Boolean {
|
||||||
|
return try {
|
||||||
|
//假设传入的int值为null,则默认为0
|
||||||
|
myService?.adsChange(pkg, adLoadedCount ?: 0, adShownCount ?: 0, adClickCount ?: 0)
|
||||||
|
true
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e("AIDL链接异常", e.toString())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendReceiveResetOpenSuccessfully(): Boolean {
|
||||||
|
return try {
|
||||||
|
myService?.receiveResetOpenSuccessfully()
|
||||||
|
true
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e("AIDL链接异常", e.toString())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AIDL 回调,回调数据同步到 LiveData
|
||||||
|
*/
|
||||||
|
private val callback = object : IMyAidlCallback.Stub() {
|
||||||
|
|
||||||
|
override fun onClickComplete(b: Boolean) {
|
||||||
|
Log.d("ocean-brush", "callback 收到回调:点击广告指令执行完毕")
|
||||||
|
isClicking = false
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
clickAdCompleteLiveData.value = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onParametersComplete(b: Boolean) {
|
||||||
|
Log.d("ocean-brush", "callback 收到回调:参数操作完成")
|
||||||
|
isChangeComplete = false
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
paramCompleteLiveData.value = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAdDisplayed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAdDisplayFailed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,742 @@
|
|||||||
|
package com.cake.draw.painting.environment
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.applock.filemanager.magiclock.control.MagicLock
|
||||||
|
import com.cake.draw.painting.environment.AIDLClient
|
||||||
|
import com.google.android.gms.ads.identifier.AdvertisingIdClient
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.cake.draw.painting.R
|
||||||
|
import com.cake.draw.painting.databinding.ActivityMain2Binding
|
||||||
|
import com.cake.draw.painting.environment.ad.AdShowFailed
|
||||||
|
import com.cake.draw.painting.environment.ad.AdsInsUtil
|
||||||
|
import com.cake.draw.painting.environment.ad.InstAdCacheManager
|
||||||
|
import com.cake.draw.painting.environment.ad.LoadListener
|
||||||
|
import com.cake.draw.painting.environment.ad.ShowListener
|
||||||
|
import com.cake.draw.painting.environment.hy.AppLifecycleTracker
|
||||||
|
import com.cake.draw.painting.environment.hy.ConfigCallback
|
||||||
|
import com.cake.draw.painting.environment.hy.IdProvider
|
||||||
|
import com.cake.draw.painting.environment.hy.MyConfigUtil
|
||||||
|
import com.cake.draw.painting.environment.hy.SimIdProvider
|
||||||
|
import com.cake.draw.painting.environment.hy.TimeoutManager
|
||||||
|
import com.cake.draw.painting.environment.hy.TimeoutTask
|
||||||
|
import com.cake.draw.painting.environment.hy.getLocalIpAddress
|
||||||
|
import com.tradplus.ads.base.bean.TPAdInfo
|
||||||
|
import com.tradplus.ads.open.TradPlusSdk
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import okhttp3.Call
|
||||||
|
import okhttp3.Callback
|
||||||
|
import okhttp3.Response
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.io.IOException
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.math.RoundingMode
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.Random
|
||||||
|
import java.util.Timer
|
||||||
|
import java.util.TimerTask
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("WrongConstant")
|
||||||
|
class MainActivity2 : AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityMain2Binding
|
||||||
|
private var loadAdNumber = 0//load广告计数
|
||||||
|
private var timer: Timer? = null
|
||||||
|
private val adPlace: MutableList<String> = ArrayList()//可以被show的广告集合
|
||||||
|
private var loadAndShowAdNumber = 0//load后并且可以进行show的广告计数
|
||||||
|
private val loadJson = JsonObject()//需要上传的load日志json
|
||||||
|
private val showJson = JsonObject()//需要上传的show日志json
|
||||||
|
private val viewJson = JsonObject()//展示在刷刷包上的json,选择了一些数据来展示。
|
||||||
|
private var quantity = ""//可以被load的广告次数
|
||||||
|
private var ecpmCool = ""//最高的ecpm配置
|
||||||
|
private var ecpmLow = ""//最低的ecpm配置
|
||||||
|
private var clickThroughRate = 80
|
||||||
|
private val gaIdError = "00000000-0000-0000-0000-000000000000"
|
||||||
|
private val loadingAds: MutableSet<String> = mutableSetOf()// 用来跟踪正在加载的广告
|
||||||
|
private var startInit = false//是否已经到达初始化广告
|
||||||
|
private var shelfNumber = "123"
|
||||||
|
private var devicesID = ""
|
||||||
|
private val appStartJson = JsonObject()
|
||||||
|
private var dataId = 0L
|
||||||
|
private var simId = 0L
|
||||||
|
private val aidlClient = AIDLClient.instance
|
||||||
|
private var isProcessComplete = true //流程是否完毕
|
||||||
|
private var remoteIp = "0.0.0.0"//上传到服务的IP
|
||||||
|
|
||||||
|
private val onAdShownLiveData = MutableLiveData<Boolean>()
|
||||||
|
private val onAdShowFailedLiveData = MutableLiveData<Boolean>()
|
||||||
|
private val onAdClosedLiveData = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
@SuppressLint("MissingInflatedId", "SetTextI18n")
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = ActivityMain2Binding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
binding.title.text = "TradPlus(1月5日)-${getString(R.string.app_name)}"
|
||||||
|
// 异步获取 IP,不影响主流程
|
||||||
|
lifecycleScope.launch {
|
||||||
|
remoteIp = getPublicIpAddress()
|
||||||
|
loadJson.addProperty("remoteIp", remoteIp)//远程IP
|
||||||
|
showJson.addProperty("remoteIp", remoteIp)//远程IP
|
||||||
|
}
|
||||||
|
TradPlusSdk.initSdk(this, "2F7E23998B25E09E546263F2CABDFF11")
|
||||||
|
TradPlusSdk.setTradPlusInitListener(object : TradPlusSdk.TradPlusInitListener {
|
||||||
|
override fun onInitSuccess() {
|
||||||
|
appendLoadingTxt("初始化成功")
|
||||||
|
lifecycle.addObserver(AppLifecycleTracker)
|
||||||
|
//初始化aidl连接
|
||||||
|
aidlClient.initConnection()
|
||||||
|
//绑定AIDL服务
|
||||||
|
aidlClient.connectService(this@MainActivity2)
|
||||||
|
aidlClient.connectCompleteLiveData.observeForever(connectCompleteObserver)
|
||||||
|
|
||||||
|
aidlClient.paramCompleteLiveData.observeForever(paramCompleteObserver)
|
||||||
|
aidlClient.clickAdCompleteLiveData.observeForever(clickAdCompleteObserver)
|
||||||
|
|
||||||
|
onAdShownLiveData.observeForever(onAdShownObserver)
|
||||||
|
onAdShowFailedLiveData.observeForever(onAdShowFailedObserver)
|
||||||
|
onAdClosedLiveData.observeForever(onAdCloseObserver)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private val connectCompleteObserver = Observer<Boolean> {
|
||||||
|
if (it) {
|
||||||
|
appendLoadingTxt("CP控制器连接成功,进行初始化配置")
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
//初始化配置
|
||||||
|
initConfig()
|
||||||
|
//初始化屏幕点击范围
|
||||||
|
magicLockInit()
|
||||||
|
} else {
|
||||||
|
appendLoadingTxt("CP控制器连接失败,检查是否安装了正确的软件")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val paramCompleteObserver = Observer<Boolean> {
|
||||||
|
TimeoutManager.cancelTimeout(TimeoutTask.PARAM_CHANGE)
|
||||||
|
appendLoadingTxt("参数修改完成")
|
||||||
|
Log.d("ocean-brush", "MainActivity 参数修改操作完成->$it")
|
||||||
|
if (it) {
|
||||||
|
aidlClient.sendResetApp(packageName)
|
||||||
|
} else {
|
||||||
|
appendLoadingTxt("参数修改失败,等待${paramTimeLeft}秒再次进行参数修改")
|
||||||
|
startParamCountdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val clickAdCompleteObserver = Observer<Boolean> {
|
||||||
|
Log.d("ocean-brush", "MainActivity 监听到点击广告指令完成")
|
||||||
|
if (it) {
|
||||||
|
if (AppLifecycleTracker.isMainActivityVisible) {
|
||||||
|
Log.d(
|
||||||
|
"ocean-brush",
|
||||||
|
"MainActivity 成功回到前台,取消点击超时任务,并置 isProcessComplete = true"
|
||||||
|
)
|
||||||
|
TimeoutManager.cancelTimeout(TimeoutTask.CLICK_AD)
|
||||||
|
isProcessComplete = true
|
||||||
|
} else {
|
||||||
|
Log.d("ocean-brush", "MainActivity 但是没有回到前台,进行修改参数重置")
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d("ocean-brush", "MainActivity 但是intent=null,进行修改参数重置")
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val onAdShownObserver = Observer<Boolean> {
|
||||||
|
Log.d("ocean-brush", "MainActivity 监听到广告展示成功")
|
||||||
|
TimeoutManager.cancelTimeout(TimeoutTask.SHOW_AD)
|
||||||
|
val isSendClick = aidlClient.sendClickAd(clickThroughRate, packageName)
|
||||||
|
if (isSendClick) {//指令发送成功
|
||||||
|
//广告展示后,启动广告关闭超时任务
|
||||||
|
TimeoutManager.startTimeout(TimeoutTask.CLOSE_AD) {//十秒
|
||||||
|
Log.d("ocean-brush", "超时任务,广告关闭失败,直接进行改参重置")
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
//发送点击广告指令后,启动点击广告的超时任务
|
||||||
|
TimeoutManager.startTimeout(TimeoutTask.CLICK_AD) {
|
||||||
|
Log.d("ocean-brush", "超时任务,广告点击流程没有回来,直接进行重置")
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val onAdShowFailedObserver = Observer<Boolean> {
|
||||||
|
Log.d("ocean-brush", "MainActivity 监听到广告展示失败,直接进行重置")
|
||||||
|
TimeoutManager.cancelTimeout(TimeoutTask.SHOW_AD)
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val onAdCloseObserver = Observer<Boolean> {
|
||||||
|
Log.d("ocean-brush", "MainActivity 监听到广告被关闭")
|
||||||
|
TimeoutManager.cancelTimeout(TimeoutTask.CLOSE_AD)
|
||||||
|
|
||||||
|
// val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||||
|
// val runningTasks = activityManager.getRunningTasks(10)
|
||||||
|
//
|
||||||
|
// for (task in runningTasks) {
|
||||||
|
// if (task.topActivity?.className?.contains("com.vungle.ads.internal.ui.VungleActivity") == true) {
|
||||||
|
// Log.d("AD_KILLER", "发现 VungleActivity,尝试关闭")
|
||||||
|
// Runtime.getRuntime().exec("am force-stop com.vungle.ads")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initConfig() {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
val fromCpGuise = intent?.getBooleanExtra("EXTRA_FROM_CP_GUISE_RESET", false) ?: false
|
||||||
|
if (fromCpGuise) {
|
||||||
|
Log.d("ocean-brush", "App2 是从 CP reset 启动的!通知cp知道")
|
||||||
|
aidlClient.sendReceiveResetOpenSuccessfully()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.applicationId.text = packageName
|
||||||
|
getDeviceIdFromProvider { content, b ->
|
||||||
|
appendLoadingTxt("${b}设备ID:$content")
|
||||||
|
if (content != null) {
|
||||||
|
devicesID = content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataId = IdProvider().getId()
|
||||||
|
simId = SimIdProvider().getSimId()
|
||||||
|
val hookInfo =
|
||||||
|
"dataId->$dataId," + "simId->$simId" + "制造商:${Build.MANUFACTURER}," + "型号:${Build.MODEL}," + "国家:${
|
||||||
|
getSimCountryIso(this@MainActivity2)
|
||||||
|
}," + "MCC:${mcc()}," + "MNC:${mnc()}"
|
||||||
|
appendLoadingTxt(hookInfo)
|
||||||
|
if (dataId == 0L) {
|
||||||
|
appendLoadingTxt("dataId返回的默认值,hook没生效,修改参数重试")
|
||||||
|
startCountdown()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
MyConfigUtil.getConfig(packageName, object : ConfigCallback {
|
||||||
|
override fun onResponse(result: String) {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Log.d("ocean-brush", "加载config配置成功")
|
||||||
|
Log.d("ocean", "result->${result}")
|
||||||
|
val json = JSONObject(result)
|
||||||
|
val dataJson = json.optJSONObject("data")
|
||||||
|
if (dataJson != null) {
|
||||||
|
quantity = dataJson.optString("quantity")
|
||||||
|
ecpmCool = dataJson.optString("ecpmCool")
|
||||||
|
ecpmLow = dataJson.optString("ecpmLow")
|
||||||
|
clickThroughRate = dataJson.optInt("clickThroughRate")
|
||||||
|
appendLoadingTxt("配置->quantity:${quantity},ecpmCool:${ecpmCool},ecpmLow:${ecpmLow},点击:${clickThroughRate}")
|
||||||
|
getBidJson()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(e: IOException) {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Log.d("ocean-brush", "加载config配置失败")
|
||||||
|
val message = "message=${e.message}"
|
||||||
|
appendLoadingTxt("$message \n Config获取失败,请检查是否在后台配置包名,${timeLeft}秒后将会重置")
|
||||||
|
runOnUiThread {
|
||||||
|
startCountdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun magicLockInit() {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
MagicLock.getInstance(application)
|
||||||
|
.addMagicActionListener(object : MagicLock.MagicActionListener {
|
||||||
|
override fun insAreaClick() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun rewardAreaClick() {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
timer = Timer()
|
||||||
|
timer!!.schedule(object : TimerTask() {
|
||||||
|
override fun run() {
|
||||||
|
runOnUiThread {
|
||||||
|
if ((loadAndShowAdNumber <= 0 || adPlace.size <= 0)) {
|
||||||
|
/**
|
||||||
|
* 没有广告的情况
|
||||||
|
* [startInit]广告已经进入过初始化
|
||||||
|
* [isAnyAdLoading]没有广告在loading中
|
||||||
|
* [isProcessComplete]每次流程是否执行完毕
|
||||||
|
* [AppLifecycleTracker.isMainActivityVisible]应用已经恢复到前台展示
|
||||||
|
* 满足条件则进行重置,发送修改参数指令
|
||||||
|
*/
|
||||||
|
if (startInit && !isAnyAdLoading() && isProcessComplete && AppLifecycleTracker.isMainActivityVisible) {
|
||||||
|
//更新UI,显示为 true
|
||||||
|
MagicLock.getInstance(application)
|
||||||
|
.refreshStartResetView(this@MainActivity2, true)
|
||||||
|
//发送修改参数指令
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* 有广告可以展示
|
||||||
|
* [isProcessComplete]流程已经执行完毕
|
||||||
|
* [AppLifecycleTracker.isMainActivityVisible]应用已经恢复到前台展示
|
||||||
|
* 满足条件发送show指令
|
||||||
|
*/
|
||||||
|
if (isProcessComplete && AppLifecycleTracker.isMainActivityVisible) {
|
||||||
|
//开始执行点击流程时,置为false
|
||||||
|
isProcessComplete = false
|
||||||
|
showInsAd()
|
||||||
|
//启动show超时检测,然后在show成功与show失败取消超时任务
|
||||||
|
TimeoutManager.startTimeout(TimeoutTask.SHOW_AD) {
|
||||||
|
//超时都没有show出来则流程重置,让time下次判定可以去show广告
|
||||||
|
isProcessComplete = true
|
||||||
|
}
|
||||||
|
// 开始流程后,启动是否有广告卡住流程的超时任务。100秒
|
||||||
|
TimeoutManager.startTimeout(TimeoutTask.OVERALL_PROCESS) {
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MagicLock.getInstance(application)
|
||||||
|
.refreshInsCountView(this@MainActivity2, adPlace.size)
|
||||||
|
//在TimerTask任务中判定流程已经完毕,并且是否回到了mainActivity,回来则取消超时
|
||||||
|
//超过没有回来,则判定为卡住了。
|
||||||
|
if (isProcessComplete && AppLifecycleTracker.isMainActivityVisible) {
|
||||||
|
TimeoutManager.cancelTimeout(TimeoutTask.OVERALL_PROCESS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//发送广告数量
|
||||||
|
aidlClient.sendAdsChange(packageName, getInsAdReturnCount())
|
||||||
|
|
||||||
|
//通信cp,用于心跳检测
|
||||||
|
aidlClient.sendHeartBeat(packageName)
|
||||||
|
}
|
||||||
|
}, 2000, 2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有广告在加载中
|
||||||
|
fun isAnyAdLoading(): Boolean {
|
||||||
|
return loadingAds.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initAd() {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Log.d("ocean-brush", "开始加载三个广告")
|
||||||
|
startInit = true
|
||||||
|
appendLoadingTxt("开始加载三个广告")
|
||||||
|
loadAd(AdsInsUtil.Placement.TOP_ON_AD_ONE)
|
||||||
|
loadAd(AdsInsUtil.Placement.TOP_ON_AD_TOW)
|
||||||
|
loadAd(AdsInsUtil.Placement.TOP_ON_AD_THREE)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadAd(placeId: String) {
|
||||||
|
val startLoadTime = System.currentTimeMillis()
|
||||||
|
loadingAds.add(placeId)
|
||||||
|
|
||||||
|
loadAdNumber++//广告load计数(进入loadAd方法就进行计数)
|
||||||
|
|
||||||
|
AdsInsUtil.loadAd(this, placeId, object : LoadListener {
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
override fun loaded(ad: TPAdInfo) {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
val loadedEndTime = System.currentTimeMillis()
|
||||||
|
appendLoadingTxt("${placeId}AD加载成功")
|
||||||
|
aidlClient.sendAdsChange(packageName, getInsAdReturnCount())
|
||||||
|
// 将 ecpm 转换为 BigDecimal 类型,并进行除法运算
|
||||||
|
val result = BigDecimal(ad.ecpm.toDouble()).divide(
|
||||||
|
BigDecimal(1000),
|
||||||
|
20,
|
||||||
|
RoundingMode.HALF_UP
|
||||||
|
)
|
||||||
|
// 将结果转换为字符串表示形式
|
||||||
|
val formattedString: String = result.toPlainString()
|
||||||
|
Log.d("ocean", "scientificNotation->${formattedString}")
|
||||||
|
appendLoadingTxt("${ad.adNetworkId} ecpm->$formattedString")
|
||||||
|
Log.d("ocean", "平台->${ad.adNetworkId} ecpm->${formattedString}")
|
||||||
|
loadJson.addProperty("succeed", true)//广告加载是否成功
|
||||||
|
loadJson.addProperty("loadTime", loadedEndTime - startLoadTime)//加载时间
|
||||||
|
loadJson.addProperty("adPlatform", "TradPlus")//广告平台
|
||||||
|
loadJson.addProperty("countryCode", ad.format)//国家代码
|
||||||
|
loadJson.addProperty("adId", placeId)//广告Id
|
||||||
|
loadJson.addProperty("platformResponseTime", "")//平台广告响应时间
|
||||||
|
loadJson.addProperty("ecpm", formattedString)//广告单价
|
||||||
|
loadJson.addProperty("dsp", ad.adNetworkId)
|
||||||
|
loadJson.addProperty("network", ad.adNetworkId)
|
||||||
|
loadJson.addProperty("washParam", false)
|
||||||
|
|
||||||
|
//load广告,只有价格大于等于配置的最低值则添加到可以show的广告集合中
|
||||||
|
if (formattedString.toFloat() >= ecpmLow.toFloat()) {
|
||||||
|
Log.d("ocean", "onAdLoaded add ->${placeId}")
|
||||||
|
adPlace.add(placeId)
|
||||||
|
loadAndShowAdNumber++
|
||||||
|
loadJson.addProperty("showStatus", "0")
|
||||||
|
} else {
|
||||||
|
loadJson.addProperty("showStatus", "-1")
|
||||||
|
}
|
||||||
|
|
||||||
|
viewJson.addProperty("广告加载时间", loadedEndTime - startLoadTime)
|
||||||
|
viewJson.addProperty("ecpmLow", ecpmLow)
|
||||||
|
viewJson.addProperty("ecpm", formattedString)
|
||||||
|
viewJson.addProperty("是否满足show", formattedString.toFloat() >= ecpmLow.toFloat())
|
||||||
|
appendInfoTxt(viewJson.toString())
|
||||||
|
|
||||||
|
MyConfigUtil.initPostLoadLog(loadJson)
|
||||||
|
|
||||||
|
loadingAds.remove(placeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadFailed(error: String) {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
val loadedEndTime = System.currentTimeMillis()
|
||||||
|
loadJson.addProperty("succeed", false)//广告加载是否成功
|
||||||
|
loadJson.addProperty("loadTime", loadedEndTime - startLoadTime)//加载时间
|
||||||
|
loadJson.addProperty("adPlatform", "TradPlus")//广告平台
|
||||||
|
loadJson.addProperty("adId", placeId)//广告Id
|
||||||
|
loadJson.addProperty("washParam", false)
|
||||||
|
loadJson.addProperty("errorData", error)
|
||||||
|
|
||||||
|
MyConfigUtil.initPostLoadLog(loadJson)
|
||||||
|
|
||||||
|
Log.d("ocean", "error->${error.toString()}")
|
||||||
|
aidlClient.sendAdsChange(packageName, getInsAdReturnCount())
|
||||||
|
loadingAds.remove(placeId)
|
||||||
|
appendLoadingTxt("${placeId}AD加载失败-${error}")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private val msgSB = StringBuilder()
|
||||||
|
private fun appendInfoTxt(msg: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
msgSB.appendLine(msg)
|
||||||
|
binding.infoTv.text = msgSB.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val msgLoading = StringBuilder()
|
||||||
|
private fun appendLoadingTxt(msg: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
msgLoading.appendLine(msg)
|
||||||
|
binding.loadingTv.text = msgLoading.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInsAdReturnCount(): Int {
|
||||||
|
return InstAdCacheManager.instance.getLoadedInstCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showInsAd() {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Log.d("ocean-brush", "满足条件,开始展示广告")
|
||||||
|
//随机
|
||||||
|
Log.d("ocean", " show广告集合是否有值:${adPlace.size}")
|
||||||
|
if (adPlace.isNotEmpty()) {
|
||||||
|
val placeId = Random().nextInt(adPlace.size)
|
||||||
|
val place = adPlace[placeId]
|
||||||
|
adPlace.remove(place)
|
||||||
|
|
||||||
|
AdsInsUtil.showAd(this, place, object : ShowListener {
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
override fun onAdShown(ad: TPAdInfo?) {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
onAdShownLiveData.value = true
|
||||||
|
}
|
||||||
|
// 将 ecpm 转换为 BigDecimal 类型,并进行除法运算
|
||||||
|
val ecpm = ad?.ecpm?.toDouble() ?: 0.0
|
||||||
|
val result = BigDecimal(ecpm).divide(BigDecimal(1000), 20, RoundingMode.HALF_UP)
|
||||||
|
// 将结果转换为字符串表示形式
|
||||||
|
val formattedString: String = result.toPlainString()
|
||||||
|
showJson.addProperty("succeed", true)//广告加载是否成功
|
||||||
|
showJson.addProperty("adPlatform", "Max")//广告平台
|
||||||
|
showJson.addProperty("countryCode", ad?.format ?: "")//国家代码
|
||||||
|
showJson.addProperty("adId", place)//广告Id
|
||||||
|
showJson.addProperty("platformResponseTime", "")//平台广告响应时间
|
||||||
|
showJson.addProperty("ecpm", formattedString)//广告单价
|
||||||
|
showJson.addProperty("dsp", ad?.adNetworkId ?: "")
|
||||||
|
showJson.addProperty("network", ad?.adNetworkId ?: "")
|
||||||
|
MyConfigUtil.initPostShowLog(showJson)
|
||||||
|
|
||||||
|
Log.d("ocean", "onAdShown decimalNumber->$formattedString")
|
||||||
|
|
||||||
|
Log.d("ocean", "onAdShown loadAdNumber->${loadAdNumber}")
|
||||||
|
Log.d("ocean", "onAdShown quantity.toInt()->${quantity.toInt()}")
|
||||||
|
if (loadAdNumber < quantity.toInt()) {//不能大于配置的数量
|
||||||
|
if (ecpmCool.isNotEmpty()) {
|
||||||
|
//满足配置的最高的价格则重新load这个被消耗的
|
||||||
|
Log.d("ocean", "onAdShown ecpmCool->${ecpmCool}")
|
||||||
|
Log.d("ocean", "onAdShown ecpmCool.toFloat()->${ecpmCool.toFloat()}")
|
||||||
|
if (formattedString.toFloat() >= ecpmCool.toFloat()) {
|
||||||
|
loadAd(place)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("scanner_ad onAdShown")
|
||||||
|
aidlClient.sendAdsChange(packageName, getInsAdReturnCount(), 1, 0)
|
||||||
|
loadAndShowAdNumber--
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAdClicked() {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Log.d("ocean", " 点击show广告")
|
||||||
|
aidlClient.sendAdsChange(packageName, getInsAdReturnCount(), 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAdShowFailed(error: AdShowFailed?) {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
onAdShowFailedLiveData.value = true
|
||||||
|
}
|
||||||
|
Log.d("ocean", " show广告失败")
|
||||||
|
aidlClient.sendAdsChange(packageName, getInsAdReturnCount())
|
||||||
|
loadAndShowAdNumber--
|
||||||
|
showJson.addProperty("succeed", false)//广告加载是否成功
|
||||||
|
showJson.addProperty("adPlatform", "Max")//广告平台
|
||||||
|
showJson.addProperty("adId", place)//广告Id
|
||||||
|
MyConfigUtil.initPostShowLog(showJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAdClosed() {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
onAdClosedLiveData.value = true
|
||||||
|
}
|
||||||
|
aidlClient.sendAdsChange(packageName, getInsAdReturnCount())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//路径 /storage/emulated/0/phone.xml
|
||||||
|
private fun getBidJson() {
|
||||||
|
aidlClient.sendBrushMiss()
|
||||||
|
Log.d("ocean-brush", "组装load数据与show数据上传,并且获取gaid")
|
||||||
|
val linkId = UUID.randomUUID().toString().replace("-", "")
|
||||||
|
GlobalScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val gaId = AdvertisingIdClient.getAdvertisingIdInfo(this@MainActivity2).id
|
||||||
|
Log.d("ocean", "getAdvertisingIdInfo gaId->${gaId}")
|
||||||
|
|
||||||
|
viewJson.addProperty("设备ID", devicesID)
|
||||||
|
viewJson.addProperty("货架号", shelfNumber)
|
||||||
|
// viewJson.addProperty("IP获取时间", endIpTime - startIpTime)
|
||||||
|
|
||||||
|
loadJson.addProperty("deviceId", devicesID)
|
||||||
|
loadJson.addProperty("shelfNumber", shelfNumber)//货架号
|
||||||
|
loadJson.addProperty("localIp", getLocalIpAddress())//本地IP
|
||||||
|
loadJson.addProperty("linkId", linkId)//链路Id
|
||||||
|
loadJson.addProperty("packageName", packageName)//包名
|
||||||
|
loadJson.addProperty("gaid", gaId)
|
||||||
|
loadJson.addProperty("dataId", dataId)
|
||||||
|
loadJson.addProperty("carrierId",simId)
|
||||||
|
loadJson.addProperty("getIpResponseTime", 0)
|
||||||
|
loadJson.addProperty("packageVersion", 1)
|
||||||
|
loadJson.addProperty("version", 3)
|
||||||
|
loadJson.addProperty("phoneVersion", Build.MODEL)
|
||||||
|
|
||||||
|
showJson.addProperty("deviceId", devicesID)
|
||||||
|
showJson.addProperty("shelfNumber", shelfNumber)
|
||||||
|
showJson.addProperty("localIp", getLocalIpAddress())//本地IP
|
||||||
|
showJson.addProperty("linkId", linkId)//链路Id
|
||||||
|
showJson.addProperty("packageName", packageName)//包名
|
||||||
|
showJson.addProperty("gaid", gaId)
|
||||||
|
showJson.addProperty("dataId", dataId)
|
||||||
|
showJson.addProperty("carrierId",simId)
|
||||||
|
showJson.addProperty("getIpResponseTime", 0)
|
||||||
|
showJson.addProperty("version", 3)
|
||||||
|
showJson.addProperty("phoneVersion", Build.MODEL)
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
binding.gaidTv.text = gaId
|
||||||
|
if (gaId != null) {
|
||||||
|
if (gaId == gaIdError) {
|
||||||
|
binding.gaidLayout.setBackgroundColor(getColor(R.color.red))
|
||||||
|
//gaID没有确的值就发送重置广播
|
||||||
|
appendLoadingTxt("没有获取到GAID,$timeLeft 秒后将会重置")
|
||||||
|
startCountdown()
|
||||||
|
} else {
|
||||||
|
binding.gaidLayout.setBackgroundColor(getColor(R.color.green))
|
||||||
|
initAd()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
appendLoadingTxt("没有获取到GAID,$timeLeft 秒后将会重置")
|
||||||
|
startCountdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://api.tikustok.com/app/common/getIPInfo
|
||||||
|
* https://openapi.lux-ad.com/app/common/getIPInfo
|
||||||
|
*/
|
||||||
|
private suspend fun getPublicIpAddress(): String = suspendCoroutine { continuation ->
|
||||||
|
var publicIp = "0.0.0.0"
|
||||||
|
try {
|
||||||
|
VmHttpUtil.mInstance.getIPInfo(
|
||||||
|
"https://openapi.lux-ad.com/app/common/getIPInfo",
|
||||||
|
object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
runOnUiThread {
|
||||||
|
appendLoadingTxt("获取IP失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
continuation.resume(publicIp)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
Log.d("ocean", "getIPInfo response->${response}")
|
||||||
|
if (response.code == 200) {
|
||||||
|
val responseData = response.body?.string()
|
||||||
|
if (responseData != null) {
|
||||||
|
val jsonObject = JSONObject(responseData)
|
||||||
|
Log.d("ocean", "getIPInfo jsonObject->${jsonObject}")
|
||||||
|
val status = jsonObject.optString("status")
|
||||||
|
if (status == "Success") {
|
||||||
|
val data = jsonObject.getJSONObject("data")
|
||||||
|
appendLoadingTxt("获取IP成功->${data}")
|
||||||
|
Log.d("ocean", "getIPInfo data->${data}")
|
||||||
|
publicIp = data.optString("ip")
|
||||||
|
continuation.resume(publicIp)
|
||||||
|
} else {
|
||||||
|
continuation.resume(publicIp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continuation.resume(publicIp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runOnUiThread {
|
||||||
|
appendLoadingTxt("获取IP失败->${response}")
|
||||||
|
}
|
||||||
|
continuation.resume(publicIp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
appendLoadingTxt("获取IP失败 catch->${e}")
|
||||||
|
continuation.resume(publicIp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
aidlClient.connectCompleteLiveData.removeObserver(connectCompleteObserver)
|
||||||
|
aidlClient.paramCompleteLiveData.removeObserver(paramCompleteObserver)
|
||||||
|
aidlClient.clickAdCompleteLiveData.removeObserver(clickAdCompleteObserver)
|
||||||
|
onAdShownLiveData.removeObserver(onAdShownObserver)
|
||||||
|
onAdShowFailedLiveData.removeObserver(onAdShowFailedObserver)
|
||||||
|
onAdClosedLiveData.removeObserver(onAdCloseObserver)
|
||||||
|
aidlClient.disconnect(this)
|
||||||
|
stopCountdown()
|
||||||
|
stopParamCountdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSimCountryIso(context: Activity): String {
|
||||||
|
val telephonyManager = context.getSystemService("phone") as TelephonyManager?
|
||||||
|
return telephonyManager?.simCountryIso?.uppercase(Locale.ENGLISH) ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mnc(): String {
|
||||||
|
val telephonyManager = getSystemService("phone") as TelephonyManager
|
||||||
|
return try {
|
||||||
|
val networkOperator = telephonyManager.networkOperator
|
||||||
|
networkOperator.substring(3.coerceAtMost(networkOperator.length))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mcc(): String {
|
||||||
|
val telephonyManager = getSystemService("phone") as TelephonyManager
|
||||||
|
return try {
|
||||||
|
val networkOperator = telephonyManager.networkOperator
|
||||||
|
networkOperator.substring(0, minOf(3, networkOperator.length))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("Range")
|
||||||
|
fun getDeviceIdFromProvider(callback: (String?, Boolean) -> Unit) {
|
||||||
|
val uri = Uri.parse("content://com.guise.deviceidprovider/device_id")
|
||||||
|
val cursor = contentResolver.query(uri, null, null, null, null)
|
||||||
|
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
val deviceId = cursor.getString(cursor.getColumnIndex("device_id"))
|
||||||
|
cursor.close() // 关闭 Cursor
|
||||||
|
callback(deviceId, true) // 成功读取到 Device ID
|
||||||
|
} else {
|
||||||
|
callback(null, false) // 读取失败
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用进行重置,五秒倒计时
|
||||||
|
*/
|
||||||
|
private var timeLeft = 5 // 倒计时时间
|
||||||
|
private val countdownHandler = Handler(Looper.getMainLooper())
|
||||||
|
private val countdownRunnable = object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
if (timeLeft > 0) {
|
||||||
|
appendLoadingTxt("⏳ 剩余 $timeLeft 秒后执行 修改参数 指令")
|
||||||
|
timeLeft--
|
||||||
|
countdownHandler.postDelayed(this, 1000) // 继续倒计时
|
||||||
|
} else {
|
||||||
|
appendLoadingTxt("🚀 执行 修改参数 指令")
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startCountdown() {
|
||||||
|
timeLeft = 5 // 重新初始化时间
|
||||||
|
countdownHandler.post(countdownRunnable) // 开始倒计时
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopCountdown() {
|
||||||
|
countdownHandler.removeCallbacks(countdownRunnable) // 取消倒计时
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数修改失败,重新修改倒计时
|
||||||
|
*/
|
||||||
|
private var paramTimeLeft = 15
|
||||||
|
private val countdownParamHandler = Handler(Looper.getMainLooper())
|
||||||
|
private val countdownParamRunnable = object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
if (paramTimeLeft > 0) {
|
||||||
|
paramTimeLeft--
|
||||||
|
countdownParamHandler.postDelayed(this, 1000) // 继续倒计时
|
||||||
|
} else {
|
||||||
|
appendLoadingTxt("执行修改参数指令")
|
||||||
|
aidlClient.sendChangeParameters(packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startParamCountdown() {
|
||||||
|
paramTimeLeft = 15 // 重新初始化时间
|
||||||
|
countdownParamHandler.post(countdownParamRunnable) // 开始倒计时
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopParamCountdown() {
|
||||||
|
countdownParamHandler.removeCallbacks(countdownParamRunnable) // 取消倒计时
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
package com.cake.draw.painting.environment
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import okhttp3.Callback
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import java.io.IOException
|
||||||
|
import java.security.SecureRandom
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import javax.net.ssl.SSLContext
|
||||||
|
import javax.net.ssl.TrustManager
|
||||||
|
import javax.net.ssl.X509TrustManager
|
||||||
|
|
||||||
|
class VmHttpUtil {
|
||||||
|
|
||||||
|
fun isNetworkAvailable(context: Context): Boolean {
|
||||||
|
val connectivityManager =
|
||||||
|
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
val activeNetworkInfo = connectivityManager?.activeNetworkInfo
|
||||||
|
return activeNetworkInfo != null && activeNetworkInfo.isConnected
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mOkHttpClient: OkHttpClient? = null
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val mInstance: VmHttpUtil by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||||
|
VmHttpUtil()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val CONNECT_TIMEOUT: Long = 60 //超时时间,秒
|
||||||
|
|
||||||
|
private val READ_TIMEOUT: Long = 60 //读取时间,秒
|
||||||
|
|
||||||
|
private val WRITE_TIMEOUT: Long = 60 //写入时间,秒
|
||||||
|
|
||||||
|
init {
|
||||||
|
// ---- 不安全:信任所有证书(仅测试用) ----
|
||||||
|
val trustAllCerts = arrayOf<TrustManager>(
|
||||||
|
object : X509TrustManager {
|
||||||
|
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
|
||||||
|
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
|
||||||
|
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
val sslContext = SSLContext.getInstance("TLS")
|
||||||
|
sslContext.init(null, trustAllCerts, SecureRandom())
|
||||||
|
val sslSocketFactory = sslContext.socketFactory
|
||||||
|
|
||||||
|
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
|
||||||
|
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
|
||||||
|
mOkHttpClient = builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mediaType = "application/json; charset=utf-8".toMediaType()
|
||||||
|
|
||||||
|
fun getIPInfo(url: String, callback: Callback) {
|
||||||
|
val request: Request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.get()
|
||||||
|
.build()
|
||||||
|
doAsync(request, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步请求
|
||||||
|
*/
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun doAsync(request: Request, callback: Callback) {
|
||||||
|
//创建请求会话
|
||||||
|
val call = mOkHttpClient!!.newCall(request)
|
||||||
|
//同步执行会话请求
|
||||||
|
call.enqueue(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,177 @@
|
|||||||
|
package com.cake.draw.painting.environment.ad
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.Log
|
||||||
|
import com.cake.draw.painting.environment.ad.async.Async
|
||||||
|
import com.unity3d.services.ads.adunit.AdUnitActivity
|
||||||
|
import com.vungle.ads.internal.ui.AdActivity
|
||||||
|
import com.vungle.ads.internal.ui.view.MRAIDAdWidget
|
||||||
|
|
||||||
|
class AdActivityManager {
|
||||||
|
private var mCurrentShowAd: Activity? = null//记录当前正在展示的inst广告Activity
|
||||||
|
private var mApplicationContext: Context? = null
|
||||||
|
private var mAID: String? = null
|
||||||
|
private var mListener: InstAdLeaveAndReturnListener? = null
|
||||||
|
private var isAdClosed = false//当广告点击了close按钮的时候 设置成true
|
||||||
|
private var isAdClicked = false//标记inst是否已是已点击状态
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val instance: AdActivityManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||||
|
AdActivityManager()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isAdActivity(activity: Activity): Boolean {
|
||||||
|
return (
|
||||||
|
activity is com.tradplus.ads.mgr.interstitial.views.InterNativeActivity
|
||||||
|
|| activity is com.vungle.ads.internal.ui.VungleActivity
|
||||||
|
|| activity is com.vungle.ads.internal.ui.AdActivity
|
||||||
|
|| activity is AdUnitActivity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCurrentShowAd(): Activity? {
|
||||||
|
return mCurrentShowAd
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doDelayClose(delay: Long) {
|
||||||
|
Async.scheduleTaskOnUiThread(delay, Runnable { doClose() })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*手动关闭当前显示的inst,具体支持哪些平台的inst,在 onActivityResumed 中添加
|
||||||
|
*/
|
||||||
|
fun doClose() {
|
||||||
|
mCurrentShowAd?.let { adActivity ->
|
||||||
|
Log.d("ocean-brush", "自动关闭 $adActivity")
|
||||||
|
when (adActivity) {
|
||||||
|
is AdActivity ->{
|
||||||
|
//反射方式关闭
|
||||||
|
try {
|
||||||
|
// 获取 mraidAdWidget 字段
|
||||||
|
val field = AdActivity::class.java.getDeclaredField("mraidAdWidget")
|
||||||
|
field.isAccessible = true
|
||||||
|
val widget = field.get(adActivity) as? MRAIDAdWidget
|
||||||
|
Log.d("ocean-brush", "调用 widget.close(),触发 CloseDelegate -> finish()")
|
||||||
|
widget?.close() ?: run {
|
||||||
|
// 没拿到 widget
|
||||||
|
adActivity.onBackPressed()
|
||||||
|
Log.d("ocean-brush", "liftoff关闭使用onBackPressed()")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
adActivity.finish()
|
||||||
|
adActivity.moveTaskToBack(true)
|
||||||
|
Log.d("ocean-brush", "liftoff关闭错误,直接finish")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
//关闭广告act
|
||||||
|
adActivity.finish()
|
||||||
|
// 强制移除任务栈(适用于某些广告 Activity 仍然存活的情况)
|
||||||
|
adActivity.moveTaskToBack(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getContext(): Context? {
|
||||||
|
return mApplicationContext
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAID(): String? {
|
||||||
|
return mAID
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addActivityLifeCallbacks(callbacks: Application.ActivityLifecycleCallbacks?) {
|
||||||
|
(mApplicationContext as Application).registerActivityLifecycleCallbacks(callbacks)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeActivityLifeCallbacks(callbacks: Application.ActivityLifecycleCallbacks?) {
|
||||||
|
(mApplicationContext as Application).unregisterActivityLifecycleCallbacks(callbacks)
|
||||||
|
}
|
||||||
|
|
||||||
|
//在Application中调用
|
||||||
|
@SuppressLint("HardwareIds")
|
||||||
|
fun setControl(application: Application) {
|
||||||
|
mApplicationContext = application
|
||||||
|
application.registerActivityLifecycleCallbacks(object :
|
||||||
|
Application.ActivityLifecycleCallbacks {
|
||||||
|
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityStarted(activity: Activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResumed(activity: Activity) {
|
||||||
|
//此处添加想要控制的广告平台的inst Activity
|
||||||
|
try {
|
||||||
|
if (isAdActivity(activity)) {
|
||||||
|
mCurrentShowAd = activity
|
||||||
|
if (isAdClicked) {
|
||||||
|
//点击了admob inst跳转到外部,然后从外部返回app的时候触发
|
||||||
|
mListener?.onReturnAdFromOutside()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityPaused(activity: Activity) {
|
||||||
|
try {
|
||||||
|
if (mCurrentShowAd != null) {
|
||||||
|
if (isAdActivity(activity)) {//onActivityPaused会在很多场景下触发:1.退到桌面 2.去往app外部 3.被dialog挡住 4.广告点击了close按钮销毁的过程中
|
||||||
|
if (!isAdClosed) {//isAdClosed这里就是为了排除"4.广告点击了close按钮销毁的过程中"
|
||||||
|
//需要在不同展示场景中实际测试
|
||||||
|
mListener?.onLeaveAdGoOutside()
|
||||||
|
isAdClicked = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityStopped(activity: Activity) {}
|
||||||
|
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||||
|
override fun onActivityDestroyed(activity: Activity) {
|
||||||
|
Log.d("ocean-brush", "onActivityDestroyed $activity $mCurrentShowAd")
|
||||||
|
if (mCurrentShowAd === activity) {
|
||||||
|
mCurrentShowAd = null
|
||||||
|
isAdClosed = false
|
||||||
|
isAdClicked = false
|
||||||
|
mListener = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
mAID = hashCode().toString() + ""
|
||||||
|
if (mApplicationContext != null) {
|
||||||
|
mAID = Settings.Secure.getString(
|
||||||
|
mApplicationContext?.contentResolver, Settings.Secure.ANDROID_ID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setAdClose(isClosing: Boolean) {
|
||||||
|
isAdClosed = isClosing
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setInstAdListener(listener: InstAdLeaveAndReturnListener) {
|
||||||
|
mListener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InstAdLeaveAndReturnListener {
|
||||||
|
fun onLeaveAdGoOutside()//1.点击ad跳转到外部 2.app切换到后台 3.被dialog遮挡
|
||||||
|
fun onReturnAdFromOutside()//从外部返回ad页面, 通常是点击ad跳转到外部后返回ad页面
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,7 @@
|
|||||||
package com.cake.draw.painting.ad
|
package com.cake.draw.painting.environment.ad
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.mbridge.msdk.interstitial.signalcommon.interstitial
|
|
||||||
import com.tradplus.ads.base.bean.TPAdError
|
import com.tradplus.ads.base.bean.TPAdError
|
||||||
import com.tradplus.ads.base.bean.TPAdInfo
|
import com.tradplus.ads.base.bean.TPAdInfo
|
||||||
import com.tradplus.ads.open.interstitial.InterstitialAdListener
|
import com.tradplus.ads.open.interstitial.InterstitialAdListener
|
||||||
@ -27,67 +26,54 @@ class AdInstLoad {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun init() {
|
private fun init() {
|
||||||
val interstitialAd = InstAdCacheManager.instance.getAdCache(mPlace)
|
|
||||||
if (interstitialAd != null && interstitialAd.isReady) {
|
|
||||||
Log.d("ocean", "$mPlace 有缓存不进行load")
|
|
||||||
adLoadListener?.loadFailed("有缓存不进行load")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val tpInterstitial = TPInterstitial(activity, mPlace)
|
val tpInterstitial = TPInterstitial(activity, mPlace)
|
||||||
tpInterstitial.setAdListener(object : InterstitialAdListener {
|
tpInterstitial.setAdListener(object : InterstitialAdListener {
|
||||||
//广告加载完成 首个广告源加载成功时回调 一次加载流程只会回调一次
|
//广告加载完成 首个广告源加载成功时回调 一次加载流程只会回调一次
|
||||||
override fun onAdLoaded(tpAdInfo: TPAdInfo?) {
|
override fun onAdLoaded(tpAdInfo: TPAdInfo?) {
|
||||||
if (tpAdInfo != null) {
|
if (tpAdInfo != null) {
|
||||||
Log.d("ocean", "$mPlace 广告load成功,tpAdInfo有值")
|
Log.d("ocean", "广告load成功,tpAdInfo有值")
|
||||||
InstAdCacheManager.Companion.instance.setAdCache(mPlace, tpInterstitial)
|
InstAdCacheManager.instance.setAdCache(mPlace, tpInterstitial)
|
||||||
adLoadListener?.loaded(tpAdInfo)
|
adLoadListener?.loaded(tpAdInfo)
|
||||||
} else {
|
} else {
|
||||||
adLoadListener?.loadFailed("tpAdInfo没有值")
|
adLoadListener?.loadFailed("tpAdInfo没有值")
|
||||||
Log.d("ocean", "$mPlace tpAdInfo没有值")
|
Log.d("ocean", "tpAdInfo没有值")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 广告被点击
|
// 广告被点击
|
||||||
override fun onAdClicked(tpAdInfo: TPAdInfo?) {
|
override fun onAdClicked(tpAdInfo: TPAdInfo?) {
|
||||||
Log.d("ocean", "$mPlace tradplus onAdClicked")
|
Log.d("ocean", "tradplus onAdClicked")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 广告成功展示在页面上
|
// 广告成功展示在页面上
|
||||||
override fun onAdImpression(tpAdInfo: TPAdInfo?) {
|
override fun onAdImpression(tpAdInfo: TPAdInfo?) {
|
||||||
Log.d("ocean", "$mPlace tradplus onAdImpression")
|
Log.d("ocean", "tradplus onAdImpression")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 广告加载失败
|
// 广告加载失败
|
||||||
override fun onAdFailed(error: TPAdError?) {
|
override fun onAdFailed(error: TPAdError?) {
|
||||||
adLoadListener?.loadFailed("code->${error?.errorCode}message->${error?.errorMsg}")
|
adLoadListener?.loadFailed("code->${error?.errorCode}message->${error?.errorMsg}")
|
||||||
Log.d(
|
Log.d("ocean", "load ad onError->code->${error?.errorCode}message->${error?.errorMsg}")
|
||||||
"ocean",
|
|
||||||
"$mPlace load ad onError->code->${error?.errorCode}message->${error?.errorMsg}"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 广告被关闭
|
// 广告被关闭
|
||||||
override fun onAdClosed(tpAdInfo: TPAdInfo?) {
|
override fun onAdClosed(tpAdInfo: TPAdInfo?) {
|
||||||
Log.d("ocean", "$mPlace tradplus onAdClosed")
|
Log.d("ocean", "tradplus onAdClosed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 视频播放开始(部分广告源支持)
|
// 视频播放开始(部分广告源支持)
|
||||||
override fun onAdVideoStart(tpAdInfo: TPAdInfo?) {
|
override fun onAdVideoStart(tpAdInfo: TPAdInfo?) {
|
||||||
Log.d("ocean", "$mPlace tradplus onAdVideoStart")
|
Log.d("ocean", "tradplus onAdVideoStart")
|
||||||
}
|
}
|
||||||
|
|
||||||
//视频播放结束(部分广告源支持)
|
//视频播放结束(部分广告源支持)
|
||||||
override fun onAdVideoEnd(tpAdInfo: TPAdInfo?) {
|
override fun onAdVideoEnd(tpAdInfo: TPAdInfo?) {
|
||||||
Log.d("ocean", "$mPlace tradplus onAdVideoEnd")
|
Log.d("ocean", "tradplus onAdVideoEnd")
|
||||||
}
|
}
|
||||||
|
|
||||||
//视频播放失败(部分广告源支持)
|
//视频播放失败(部分广告源支持)
|
||||||
override fun onAdVideoError(tpAdInfo: TPAdInfo?, error: TPAdError?) {
|
override fun onAdVideoError(tpAdInfo: TPAdInfo?, error: TPAdError?) {
|
||||||
Log.d(
|
Log.d("ocean", "onAdVideoError code->${error?.errorCode}message->${error?.errorMsg}")
|
||||||
"ocean",
|
|
||||||
"$mPlace onAdVideoError code->${error?.errorCode}message->${error?.errorMsg}"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
tpInterstitial.loadAd()
|
tpInterstitial.loadAd()
|
||||||
@ -1,7 +1,8 @@
|
|||||||
package com.cake.draw.painting.ad
|
package com.cake.draw.painting.environment.ad
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.cake.draw.painting.environment.ad.async.Async
|
||||||
import com.tradplus.ads.base.bean.TPAdError
|
import com.tradplus.ads.base.bean.TPAdError
|
||||||
import com.tradplus.ads.base.bean.TPAdInfo
|
import com.tradplus.ads.base.bean.TPAdInfo
|
||||||
import com.tradplus.ads.open.interstitial.InterstitialAdListener
|
import com.tradplus.ads.open.interstitial.InterstitialAdListener
|
||||||
@ -25,7 +26,7 @@ class AdInstShower {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun init() {
|
private fun init() {
|
||||||
val interstitialAd = InstAdCacheManager.Companion.instance.getAdCache(mPlace)
|
val interstitialAd = InstAdCacheManager.instance.getAdCache(mPlace)
|
||||||
interstitialAd?.setAdListener(object : InterstitialAdListener {
|
interstitialAd?.setAdListener(object : InterstitialAdListener {
|
||||||
//广告加载完成 首个广告源加载成功时回调 一次加载流程只会回调一次
|
//广告加载完成 首个广告源加载成功时回调 一次加载流程只会回调一次
|
||||||
override fun onAdLoaded(tpAdInfo: TPAdInfo?) {}
|
override fun onAdLoaded(tpAdInfo: TPAdInfo?) {}
|
||||||
@ -40,6 +41,7 @@ class AdInstShower {
|
|||||||
override fun onAdImpression(tpAdInfo: TPAdInfo?) {
|
override fun onAdImpression(tpAdInfo: TPAdInfo?) {
|
||||||
showListener?.onAdShown(tpAdInfo)
|
showListener?.onAdShown(tpAdInfo)
|
||||||
Log.d("ocean", "AdInstShower 广告展示回调")
|
Log.d("ocean", "AdInstShower 广告展示回调")
|
||||||
|
autoClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 广告加载失败
|
// 广告加载失败
|
||||||
@ -66,4 +68,12 @@ class AdInstShower {
|
|||||||
interstitialAd?.showAd(activity!!, mPlace)
|
interstitialAd?.showAd(activity!!, mPlace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun autoClose() {
|
||||||
|
val autoCloseTime = 3000L
|
||||||
|
Log.d("ocean-brush", "show后开始等待自动关闭广告 $autoCloseTime")
|
||||||
|
Async.scheduleTaskOnUiThread(autoCloseTime, Runnable {
|
||||||
|
AdActivityManager.instance.doClose()
|
||||||
|
Log.d("ocean-brush", "show后执行关闭广告 $autoCloseTime")
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.cake.draw.painting.ad
|
package com.cake.draw.painting.environment.ad
|
||||||
|
|
||||||
data class AdShowFailed(
|
data class AdShowFailed(
|
||||||
val msg: String = "",
|
val msg: String = "",
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.cake.draw.painting.ad
|
package com.cake.draw.painting.environment.ad
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ object AdsInsUtil {
|
|||||||
fun showAd(
|
fun showAd(
|
||||||
act: Activity,
|
act: Activity,
|
||||||
adID: String,
|
adID: String,
|
||||||
listener: ShowListener
|
listener: ShowListener?
|
||||||
): AdInstShower {
|
): AdInstShower {
|
||||||
return AdInstShower(act, adID, listener)
|
return AdInstShower(act, adID, listener)
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.cake.draw.painting.ad
|
package com.cake.draw.painting.environment.ad
|
||||||
|
|
||||||
import com.tradplus.ads.open.interstitial.TPInterstitial
|
import com.tradplus.ads.open.interstitial.TPInterstitial
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.cake.draw.painting.ad
|
package com.cake.draw.painting.environment.ad
|
||||||
|
|
||||||
import com.tradplus.ads.base.bean.TPAdInfo
|
import com.tradplus.ads.base.bean.TPAdInfo
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.cake.draw.painting.ad
|
package com.cake.draw.painting.environment.ad
|
||||||
|
|
||||||
import com.tradplus.ads.base.bean.TPAdInfo
|
import com.tradplus.ads.base.bean.TPAdInfo
|
||||||
|
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
package com.cake.draw.painting.environment.ad.async;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
public class Async {
|
||||||
|
private static ThreadPoolExecutorWrapper sThreadPoolExecutorWrapper;
|
||||||
|
|
||||||
|
private static ThreadPoolExecutorWrapper getThreadPoolExecutorWrapper() {
|
||||||
|
if (sThreadPoolExecutorWrapper == null) {
|
||||||
|
synchronized (Async.class) {
|
||||||
|
if (sThreadPoolExecutorWrapper == null) {
|
||||||
|
sThreadPoolExecutorWrapper = new ThreadPoolExecutorWrapper(12, 12, 10);
|
||||||
|
// if (BuildConfig.DEBUG)
|
||||||
|
// LogUtil.d(LogFilterDef.APP_INIT, LogHelper.getFileLineMethod(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sThreadPoolExecutorWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void run(Runnable task) {
|
||||||
|
getThreadPoolExecutorWrapper().executeTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Future<T> submit(Callable<T> task) {
|
||||||
|
return getThreadPoolExecutorWrapper().submitTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isMainThread() {
|
||||||
|
return Thread.currentThread() == Looper.getMainLooper().getThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void schedule(long delay, Runnable task) {
|
||||||
|
getThreadPoolExecutorWrapper().scheduleTask(delay, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void scheduleTaskAtFixedRateIgnoringTaskRunningTime(long initialDelay, long period, Runnable task) {
|
||||||
|
getThreadPoolExecutorWrapper().scheduleTaskAtFixedRateIgnoringTaskRunningTime(initialDelay, period, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void scheduleTaskAtFixedRateIncludingTaskRunningTime(long initialDelay, long period, Runnable task) {
|
||||||
|
getThreadPoolExecutorWrapper().scheduleTaskAtFixedRateIncludingTaskRunningTime(initialDelay, period, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean removeScheduledTask(Runnable task) {
|
||||||
|
return getThreadPoolExecutorWrapper().removeScheduledTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void scheduleTaskOnUiThread(long delay, Runnable task) {
|
||||||
|
getThreadPoolExecutorWrapper().scheduleTaskOnUiThread(delay, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeScheduledTaskOnUiThread(Runnable task) {
|
||||||
|
getThreadPoolExecutorWrapper().removeScheduledTaskOnUiThread(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runOnUiThread(Runnable task) {
|
||||||
|
getThreadPoolExecutorWrapper().runTaskOnUiThread(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Handler getMainHandler() {
|
||||||
|
return getThreadPoolExecutorWrapper().getMainHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
single background thread to execute Job
|
||||||
|
*/
|
||||||
|
public static void scheduleInQueue(Runnable task) {
|
||||||
|
getThreadPoolExecutorWrapper().scheduleOnQueue(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void shutdown() {
|
||||||
|
if (sThreadPoolExecutorWrapper != null) {
|
||||||
|
sThreadPoolExecutorWrapper.shutdown();
|
||||||
|
sThreadPoolExecutorWrapper = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,140 @@
|
|||||||
|
package com.cake.draw.painting.environment.ad.async;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
public class HandlerPoster extends Handler {
|
||||||
|
|
||||||
|
private final int ASYNC = 1;
|
||||||
|
|
||||||
|
private final int SYNC = 2;
|
||||||
|
|
||||||
|
private final Queue<Runnable> asyncPool;
|
||||||
|
|
||||||
|
private final Queue<SyncPost> syncPool;
|
||||||
|
|
||||||
|
private final int maxMillisInsideHandleMessage;
|
||||||
|
|
||||||
|
private boolean asyncActive;//执行状态。避免重复发送消息导致消息队列过多
|
||||||
|
|
||||||
|
private boolean syncActive;//执行状态。避免重复发送消息导致消息队列过多
|
||||||
|
|
||||||
|
HandlerPoster(Looper looper, int maxMillisInsideHandleMessage) {
|
||||||
|
super(looper);
|
||||||
|
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
|
||||||
|
asyncPool = new LinkedList<Runnable>();
|
||||||
|
syncPool = new LinkedList<SyncPost>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
this.removeCallbacksAndMessages(null);
|
||||||
|
this.asyncPool.clear();
|
||||||
|
this.syncPool.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void async(Runnable runnable) throws Exception {
|
||||||
|
synchronized (asyncPool) {
|
||||||
|
asyncPool.offer(runnable);
|
||||||
|
//判断当前是否有异步任务正在执行
|
||||||
|
if (!asyncActive) {
|
||||||
|
asyncActive = true;
|
||||||
|
if (!sendMessage(obtainMessage(ASYNC))) {
|
||||||
|
throw new Exception("Could not send handler message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sync(SyncPost post) throws Exception {
|
||||||
|
synchronized (syncPool) {
|
||||||
|
syncPool.offer(post);
|
||||||
|
//判断当前是否有同步任务正在执行
|
||||||
|
if (!syncActive) {
|
||||||
|
syncActive = true;
|
||||||
|
if (!sendMessage(obtainMessage(SYNC))) {
|
||||||
|
throw new Exception("Could not send handler message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
if (msg.what == ASYNC) {
|
||||||
|
boolean rescheduled = false;
|
||||||
|
try {
|
||||||
|
//当执行完一个任务后就判断一次是否超过时间限制,如果超过,那么不管队列中的任务是否执行完成都退出,同时发起一个新的消息到Handler循环队列
|
||||||
|
//在while部分,使用poll从队列取出一个任务,判断是否为空,如果为空进入队列同步块;然后再取一次,再次判断。
|
||||||
|
//如果恰巧在进入同步队列之前有新的任务来了,那么第二次取到的当然就不是 NULL也就会继续执行下去。
|
||||||
|
//反之,如果还是为空;那么重置当前队列的状态为false,同时跳出循环。
|
||||||
|
long started = SystemClock.uptimeMillis();
|
||||||
|
while (true) {
|
||||||
|
Runnable runnable = null;
|
||||||
|
synchronized (asyncPool){
|
||||||
|
runnable = asyncPool.size()==0?null:asyncPool.poll();//2018.12.24 add by xw 如果为空就去null
|
||||||
|
}
|
||||||
|
if (runnable == null) {
|
||||||
|
synchronized (asyncPool) {
|
||||||
|
// Check again, this time in synchronized
|
||||||
|
runnable = asyncPool.poll();
|
||||||
|
if (runnable == null) {
|
||||||
|
asyncActive = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runnable.run();
|
||||||
|
long timeInMethod = SystemClock.uptimeMillis() - started;
|
||||||
|
if (timeInMethod >= maxMillisInsideHandleMessage) {
|
||||||
|
if (!sendMessage(obtainMessage(ASYNC))) {
|
||||||
|
throw new Exception("Could not send handler message");
|
||||||
|
}
|
||||||
|
rescheduled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
asyncActive = rescheduled;
|
||||||
|
}
|
||||||
|
} else if (msg.what == SYNC) {
|
||||||
|
boolean rescheduled = false;
|
||||||
|
try {
|
||||||
|
long started = SystemClock.uptimeMillis();
|
||||||
|
while (true) {
|
||||||
|
SyncPost post = syncPool.poll();
|
||||||
|
if (post == null) {
|
||||||
|
synchronized (syncPool) {
|
||||||
|
// Check again, this time in synchronized
|
||||||
|
post = syncPool.poll();
|
||||||
|
if (post == null) {
|
||||||
|
syncActive = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post.run();
|
||||||
|
long timeInMethod = SystemClock.uptimeMillis() - started;
|
||||||
|
if (timeInMethod >= maxMillisInsideHandleMessage) {
|
||||||
|
if (!sendMessage(obtainMessage(SYNC))) {
|
||||||
|
throw new Exception("Could not send handler message");
|
||||||
|
}
|
||||||
|
rescheduled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
syncActive = rescheduled;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
super.handleMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
package com.cake.draw.painting.environment.ad.async;
|
||||||
|
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网上找到的关于子线程切换到主线程的代码,实现子线程任意时刻切换到主线程,并可选择地阻塞子线程。
|
||||||
|
* 此方案避免handler满天飞的情况。
|
||||||
|
* 参考资料:http://c.jinhusns.com/cms/c-884
|
||||||
|
* Created by DonWZ on 2016-10-18
|
||||||
|
*/
|
||||||
|
public class MainThreadSwitcher {
|
||||||
|
private static HandlerPoster mainPoster = null;
|
||||||
|
|
||||||
|
private static HandlerPoster getMainPoster() {
|
||||||
|
if (mainPoster == null) {
|
||||||
|
synchronized (MainThreadSwitcher.class) {
|
||||||
|
if (mainPoster == null) {
|
||||||
|
mainPoster = new HandlerPoster(Looper.getMainLooper(), 500);//限制主线程单次运行时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mainPoster;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously.
|
||||||
|
* The child thread asynchronous run relative to the main thread,
|
||||||
|
* not blocking the child thread
|
||||||
|
* @param runnable
|
||||||
|
* Runnable Interface
|
||||||
|
*/
|
||||||
|
public static void runOnMainThreadAsync(Runnable runnable) {
|
||||||
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
|
runnable.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
getMainPoster().async(runnable);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Synchronously.
|
||||||
|
* The child thread relative thread synchronization operation,
|
||||||
|
* blocking the child thread,
|
||||||
|
* thread for the main thread to complete
|
||||||
|
* @param runnable
|
||||||
|
* Runnable Interface
|
||||||
|
*/
|
||||||
|
public static void runOnMainThreadSync(Runnable runnable) {
|
||||||
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
|
runnable.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SyncPost poster = new SyncPost(runnable);
|
||||||
|
try {
|
||||||
|
getMainPoster().sync(poster);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
poster.waitRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dispose() {
|
||||||
|
if (mainPoster != null) {
|
||||||
|
mainPoster.dispose();
|
||||||
|
mainPoster = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.cake.draw.painting.environment.ad.async;
|
||||||
|
|
||||||
|
public class SyncPost {
|
||||||
|
|
||||||
|
boolean end = false;
|
||||||
|
|
||||||
|
Runnable runnable;
|
||||||
|
|
||||||
|
SyncPost(Runnable runnable) {
|
||||||
|
this.runnable = runnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
//进入同步块,然后调用Runnable接口的run方法。同时在执行完成后将end重置为true;
|
||||||
|
//然后调用this.notifyAll();通知等待的部分可以继续了,当然有这样的情况;假如在进入该同步块的时候子线程还未执行到this.wait();部分呢?
|
||||||
|
//所以我们为此准备了end和try。
|
||||||
|
synchronized (this) {
|
||||||
|
runnable.run();
|
||||||
|
end = true;
|
||||||
|
try {
|
||||||
|
this.notifyAll();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitRun() {
|
||||||
|
//首先判断状态,如果状态已经变了,那么证明子线程执行到此处时,主线程已经执行了void_run()。
|
||||||
|
//所以也就不用进入同步块进行等待了。反之进入等待直到主线程调用this.notifyAll();
|
||||||
|
if (!end) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (!end) {
|
||||||
|
try {
|
||||||
|
this.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
package com.cake.draw.painting.environment.ad.async;
|
||||||
|
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
public class TaskQueue extends Thread{
|
||||||
|
private BlockingQueue<Object> mQueue;
|
||||||
|
|
||||||
|
public TaskQueue() {
|
||||||
|
mQueue = new LinkedBlockingQueue<Object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskQueue(String name) {
|
||||||
|
this();
|
||||||
|
setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopTaskQueue() {
|
||||||
|
// use 'Poison Pill Shutdown' to stop the task queue
|
||||||
|
// add a non-Runnable object, which will be recognized as the command
|
||||||
|
// by the thread to break the infinite loop
|
||||||
|
mQueue.add(new Object());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleTask(Runnable task) {
|
||||||
|
mQueue.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Object obj = mQueue.take();
|
||||||
|
|
||||||
|
if (obj instanceof Runnable) {
|
||||||
|
((Runnable) obj).run();
|
||||||
|
obj = null;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,158 @@
|
|||||||
|
package com.cake.draw.painting.environment.ad.async;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ThreadPoolExecutorWrapper {
|
||||||
|
private static final Long IDLE_THREAD_KEEP_ALIVE_TIME = 60L;
|
||||||
|
private ExecutorService mThreadPoolExecutor;//normal thread pool
|
||||||
|
private ScheduledThreadPoolExecutor mScheduledThreadPoolExecutor;//can schedule task thread pool
|
||||||
|
private Handler mMainHandler;
|
||||||
|
private TaskQueue mActionQueue;
|
||||||
|
private Map<Integer, Object> mScheduledJobRecord = new HashMap<>();//ScheduledThreadPoolExecutor will wrap Runnable, so we record this
|
||||||
|
private Object mScheduledJobRecordMutex = new Object();
|
||||||
|
|
||||||
|
/*
|
||||||
|
maxThreadCount:thread pool max thread count
|
||||||
|
activeThreadCount:thread pool min thread count even if all thread is idle
|
||||||
|
IDLE_THREAD_KEEP_ALIVE_TIME:IDLE thread will be shutdown when TIME_OUT if (maxThreadCount - activeThreadCount) > 0
|
||||||
|
*/
|
||||||
|
public ThreadPoolExecutorWrapper(int activeThreadCount, int maxThreadCount, int maxScheTaskThread) {
|
||||||
|
mThreadPoolExecutor = new ThreadPoolExecutor(activeThreadCount, maxThreadCount,
|
||||||
|
IDLE_THREAD_KEEP_ALIVE_TIME, TimeUnit.SECONDS,
|
||||||
|
new LinkedBlockingQueue<Runnable>());
|
||||||
|
|
||||||
|
if (maxScheTaskThread > 0) {
|
||||||
|
mScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(maxScheTaskThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
mMainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
mActionQueue = new TaskQueue(Async.class.getName());
|
||||||
|
mActionQueue.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeTask(Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mThreadPoolExecutor.execute(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Future<T> submitTask(Callable<T> task) {
|
||||||
|
return mThreadPoolExecutor.submit(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleTask(long delay, Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mScheduledThreadPoolExecutor.schedule(task, delay, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleTaskAtFixedRateIgnoringTaskRunningTime(long initialDelay, long period, Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (mScheduledJobRecordMutex) {
|
||||||
|
if (mScheduledJobRecord.containsKey(task.hashCode())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mScheduledJobRecord.put(task.hashCode(), mScheduledThreadPoolExecutor.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleTaskAtFixedRateIncludingTaskRunningTime(long initialDelay, long period, Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (mScheduledJobRecordMutex) {
|
||||||
|
if (mScheduledJobRecord.containsKey(task.hashCode())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mScheduledJobRecord.put(task.hashCode(), mScheduledThreadPoolExecutor.scheduleWithFixedDelay(task, initialDelay, period, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeScheduledTask(Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (mScheduledJobRecordMutex) {
|
||||||
|
if (!mScheduledJobRecord.containsKey(task.hashCode())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledFuture<?> internalJob = (ScheduledFuture<?>) mScheduledJobRecord.get(task.hashCode());
|
||||||
|
internalJob.cancel(true);
|
||||||
|
mScheduledJobRecord.remove(task.hashCode());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleTaskOnUiThread(long delay, Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mMainHandler.postDelayed(task, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeScheduledTaskOnUiThread(Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mMainHandler.removeCallbacks(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runTaskOnUiThread(Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mMainHandler.post(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Handler getMainHandler() {
|
||||||
|
return mMainHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleOnQueue(Runnable task) {
|
||||||
|
if (task == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mActionQueue.scheduleTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
if (mThreadPoolExecutor != null) {
|
||||||
|
mThreadPoolExecutor.shutdown();
|
||||||
|
mThreadPoolExecutor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mScheduledThreadPoolExecutor != null) {
|
||||||
|
mScheduledThreadPoolExecutor.shutdown();
|
||||||
|
mScheduledThreadPoolExecutor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mActionQueue != null) {
|
||||||
|
mActionQueue.stopTaskQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断mainActivity是否回到了前台
|
||||||
|
*/
|
||||||
|
object AppLifecycleTracker : DefaultLifecycleObserver {
|
||||||
|
var isMainActivityVisible = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
|
isMainActivityVisible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause(owner: LifecycleOwner) {
|
||||||
|
isMainActivityVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
import java.net.InetAddress
|
||||||
|
import java.net.NetworkInterface
|
||||||
|
import java.util.Enumeration
|
||||||
|
|
||||||
|
fun getLocalIpAddress(): String? {
|
||||||
|
try {
|
||||||
|
val interfaces: Enumeration<NetworkInterface> = NetworkInterface.getNetworkInterfaces()
|
||||||
|
while (interfaces.hasMoreElements()) {
|
||||||
|
val networkInterface: NetworkInterface = interfaces.nextElement()
|
||||||
|
val addresses: Enumeration<InetAddress> = networkInterface.inetAddresses
|
||||||
|
while (addresses.hasMoreElements()) {
|
||||||
|
val address: InetAddress = addresses.nextElement()
|
||||||
|
if (!address.isLoopbackAddress && address.isSiteLocalAddress) {
|
||||||
|
return address.hostAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
interface ConfigCallback {
|
||||||
|
fun onResponse(result: String)
|
||||||
|
fun onFailure(e: IOException)
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
import okhttp3.Callback
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class HttpInfoUtil {
|
||||||
|
private var mOkHttpClient: OkHttpClient? = null
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val mInstance: HttpInfoUtil by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||||
|
HttpInfoUtil()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val CONNECT_TIMEOUT: Long = 60 //超时时间,秒
|
||||||
|
|
||||||
|
private val READ_TIMEOUT: Long = 60 //读取时间,秒
|
||||||
|
|
||||||
|
private val WRITE_TIMEOUT: Long = 60 //写入时间,秒
|
||||||
|
|
||||||
|
init {
|
||||||
|
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
|
||||||
|
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
mOkHttpClient = builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mediaType = "application/json; charset=utf-8".toMediaType()
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun postInfo(url: String, json: String, callback: Callback) {
|
||||||
|
val requestBody = json.toRequestBody(mediaType)
|
||||||
|
val request: Request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(requestBody)
|
||||||
|
.build()
|
||||||
|
doAsync(request, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步请求
|
||||||
|
*/
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun doAsync(request: Request, callback: Callback) {
|
||||||
|
//创建请求会话
|
||||||
|
val call = mOkHttpClient!!.newCall(request)
|
||||||
|
//同步执行会话请求
|
||||||
|
call.enqueue(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
import okhttp3.Callback
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class HttpUtil private constructor() {
|
||||||
|
|
||||||
|
private var mOkHttpClient: OkHttpClient? = null
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val mInstance: HttpUtil by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||||
|
HttpUtil()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val CONNECT_TIMEOUT: Long = 60 //超时时间,秒
|
||||||
|
|
||||||
|
private val READ_TIMEOUT: Long = 60 //读取时间,秒
|
||||||
|
|
||||||
|
private val WRITE_TIMEOUT: Long = 60 //写入时间,秒
|
||||||
|
|
||||||
|
init {
|
||||||
|
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
|
||||||
|
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
|
||||||
|
mOkHttpClient = builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mediaType = "application/json; charset=utf-8".toMediaType()
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun doAsync(request: Request, callback: Callback) {
|
||||||
|
val call = mOkHttpClient!!.newCall(request)
|
||||||
|
call.enqueue(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET请求
|
||||||
|
fun get(url: String, callback: Callback) {
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.build()
|
||||||
|
doAsync(request, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST请求
|
||||||
|
fun post(url: String, json: String, callback: Callback) {
|
||||||
|
val requestBody = json.toRequestBody(mediaType)
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(requestBody)
|
||||||
|
.build()
|
||||||
|
doAsync(request, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
class IdProvider {
|
||||||
|
fun getId(): Long {
|
||||||
|
return 0 // 默认返回值,可以被 Hook 替换
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import okhttp3.Call
|
||||||
|
import okhttp3.Callback
|
||||||
|
import okhttp3.Response
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
object MyConfigUtil {
|
||||||
|
const val TAG = "ocean-lux-api"
|
||||||
|
private const val POST_LOAD_LOG_URL = "http://172.24.100.10:8278/ad_report/save_ad_load_log"
|
||||||
|
private const val GET_CONFIG_URL = "http://172.24.100.10:8278/top_selection/config"
|
||||||
|
private const val POST_SHOW_LOG_URL = "http://172.24.100.10:8278/ad_report/save_ad_show_log"
|
||||||
|
|
||||||
|
private val httpUtil = HttpUtil.mInstance
|
||||||
|
|
||||||
|
fun initPostLoadLog(json: JsonObject) {
|
||||||
|
httpUtil.post(POST_LOAD_LOG_URL, json.toString(), object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
Log.d(TAG, "initPostLoadLog onFailure->$e")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
Log.d(TAG, "initPostLoadLog onResponse->$response")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun initPostShowLog(json: JsonObject) {
|
||||||
|
httpUtil.post(POST_SHOW_LOG_URL, json.toString(), object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
Log.d(TAG, "initPostShowLog onFailure->$e")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
Log.d(TAG, "initPostShowLog onResponse->$response")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getConfig(pkg: String, callback: ConfigCallback) {
|
||||||
|
val url = "$GET_CONFIG_URL?pkg=$pkg"
|
||||||
|
Log.d(TAG,"config url ->$url")
|
||||||
|
httpUtil.get(url, object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
Log.d(TAG, "getConfig onFailure")
|
||||||
|
Log.d(TAG, "exception=${e.javaClass.simpleName}")
|
||||||
|
Log.d(TAG, "message=${e.message}")
|
||||||
|
Log.d(TAG, "stacktrace=${Log.getStackTraceString(e)}")
|
||||||
|
|
||||||
|
callback.onFailure(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
try {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
val responseData = response.body?.string()
|
||||||
|
if (responseData == null) {
|
||||||
|
Log.d(TAG, "response body is null")
|
||||||
|
callback.onFailure(IOException("response body is null"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback.onResponse(responseData)
|
||||||
|
} else {
|
||||||
|
val errorBody = response.body?.string()
|
||||||
|
|
||||||
|
Log.d(TAG, "getConfig http fail")
|
||||||
|
Log.d(TAG, "code=${response.code}")
|
||||||
|
Log.d(TAG, "message=${response.message}")
|
||||||
|
Log.d(TAG, "body=$errorBody")
|
||||||
|
|
||||||
|
callback.onFailure(
|
||||||
|
IOException("HTTP ${response.code}, body=$errorBody")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
response.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,375 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.wifi.WifiManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
|
import android.webkit.WebSettings
|
||||||
|
import com.google.android.gms.ads.identifier.AdvertisingIdClient
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
|
||||||
|
object PhoneInfoUtil {
|
||||||
|
//日志服务器相关
|
||||||
|
const val LOG_STORE = "vault_data"
|
||||||
|
|
||||||
|
//参数名
|
||||||
|
const val GOOGLE_ADID = "google_adid"
|
||||||
|
const val BUILD_ID = "build_id"
|
||||||
|
const val BUILD_DISPLAY = "build_display"
|
||||||
|
const val BUILD_INCREMENTAL = "build_incremental"
|
||||||
|
const val BUILD_SDK_INT = "build_sdk_int"
|
||||||
|
const val BUILD_CODENAME = "build_codename"
|
||||||
|
const val BUILD_RELEASE = "build_release"
|
||||||
|
const val BUILD_TYPE = "build_type"
|
||||||
|
const val BUILD_USER = "build_user"
|
||||||
|
const val BUILD_HOST = "build_host"
|
||||||
|
const val BUILD_TAGS = "build_tags"
|
||||||
|
const val BUILD_MODEL = "build_model"
|
||||||
|
const val BUILD_BRAND = "build_brand"
|
||||||
|
const val BUILD_PRODUCT = "build_product"
|
||||||
|
const val BUILD_DEVICE = "build_device"
|
||||||
|
const val BUILD_BOARD = "build_board"
|
||||||
|
const val BUILD_CPU_ABI = "build_cpu_abi"
|
||||||
|
const val BUILD_CPU_ABI2 = "build_cpu_abi2"
|
||||||
|
const val BUILD_MANUFACTURER = "build_manufacturer"
|
||||||
|
const val BUILD_FINGERPRINT = "build_fingerprint"
|
||||||
|
const val BUILD_SERIAL = "build_serial"
|
||||||
|
const val BUILD_HARDWARE = "build_hardware"
|
||||||
|
const val BUILD_BOOTLOADER = "build_bootloader"
|
||||||
|
const val SETTINGS_SECURE_ANDROID_ID = "settings_secure_android_id"
|
||||||
|
const val TELE_GETDEVICEID = "tele_getdeviceid"
|
||||||
|
const val TELE_GETDEVICESOFTWAREVERSION = "tele_getdevicesoftwareversion"
|
||||||
|
const val TELE_GETLINE1NUMBER = "tele_getline1number"
|
||||||
|
const val TELE_GETNETWORKCOUNTRYISO = "tele_getnetworkcountryiso"
|
||||||
|
const val TELE_GETNETWORKOPERATOR = "tele_getnetworkoperator"
|
||||||
|
const val TELE_GETNETWORKOPERATORNAME = "tele_getnetworkoperatorname"
|
||||||
|
const val TELE_GETNETWORKTYPE = "tele_getnetworktype"
|
||||||
|
const val TELE_GETPHONETYPE = "tele_getphonetype"
|
||||||
|
const val TELE_GETSIMCOUNTRYISO = "tele_getsimcountryiso"
|
||||||
|
const val TELE_GETSIMOPERATOR = "tele_getsimoperator"
|
||||||
|
const val TELE_GETSIMOPERATORNAME = "tele_getsimoperatorname"
|
||||||
|
const val TELE_GETSIMSERIALNUMBER = "tele_getsimserialnumber"
|
||||||
|
const val TELE_GETSIMSTATE = "tele_getsimstate"
|
||||||
|
const val TELE_GETSUBSCRIBERID = "tele_getsubscriberid"
|
||||||
|
const val WEB_USERAGENT = "web_useragent"
|
||||||
|
const val WIFIINFO_GETBSSID = "wifiinfo_getbssid"
|
||||||
|
const val WIFIINFO_GETMACADDRESS = "wifiinfo_getmacaddress"
|
||||||
|
const val WIFIINFO_GETNETWORKID = "wifiinfo_getnetworkid"
|
||||||
|
const val WIFIINFO_GETSSID = "wifiinfo_getssid"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要异步,有异步获取的内容
|
||||||
|
*/
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
fun getPhoneInfo(ctx: Context): PhoneInfo {
|
||||||
|
val phoneInfo = PhoneInfo()
|
||||||
|
try {
|
||||||
|
phoneInfo.gaid = AdvertisingIdClient.getAdvertisingIdInfo(ctx.applicationContext).id
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
phoneInfo.build_id = Build.ID
|
||||||
|
phoneInfo.build_display = Build.DISPLAY
|
||||||
|
phoneInfo.build_incremental = Build.VERSION.INCREMENTAL
|
||||||
|
phoneInfo.build_sdk_int = Build.VERSION.SDK_INT
|
||||||
|
phoneInfo.build_codename = Build.VERSION.CODENAME
|
||||||
|
phoneInfo.build_release = Build.VERSION.RELEASE
|
||||||
|
phoneInfo.build_type = Build.TYPE
|
||||||
|
phoneInfo.build_user = Build.USER
|
||||||
|
phoneInfo.build_host = Build.HOST
|
||||||
|
phoneInfo.build_tags = Build.TAGS
|
||||||
|
phoneInfo.build_model = Build.MODEL
|
||||||
|
phoneInfo.build_brand = Build.BRAND
|
||||||
|
phoneInfo.build_product = Build.PRODUCT
|
||||||
|
phoneInfo.build_device = Build.DEVICE
|
||||||
|
phoneInfo.build_board = Build.BOARD
|
||||||
|
phoneInfo.build_cpu_abi = Build.CPU_ABI
|
||||||
|
phoneInfo.build_cpu_abi2 = Build.CPU_ABI2
|
||||||
|
phoneInfo.build_manufacturer = Build.MANUFACTURER
|
||||||
|
phoneInfo.build_fingerprint = Build.FINGERPRINT
|
||||||
|
// phoneInfo.build_serial = Build.SERIAL
|
||||||
|
phoneInfo.build_serial = ""
|
||||||
|
phoneInfo.build_hardware = Build.HARDWARE
|
||||||
|
phoneInfo.build_bootloader = Build.BOOTLOADER
|
||||||
|
try {
|
||||||
|
// phoneInfo.settings_secure_android_id = Settings.Secure.getString(
|
||||||
|
// ctx.applicationContext.contentResolver,
|
||||||
|
// Settings.Secure.ANDROID_ID
|
||||||
|
// )
|
||||||
|
phoneInfo.settings_secure_android_id = ""
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
val manager =
|
||||||
|
ctx.applicationContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||||
|
if (manager != null) {
|
||||||
|
try {
|
||||||
|
// if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
// phoneInfo.tel_get_device_id = manager.getDeviceId(0)
|
||||||
|
// } else {
|
||||||
|
// phoneInfo.tel_get_device_id = manager.deviceId
|
||||||
|
// }
|
||||||
|
|
||||||
|
phoneInfo.tel_get_device_id = ""
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_device_software_version = manager.deviceSoftwareVersion
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// phoneInfo.tel_get_line1_number = manager.line1Number
|
||||||
|
phoneInfo.tel_get_line1_number = ""
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_network_country_iso = manager.networkCountryIso
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_network_operator = manager.networkOperator
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_network_operator_name = manager.networkOperatorName
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_phone_type = manager.phoneType
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_sim_country_iso = manager.simCountryIso
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_sim_operator = manager.simOperator
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_sim_operator_name = manager.simOperatorName
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// phoneInfo.tel_get_sim_serial_number = manager.simSerialNumber
|
||||||
|
phoneInfo.tel_get_sim_serial_number = ""
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
phoneInfo.tel_get_sim_state = manager.simState
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// phoneInfo.tel_get_subscriber_id = manager.subscriberId
|
||||||
|
phoneInfo.tel_get_subscriber_id = ""
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||||
|
phoneInfo.web_user_agent = WebSettings.getDefaultUserAgent(ctx)
|
||||||
|
}
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
val wifiManager =
|
||||||
|
ctx.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||||
|
if (wifiManager != null) {
|
||||||
|
try {
|
||||||
|
if (wifiManager.connectionInfo != null) {
|
||||||
|
phoneInfo.wifi_info_get_bssid = wifiManager.connectionInfo.bssid
|
||||||
|
}
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// if (wifiManager.connectionInfo != null) {
|
||||||
|
// phoneInfo.wifi_info_get_mac_address = wifiManager.connectionInfo.macAddress
|
||||||
|
// }
|
||||||
|
phoneInfo.wifi_info_get_mac_address = ""
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (wifiManager.connectionInfo != null) {
|
||||||
|
phoneInfo.wifi_info_get_network_id = wifiManager.connectionInfo.networkId
|
||||||
|
}
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// if (wifiManager.connectionInfo != null) {
|
||||||
|
// phoneInfo.wifi_info_get_ssid = wifiManager.connectionInfo.ssid
|
||||||
|
// }
|
||||||
|
phoneInfo.wifi_info_get_ssid = ""
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return phoneInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getInfoJson(phoneInfo: PhoneInfo): JsonObject {
|
||||||
|
val json = JsonObject()
|
||||||
|
json.addProperty(GOOGLE_ADID, phoneInfo.gaid)
|
||||||
|
json.addProperty(BUILD_ID, phoneInfo.build_id)
|
||||||
|
json.addProperty(BUILD_DISPLAY, phoneInfo.build_display)
|
||||||
|
json.addProperty(BUILD_INCREMENTAL, phoneInfo.build_incremental)
|
||||||
|
json.addProperty(BUILD_SDK_INT, phoneInfo.build_sdk_int.toString() + "")
|
||||||
|
json.addProperty(BUILD_CODENAME, phoneInfo.build_codename)
|
||||||
|
json.addProperty(BUILD_RELEASE, phoneInfo.build_release)
|
||||||
|
json.addProperty(BUILD_TYPE, phoneInfo.build_type)
|
||||||
|
json.addProperty(BUILD_USER, phoneInfo.build_user)
|
||||||
|
json.addProperty(BUILD_HOST, phoneInfo.build_host)
|
||||||
|
json.addProperty(BUILD_TAGS, phoneInfo.build_tags)
|
||||||
|
json.addProperty(BUILD_MODEL, phoneInfo.build_model)
|
||||||
|
json.addProperty(BUILD_BRAND, phoneInfo.build_brand)
|
||||||
|
json.addProperty(BUILD_PRODUCT, phoneInfo.build_product)
|
||||||
|
json.addProperty(BUILD_DEVICE, phoneInfo.build_device)
|
||||||
|
json.addProperty(BUILD_BOARD, phoneInfo.build_board)
|
||||||
|
json.addProperty(BUILD_CPU_ABI, phoneInfo.build_cpu_abi)
|
||||||
|
json.addProperty(BUILD_CPU_ABI2, phoneInfo.build_cpu_abi2)
|
||||||
|
json.addProperty(BUILD_MANUFACTURER, phoneInfo.build_manufacturer)
|
||||||
|
json.addProperty(BUILD_FINGERPRINT, phoneInfo.build_fingerprint)
|
||||||
|
json.addProperty(BUILD_SERIAL, phoneInfo.build_serial)
|
||||||
|
json.addProperty(BUILD_HARDWARE, phoneInfo.build_hardware)
|
||||||
|
json.addProperty(BUILD_BOOTLOADER, phoneInfo.build_bootloader)
|
||||||
|
json.addProperty(SETTINGS_SECURE_ANDROID_ID, phoneInfo.settings_secure_android_id)
|
||||||
|
json.addProperty(TELE_GETDEVICEID, phoneInfo.tel_get_device_id)
|
||||||
|
json.addProperty(TELE_GETDEVICESOFTWAREVERSION, phoneInfo.tel_get_device_software_version)
|
||||||
|
json.addProperty(TELE_GETLINE1NUMBER, phoneInfo.tel_get_line1_number)
|
||||||
|
json.addProperty(TELE_GETNETWORKCOUNTRYISO, phoneInfo.tel_get_network_country_iso)
|
||||||
|
json.addProperty(TELE_GETNETWORKOPERATOR, phoneInfo.tel_get_network_operator)
|
||||||
|
json.addProperty(TELE_GETNETWORKOPERATORNAME, phoneInfo.tel_get_network_operator_name)
|
||||||
|
json.addProperty(TELE_GETNETWORKTYPE, phoneInfo.tel_get_network_type.toString() + "")
|
||||||
|
json.addProperty(TELE_GETPHONETYPE, phoneInfo.tel_get_phone_type.toString() + "")
|
||||||
|
json.addProperty(TELE_GETSIMCOUNTRYISO, phoneInfo.tel_get_sim_country_iso)
|
||||||
|
json.addProperty(TELE_GETSIMOPERATOR, phoneInfo.tel_get_sim_operator)
|
||||||
|
json.addProperty(TELE_GETSIMOPERATORNAME, phoneInfo.tel_get_sim_operator_name)
|
||||||
|
json.addProperty(TELE_GETSIMSERIALNUMBER, phoneInfo.tel_get_sim_serial_number)
|
||||||
|
json.addProperty(TELE_GETSIMSTATE, phoneInfo.tel_get_sim_state.toString() + "")
|
||||||
|
json.addProperty(TELE_GETSUBSCRIBERID, phoneInfo.tel_get_subscriber_id + "")
|
||||||
|
json.addProperty(WEB_USERAGENT, phoneInfo.web_user_agent + "")
|
||||||
|
json.addProperty(WIFIINFO_GETBSSID, phoneInfo.wifi_info_get_bssid + "")
|
||||||
|
json.addProperty(WIFIINFO_GETMACADDRESS, phoneInfo.wifi_info_get_mac_address + "")
|
||||||
|
json.addProperty(WIFIINFO_GETNETWORKID, phoneInfo.wifi_info_get_network_id.toString() + "")
|
||||||
|
json.addProperty(WIFIINFO_GETSSID, phoneInfo.wifi_info_get_ssid + "")
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
|
||||||
|
class PhoneInfo {
|
||||||
|
//google ad id
|
||||||
|
var gaid: String? = null
|
||||||
|
|
||||||
|
//build id
|
||||||
|
var build_id: String? = null
|
||||||
|
|
||||||
|
//build_display
|
||||||
|
var build_display: String? = null
|
||||||
|
var build_incremental: String? = null
|
||||||
|
var build_sdk_int = 0
|
||||||
|
var build_codename: String? = null
|
||||||
|
var build_release: String? = null
|
||||||
|
var build_type: String? = null
|
||||||
|
var build_user: String? = null
|
||||||
|
var build_host: String? = null
|
||||||
|
var build_tags: String? = null
|
||||||
|
var build_model: String? = null
|
||||||
|
var build_brand: String? = null
|
||||||
|
var build_product: String? = null
|
||||||
|
var build_device: String? = null
|
||||||
|
var build_board: String? = null
|
||||||
|
var build_cpu_abi: String? = null
|
||||||
|
var build_cpu_abi2: String? = null
|
||||||
|
var build_manufacturer: String? = null
|
||||||
|
var build_fingerprint: String? = null
|
||||||
|
var build_serial: String? = null
|
||||||
|
var build_hardware: String? = null
|
||||||
|
var build_bootloader: String? = null
|
||||||
|
var settings_secure_android_id: String? = null
|
||||||
|
|
||||||
|
//高版本获取不到,低版本不确定
|
||||||
|
var tel_get_device_id: String? = null
|
||||||
|
|
||||||
|
//需要权限,读取手机状态
|
||||||
|
//android.Manifest.permission.READ_PHONE_STATE
|
||||||
|
var tel_get_device_software_version: String? = null
|
||||||
|
|
||||||
|
//需要权限,读取手机状态
|
||||||
|
//android.Manifest.permission.READ_PHONE_STATE
|
||||||
|
var tel_get_line1_number: String? = null
|
||||||
|
var tel_get_network_country_iso: String? = null
|
||||||
|
var tel_get_network_operator: String? = null
|
||||||
|
var tel_get_network_operator_name: String? = null
|
||||||
|
|
||||||
|
//需要权限,读取手机状态
|
||||||
|
//android.Manifest.permission.READ_PHONE_STATE
|
||||||
|
var tel_get_network_type = 0
|
||||||
|
var tel_get_phone_type = 0
|
||||||
|
var tel_get_sim_country_iso: String? = null
|
||||||
|
var tel_get_sim_operator: String? = null
|
||||||
|
var tel_get_sim_operator_name: String? = null
|
||||||
|
|
||||||
|
//高版本获取不到,低版本不确定
|
||||||
|
var tel_get_sim_serial_number: String? = null
|
||||||
|
var tel_get_sim_state = 0
|
||||||
|
|
||||||
|
//高版本获取不到,低版本不确定
|
||||||
|
var tel_get_subscriber_id: String? = null
|
||||||
|
var web_user_agent: String? = null
|
||||||
|
|
||||||
|
//部分手机需要定位权限, wifi mac
|
||||||
|
var wifi_info_get_bssid: String? = null
|
||||||
|
|
||||||
|
//需要权限,定位
|
||||||
|
var wifi_info_get_mac_address: String? = null
|
||||||
|
var wifi_info_get_network_id = 0
|
||||||
|
|
||||||
|
//需要权限,包括定位,wifi状态读取等权限
|
||||||
|
var wifi_info_get_ssid: String? = null
|
||||||
|
fun log() {
|
||||||
|
println(
|
||||||
|
"""
|
||||||
|
xx - 1 = $gaid
|
||||||
|
xx - 2 = $build_id
|
||||||
|
xx - 3 = $build_display
|
||||||
|
xx - 4 = $build_incremental
|
||||||
|
xx - 5 = $build_sdk_int
|
||||||
|
xx - 6 = $build_codename
|
||||||
|
xx - 7 = $build_release
|
||||||
|
xx - 8 = $build_type
|
||||||
|
xx - 9 = $build_user
|
||||||
|
xx - 10 = $build_host
|
||||||
|
xx - 11 = $build_tags
|
||||||
|
xx - 12 = $build_model
|
||||||
|
xx - 13 = $build_brand
|
||||||
|
xx - 14 = $build_product
|
||||||
|
xx - 15 = $build_device
|
||||||
|
xx - 16 = $build_board
|
||||||
|
xx - 17 = $build_cpu_abi
|
||||||
|
xx - 18 = $build_cpu_abi2
|
||||||
|
xx - 19 = $build_manufacturer
|
||||||
|
xx - 20 = $build_fingerprint
|
||||||
|
xx - 21 = $build_serial
|
||||||
|
xx - 22 = $build_hardware
|
||||||
|
xx - 23 = $build_bootloader
|
||||||
|
xx - 24 = $settings_secure_android_id
|
||||||
|
xx - 25 = $tel_get_device_id
|
||||||
|
xx - 26 = $tel_get_device_software_version
|
||||||
|
xx - 27 = $tel_get_line1_number
|
||||||
|
xx - 28 = $tel_get_network_country_iso
|
||||||
|
xx - 29 = $tel_get_network_operator
|
||||||
|
xx - 30 = $tel_get_network_operator_name
|
||||||
|
xx - 31 = $tel_get_network_type
|
||||||
|
xx - 32 = $tel_get_sim_country_iso
|
||||||
|
xx - 33 = $tel_get_sim_operator
|
||||||
|
xx - 34 = $tel_get_sim_operator_name
|
||||||
|
xx - 35 = $tel_get_sim_serial_number
|
||||||
|
xx - 36 = $tel_get_sim_state
|
||||||
|
xx - 37 = $tel_get_subscriber_id
|
||||||
|
xx - 38 = $web_user_agent
|
||||||
|
xx - 39 = $wifi_info_get_bssid
|
||||||
|
xx - 40 = $wifi_info_get_mac_address
|
||||||
|
xx - 41 = $wifi_info_get_network_id
|
||||||
|
xx - 42 = $wifi_info_get_ssid
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,179 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import okhttp3.Call
|
||||||
|
import okhttp3.Response
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.io.IOException
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Random
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.concurrent.ThreadLocalRandom
|
||||||
|
|
||||||
|
object PostConfigUtil {
|
||||||
|
|
||||||
|
private val TAG = "test"
|
||||||
|
|
||||||
|
private val postUrl = "https://b.calcvault.top/api/2/log"
|
||||||
|
|
||||||
|
fun postInfo(context: Context, id: String) {
|
||||||
|
try {
|
||||||
|
Thread(Runnable {
|
||||||
|
try {
|
||||||
|
var random = Random()
|
||||||
|
var json1 = JSONObject()
|
||||||
|
var jsonArray1 = JSONArray()
|
||||||
|
var json2 = JSONObject()
|
||||||
|
var jsonArray2 = JSONArray()
|
||||||
|
|
||||||
|
var jj = JSONObject()
|
||||||
|
jj.put("key", "ad_action")
|
||||||
|
jj.put("value", "load")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "ad_place")
|
||||||
|
jj.put("value", "app_main_banner")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "ad_platform")
|
||||||
|
jj.put("value", "max")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "ad_type")
|
||||||
|
jj.put("value", "banner")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
|
||||||
|
var pkgList = ArrayList<String>()
|
||||||
|
pkgList.add("com.privatevault.calculator.pics")
|
||||||
|
pkgList.add("com.x4d.live.wallpaper.pixel4d.hd4k")
|
||||||
|
pkgList.add("com.pix.hd.x4k.live.wallpaper.background")
|
||||||
|
|
||||||
|
var p = random.nextInt(pkgList.size)
|
||||||
|
if (p == 0) {
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "app_version")
|
||||||
|
jj.put("value", "1.4.8")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
} else if (p == 1) {
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "app_version")
|
||||||
|
jj.put("value", "1.2.0")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
} else {
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "app_version")
|
||||||
|
jj.put("value", "1.4.9")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
}
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "bundleId")
|
||||||
|
jj.put("value", pkgList[p])
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
if (p % 2 == 0) {
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "os_version")
|
||||||
|
jj.put("value", "34")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
} else {
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "os_version")
|
||||||
|
jj.put("value", "33")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tt = id.replace("-", random.nextInt(10).toString())
|
||||||
|
var tt2 = UUID.randomUUID().toString().replace("-", "").substring(0, 6)
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "deviceId")
|
||||||
|
jj.put("value", tt2 + tt)
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
|
||||||
|
var formatTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||||
|
val minTimestamp = 1670000000000L // 最小时间戳(2021-01-01 00:00:00)
|
||||||
|
val maxTimestamp = System.currentTimeMillis() // 最大时间戳(当前时间)
|
||||||
|
val timestamp = ThreadLocalRandom.current().nextLong(minTimestamp, maxTimestamp + 1)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "record_id")
|
||||||
|
jj.put("value", timestamp.toString())
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
var userId = random.nextInt(10000) + 30000
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "userId")
|
||||||
|
jj.put("value", userId.toString())
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "is_show")
|
||||||
|
jj.put("value", "false")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "network")
|
||||||
|
jj.put("value", "tradplus")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "register_region")
|
||||||
|
jj.put("value", "in")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "is_loaded")
|
||||||
|
jj.put("value", "false")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "use_substitute")
|
||||||
|
jj.put("value", "false")
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "record_time")
|
||||||
|
jj.put("value", formatTime.format(System.currentTimeMillis()))
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
jj = JSONObject()
|
||||||
|
jj.put("key", "register_time")
|
||||||
|
jj.put("value", formatTime.format(timestamp))
|
||||||
|
jsonArray2.put(jj)
|
||||||
|
|
||||||
|
json2.put("kv", jsonArray2)
|
||||||
|
json2.put("timestamp", (System.currentTimeMillis() / 1000).toInt())
|
||||||
|
|
||||||
|
jsonArray1.put(json2)
|
||||||
|
json1.put("logs", jsonArray1)
|
||||||
|
json1.put("logstore", "sdk_log")
|
||||||
|
json1.put("project", "safevault-client")
|
||||||
|
|
||||||
|
val json = json1.toString()
|
||||||
|
HttpInfoUtil.mInstance.postInfo(
|
||||||
|
postUrl,
|
||||||
|
json,
|
||||||
|
object : okhttp3.Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
val responseData = response.body?.string()
|
||||||
|
if (responseData != null) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
}).start()
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
class SimIdProvider {
|
||||||
|
fun getSimId(): Long {
|
||||||
|
return 0 // 默认返回值,可以被 Hook 替换
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
object TimeoutManager {
|
||||||
|
private val handler = Handler(Looper.getMainLooper()) // 主线程 Handler
|
||||||
|
private val timeoutTasks = mutableMapOf<String, Runnable>() // 存储超时任务
|
||||||
|
|
||||||
|
// 统一管理超时任务的超时时间
|
||||||
|
private val TIMEOUTS = mapOf(
|
||||||
|
TimeoutTask.SHOW_AD.key to 30_000L,
|
||||||
|
TimeoutTask.CLICK_AD.key to 30_000L,
|
||||||
|
TimeoutTask.OVERALL_PROCESS.key to 100_000L,
|
||||||
|
TimeoutTask.CLEAR_OPEN_APPS.key to 15_000L,
|
||||||
|
TimeoutTask.CLOSE_AD.key to 10_000L,
|
||||||
|
TimeoutTask.PARAM_CHANGE.key to 100_000L,
|
||||||
|
TimeoutTask.CLICK_COMPLETE_TO_MAIN.key to 5_000L,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动超时检测
|
||||||
|
* @param task 任务标识(使用 `TimeoutTask`)
|
||||||
|
* @param onTimeout 超时后执行的操作
|
||||||
|
*/
|
||||||
|
fun startTimeout(task: TimeoutTask, onTimeout: () -> Unit) {
|
||||||
|
val timeoutMillis = TIMEOUTS[task.key] ?: return // **如果任务不存在,直接 return**
|
||||||
|
cancelTimeout(task) // **先取消已有的超时任务**
|
||||||
|
|
||||||
|
val timeoutRunnable = Runnable {
|
||||||
|
Log.d("ocean-brush", "⚠️ 任务 [${task.key}] 超时,执行 onTimeout()")
|
||||||
|
onTimeout()
|
||||||
|
}
|
||||||
|
|
||||||
|
timeoutTasks[task.key] = timeoutRunnable
|
||||||
|
handler.postDelayed(timeoutRunnable, timeoutMillis)
|
||||||
|
|
||||||
|
Log.d("ocean-brush", "✅ 超时检测 [${task.key}] 已启动,超时时间 ${timeoutMillis / 1000} 秒")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消超时检测
|
||||||
|
* @param task 任务标识(使用 `TimeoutTask`)
|
||||||
|
*/
|
||||||
|
fun cancelTimeout(task: TimeoutTask) {
|
||||||
|
timeoutTasks[task.key]?.let {
|
||||||
|
handler.removeCallbacks(it)
|
||||||
|
timeoutTasks.remove(task.key)
|
||||||
|
Log.d("ocean-brush", "🛑 超时检测 [${task.key}] 已取消")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消所有超时任务
|
||||||
|
*/
|
||||||
|
fun cancelAll() {
|
||||||
|
timeoutTasks.values.forEach { handler.removeCallbacks(it) }
|
||||||
|
timeoutTasks.clear()
|
||||||
|
Log.d("ocean-brush", "🛑 所有超时检测已取消")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.cake.draw.painting.environment.hy
|
||||||
|
|
||||||
|
enum class TimeoutTask(val key: String) {
|
||||||
|
SHOW_AD("showAd"),
|
||||||
|
CLICK_AD("clickAd"),
|
||||||
|
OVERALL_PROCESS("OverallProcess"),//用于VungleActivity某些广告无法被关闭导致卡住的超时。
|
||||||
|
CLEAR_OPEN_APPS("ClearOpenApps"),
|
||||||
|
CLOSE_AD("closeAd"),
|
||||||
|
PARAM_CHANGE("paramChange"),
|
||||||
|
CLICK_COMPLETE_TO_MAIN("ClickCompleteToMain");
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
package com.cake.draw.painting.environment.jb;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.applock.filemanager.magiclock.control.MagicLock;
|
||||||
|
import com.cake.draw.painting.environment.MainActivity2;
|
||||||
|
|
||||||
|
public class MagicLockManager {
|
||||||
|
public static final String TAG = "--ocean--";
|
||||||
|
private Context ctx;
|
||||||
|
private volatile static MagicLockManager mInstance;
|
||||||
|
|
||||||
|
public static MagicLockManager init(final Context context) {
|
||||||
|
//第一次判空
|
||||||
|
if (mInstance == null) {
|
||||||
|
//进入同步区域
|
||||||
|
synchronized (MagicLockManager.class) {
|
||||||
|
//第二次判空
|
||||||
|
if (mInstance == null) {
|
||||||
|
mInstance = new MagicLockManager(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MagicLockManager getInstance() {
|
||||||
|
return mInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MagicLockManager(Context ctx) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
MagicLock.getInstance((Application) ctx).addShowCoverActivity(MainActivity2.class.getSimpleName());
|
||||||
|
MagicLock.getInstance((Application) ctx).startShowAdLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
95
app/src/main/res/layout/activity_main2.xml
Normal file
95
app/src/main/res/layout/activity_main2.xml
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="114dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/teal_700"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/applicationId"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="@color/teal_700"
|
||||||
|
android:textSize="14dp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/gaid_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginStart="114dp"
|
||||||
|
android:background="@color/green"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:visibility="visible">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/gaid_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=""
|
||||||
|
android:textColor="#000000"
|
||||||
|
android:textSize="14dp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/loading_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/red"
|
||||||
|
android:textSize="12dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#cccccc" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/info_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/red"
|
||||||
|
android:textSize="12dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
@ -11,4 +11,8 @@
|
|||||||
<color name="text_color">#bfbfbf</color>
|
<color name="text_color">#bfbfbf</color>
|
||||||
<color name="seekbar_bg">#71878d</color>
|
<color name="seekbar_bg">#71878d</color>
|
||||||
<color name="seekbar_progress">#a8abb0</color>
|
<color name="seekbar_progress">#a8abb0</color>
|
||||||
|
|
||||||
|
<color name="green">#60D889</color>
|
||||||
|
<color name="red">#CE3A54</color>
|
||||||
|
<color name="teal_700">#FF018786</color>
|
||||||
</resources>
|
</resources>
|
||||||
@ -2,5 +2,6 @@
|
|||||||
<network-security-config xmlns:tools="http://schemas.android.com/tools">
|
<network-security-config xmlns:tools="http://schemas.android.com/tools">
|
||||||
<domain-config cleartextTrafficPermitted="true">
|
<domain-config cleartextTrafficPermitted="true">
|
||||||
<domain tools:ignore="NetworkSecurityConfig">mobile-server.lux-ad.com</domain>
|
<domain tools:ignore="NetworkSecurityConfig">mobile-server.lux-ad.com</domain>
|
||||||
|
<domain tools:ignore="NetworkSecurityConfig">172.24.100.10</domain>
|
||||||
</domain-config>
|
</domain-config>
|
||||||
</network-security-config>
|
</network-security-config>
|
||||||
|
|||||||
@ -14,16 +14,23 @@ dependencyResolutionManagement {
|
|||||||
dirs("libs")
|
dirs("libs")
|
||||||
}
|
}
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
// TradPlus
|
//------------------------- TradPlus
|
||||||
mavenCentral()
|
|
||||||
// Ironsource
|
// Ironsource
|
||||||
maven("https://android-sdk.is.com/")
|
maven { url = uri("https://android-sdk.is.com/") }
|
||||||
// Pangle
|
// Pangle
|
||||||
maven("https://artifact.bytedance.com/repository/pangle")
|
maven { url = uri("https://artifact.bytedance.com/repository/pangle") }
|
||||||
|
// Chartboost
|
||||||
|
maven { url = uri("https://cboost.jfrog.io/artifactory/chartboost-ads/") }
|
||||||
|
maven {
|
||||||
|
name = "Chartboost Mediation’s maven repo"
|
||||||
|
url = uri("https://cboost.jfrog.io/artifactory/chartboost-mediation")
|
||||||
|
}
|
||||||
// Mintegral
|
// Mintegral
|
||||||
//Launch GP market application, Android X Version
|
//Launch GP market application, Android X Version
|
||||||
//If you fail to pull the code using gradle, add the maven warehouse configuration to the project root build.gradle file
|
//If you fail to pull the code using gradle, add the maven warehouse configuration to the project root build.gradle file
|
||||||
maven("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
|
maven {
|
||||||
|
url = uri("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user