suiyize 4 years ago
parent c396950562
commit 08ed6854cc

@ -0,0 +1,14 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx

@ -0,0 +1,164 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<DBN-PSQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false" />
</DBN-PSQL>
<DBN-SQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false">
<option name="STATEMENT_SPACING" value="one_line" />
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
</formatting-settings>
</DBN-SQL>
<DBN-PSQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false" />
</DBN-PSQL>
<DBN-SQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false">
<option name="STATEMENT_SPACING" value="one_line" />
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
</formatting-settings>
</DBN-SQL>
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
</component>
</project>

@ -0,0 +1,458 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DBNavigator.Project.DataEditorManager">
<record-view-column-sorting-type value="BY_INDEX" />
<value-preview-text-wrapping value="false" />
<value-preview-pinned value="false" />
</component>
<component name="DBNavigator.Project.DataExportManager">
<export-instructions>
<create-header value="true" />
<friendly-headers value="false" />
<quote-values-containing-separator value="true" />
<quote-all-values value="false" />
<value-separator value="" />
<file-name value="" />
<file-location value="" />
<scope value="GLOBAL" />
<destination value="FILE" />
<format value="EXCEL" />
<charset value="GBK" />
</export-instructions>
</component>
<component name="DBNavigator.Project.DatabaseBrowserManager">
<autoscroll-to-editor value="false" />
<autoscroll-from-editor value="true" />
<show-object-properties value="true" />
<loaded-nodes />
</component>
<component name="DBNavigator.Project.DatabaseFileManager">
<open-files />
</component>
<component name="DBNavigator.Project.EditorStateManager">
<last-used-providers />
</component>
<component name="DBNavigator.Project.ExecutionManager">
<retain-sticky-names value="false" />
</component>
<component name="DBNavigator.Project.MethodExecutionManager">
<method-browser />
<execution-history>
<group-entries value="true" />
<execution-inputs />
</execution-history>
<argument-values-cache />
</component>
<component name="DBNavigator.Project.ObjectDependencyManager">
<last-used-dependency-type value="INCOMING" />
</component>
<component name="DBNavigator.Project.ObjectQuickFilterManager">
<last-used-operator value="EQUAL" />
<filters />
</component>
<component name="DBNavigator.Project.ScriptExecutionManager" clear-outputs="true">
<recently-used-interfaces />
</component>
<component name="DBNavigator.Project.Settings">
<connections />
<browser-settings>
<general>
<display-mode value="TABBED" />
<navigation-history-size value="100" />
<show-object-details 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="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="DIMENSION" enabled="true" />
<object-type name="CLUSTER" enabled="true" />
<object-type name="DBLINK" 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" />
</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="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="DIMENSION" enabled="false" />
<object-type name="CLUSTER" enabled="false" />
<object-type name="DBLINK" enabled="true" />
</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>
<tracking-columns>
<columnNames value="" />
<visible value="true" />
<editable value="false" />
</tracking-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" />
</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="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="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="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="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="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="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="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>
<debugger>
<debugger-type value="ASK" />
<use-generic-runners value="true" />
</debugger>
</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" />
</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>
<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>
<component name="DBNavigator.Project.StatementExecutionManager">
<execution-variables />
</component>
</project>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="disableWrapperSourceDistributionNotification" value="true" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="1.8" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://raw.github.com/bmob/bmob-android-sdk/master" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://dl.bintray.com/chaozhouzhang/maven" />
</remote-repository>
</component>
</project>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

@ -0,0 +1 @@
/build

@ -0,0 +1,56 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
useLibrary 'org.apache.http.legacy'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.example.luyin"
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation files('src/main/jniLibs/Msc.jar')
compileOnly files('src/main/jniLibs/Android_Map3D_SDK_V7.8.0_20201231.jar')
compileOnly files('src/main/jniLibs/AMap_Location_V5.2.0_20200915.jar')
implementation files('src/main/jniLibs/AMap_Search_V7.7.0_20201027.jar')
compileOnly files('src/main/jniLibs/android-support-v4.jar')
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'cn.bmob.android:bmob-sdk:3.7.8'
implementation "io.reactivex.rxjava2:rxjava:2.2.8"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
implementation 'com.squareup.okio:okio:2.2.2'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.amap.api:location:latest.integration'
implementation 'com.yayandroid:LocationManager:2.0.4'
}

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

@ -0,0 +1,26 @@
package com.example.luyin;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.example.luyin", appContext.getPackageName());
}
}

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.luyin">
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<!--允许联网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!--获取GSM2g、WCDMA联通3g等网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--获取wifi网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--保持CPU 运转,屏幕和键盘灯有可能是关闭的,用于文件上传和下载 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--获取sd卡写的权限用于文件上传和下载-->
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-->
<!--允许读取手机状态 用于创建BmobInstallation-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--允许程序打开网络套接字-->
<uses-permission android:name="android.permission.INTERNET" />
<!--用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!--用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--用于访问wifi网络信息wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!--用于访问网络,网络定位需要上网-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--用于写入缓存数据到扩展存储卡-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--用于申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<!--连接网络权限,用于执行云端语音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--读取联系人权限,上传联系人需要用到此权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--外存储写权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--配置权限,用来记录应用配置信息 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务-->
<!--定位信息是敏感信息可通过Setting.setLocationEnable(false)关闭定位请求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--如需使用人脸识别,还要添加:摄像头权限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application
android:name=".activities.MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service android:name="com.amap.api.location.APSService"></service>
<!-- <provider-->
<!-- android:name="cn.bmob.v3.util.BmobContentProvider"-->
<!-- android:authorities="luyin.BmobContentProvider">-->
<!-- </provider>-->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="9f73eaf8e04b78b685a4e8c51be8bd93" />
<service
android:name=".wechat.service.RedEnvelopeService"
android:label="@string/app_name"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
<activity
android:name=".activities.MainActivity"
android:launchMode="singleTask"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.example.luyin.speech.setting.IatSettings" >
</activity>
<activity android:name="com.example.luyin.speech.setting.TtsSettings" >
</activity>
<activity android:name=".activities.Wechat">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activities.TtsDemo"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".activities.VoiceActivity"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".activities.Contact">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".activities.SMS">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".activities.Location_Activity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".activities.CheckPermissionsActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".activities.Location_BackGround_Activity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<provider
android:name="cn.bmob.v3.util.BmobContentProvider"
android:authorities="com.example.luyin.BmobContentProvider">
</provider>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

@ -0,0 +1,216 @@
package com.example.luyin.activities;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.KeyEvent;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import com.example.luyin.R;
/**
* ActivityAndroid6.0
* Activity
*
*/
public class CheckPermissionsActivity extends Activity {
//是否需要检测后台定位权限设置为true时如果用户没有给予后台定位权限会弹窗提示
private boolean needCheckBackLocation = false;
//如果设置了target > 28需要增加这个权限否则不会弹出"始终允许"这个选择框
private static String BACKGROUND_LOCATION_PERMISSION = "android.permission.ACCESS_BACKGROUND_LOCATION";
/**
*
*/
protected String[] needPermissions = {
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE
};
private static final int PERMISSON_REQUESTCODE = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(Build.VERSION.SDK_INT > 28
&& getApplicationContext().getApplicationInfo().targetSdkVersion > 28) {
needPermissions = new String[] {
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
BACKGROUND_LOCATION_PERMISSION
};
}
}
/**
*
*/
private boolean isNeedCheck = true;
@Override
protected void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= 23
&& getApplicationInfo().targetSdkVersion >= 23) {
if (isNeedCheck) {
checkPermissions(needPermissions);
}
}
}
/**
*
* @param permissions
* @since 2.5.0
*
*/
private void checkPermissions(String... permissions) {
try {
if (Build.VERSION.SDK_INT >= 23
&& getApplicationInfo().targetSdkVersion >= 23) {
List<String> needRequestPermissonList = findDeniedPermissions(permissions);
if (null != needRequestPermissonList
&& needRequestPermissonList.size() > 0) {
String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
Method method = getClass().getMethod("requestPermissions", new Class[]{String[].class,
int.class});
method.invoke(this, array, PERMISSON_REQUESTCODE);
}
}
} catch (Throwable e) {
}
}
/**
*
*
* @param permissions
* @return
* @since 2.5.0
*
*/
private List<String> findDeniedPermissions(String[] permissions) {
List<String> needRequestPermissonList = new ArrayList<String>();
if (Build.VERSION.SDK_INT >= 23
&& getApplicationInfo().targetSdkVersion >= 23){
try {
for (String perm : permissions) {
Method checkSelfMethod = getClass().getMethod("checkSelfPermission", String.class);
Method shouldShowRequestPermissionRationaleMethod = getClass().getMethod("shouldShowRequestPermissionRationale",
String.class);
if ((Integer)checkSelfMethod.invoke(this, perm) != PackageManager.PERMISSION_GRANTED
|| (Boolean)shouldShowRequestPermissionRationaleMethod.invoke(this, perm)) {
if(!needCheckBackLocation
&& BACKGROUND_LOCATION_PERMISSION.equals(perm)) {
continue;
}
needRequestPermissonList.add(perm);
}
}
} catch (Throwable e) {
}
}
return needRequestPermissonList;
}
/**
*
* @param grantResults
* @return
* @since 2.5.0
*
*/
private boolean verifyPermissions(int[] grantResults) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
@TargetApi(23)
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] paramArrayOfInt) {
if (requestCode == PERMISSON_REQUESTCODE) {
if (!verifyPermissions(paramArrayOfInt)) {
showMissingPermissionDialog();
isNeedCheck = false;
}
}
}
/**
*
*
* @since 2.5.0
*
*/
private void showMissingPermissionDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.notifyTitle);
builder.setMessage(R.string.notifyMsg);
// 拒绝, 退出应用
builder.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setPositiveButton(R.string.setting,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAppSettings();
}
});
builder.setCancelable(false);
builder.show();
}
/**
*
*
* @since 2.5.0
*
*/
private void startAppSettings() {
Intent intent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
}

@ -0,0 +1,54 @@
package com.example.luyin.activities;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.example.luyin.services.EmergencyPeople;
import com.example.luyin.R;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
public class Contact extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact);
//Toast.makeText(Contact.this, "短信发送完成", Toast.LENGTH_LONG).show();
}
public void confirm(View view){
EditText phoneNumber1=(EditText)findViewById(R.id.phonenumber);
String phoneNumber2=phoneNumber1.getText().toString();
EmergencyPeople people = new EmergencyPeople();
people.setPhoneNumber(phoneNumber2);
EditText name1=(EditText)findViewById(R.id.contact);
String name2=name1.getText().toString();
EmergencyPeople people1 = new EmergencyPeople();
people1.setPhoneNumber(phoneNumber2);
people1.setName(name2);
Log.e("ss", "confirm: "+ people1.getName() );
Log.e("bb", "confirm: "+people1.getPhoneNumber());
people1.save(new SaveListener<String>() {
@Override
public void done(String s, BmobException e) {
if(e==null){
Toast.makeText(getApplicationContext(),"添加联系人成功",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(),"添加失败",Toast.LENGTH_LONG).show();
}
}
});
// Toast.makeText(Contact.this, "已添加紧急联系人",Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Contact.this,MainActivity.class);
startActivity(intent);
}
}

@ -0,0 +1,384 @@
package com.example.luyin.activities;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationClientOption.AMapLocationMode;
import com.amap.api.location.AMapLocationClientOption.AMapLocationProtocol;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.AMapLocationQualityReport;
import com.example.luyin.utils.Utils;
import com.example.luyin.R;
// 高精度定位模式
public class Location_Activity extends CheckPermissionsActivity
implements
OnCheckedChangeListener,
OnClickListener {
private RadioGroup rgLocationMode;
private EditText etInterval;
private EditText etHttpTimeout;
private CheckBox cbOnceLocation;
private CheckBox cbAddress;
private CheckBox cbGpsFirst;
private CheckBox cbCacheAble;
private CheckBox cbOnceLastest;
private CheckBox cbSensorAble;
private TextView tvResult;
private Button btLocation;
private RadioGroup rgGeoLanguage;
private AMapLocationClient locationClient = null;
private AMapLocationClientOption locationOption = null;
//储存位置
public static String Location = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
setTitle(R.string.title_location);
initView();
//初始化定位
initLocation();
}
//初始化控件
private void initView(){
rgLocationMode = (RadioGroup) findViewById(R.id.rg_locationMode);
etInterval = (EditText) findViewById(R.id.et_interval);
etHttpTimeout = (EditText) findViewById(R.id.et_httpTimeout);
cbOnceLocation = (CheckBox)findViewById(R.id.cb_onceLocation);
cbGpsFirst = (CheckBox) findViewById(R.id.cb_gpsFirst);
cbAddress = (CheckBox) findViewById(R.id.cb_needAddress);
cbCacheAble = (CheckBox) findViewById(R.id.cb_cacheAble);
cbOnceLastest = (CheckBox) findViewById(R.id.cb_onceLastest);
cbSensorAble = (CheckBox)findViewById(R.id.cb_sensorAble);
tvResult = (TextView) findViewById(R.id.tv_result);
btLocation = (Button) findViewById(R.id.bt_location);
rgGeoLanguage = (RadioGroup) findViewById(R.id.rg_language);
rgLocationMode.setOnCheckedChangeListener(this);
btLocation.setOnClickListener(this);
rgGeoLanguage.setOnCheckedChangeListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
destroyLocation();
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (null == locationOption) {
locationOption = new AMapLocationClientOption();
}
if(group == rgLocationMode) {
switch (checkedId) {
case R.id.rb_batterySaving:
locationOption.setLocationMode(AMapLocationMode.Battery_Saving);
break;
case R.id.rb_deviceSensors:
locationOption.setLocationMode(AMapLocationMode.Device_Sensors);
break;
case R.id.rb_hightAccuracy:
locationOption.setLocationMode(AMapLocationMode.Hight_Accuracy);
break;
default:
break;
}
}
if(group == rgGeoLanguage){
switch (checkedId){
case R.id.rb_languageDefault:
locationOption.setGeoLanguage(AMapLocationClientOption.GeoLanguage.DEFAULT);
break;
case R.id.rb_languageEN:
locationOption.setGeoLanguage(AMapLocationClientOption.GeoLanguage.EN);
break;
case R.id.rb_languageZH:
locationOption.setGeoLanguage(AMapLocationClientOption.GeoLanguage.ZH);
break;
}
}
}
/**
*
*/
private void setViewEnable(boolean isEnable) {
for(int i=0; i<rgLocationMode.getChildCount(); i++){
rgLocationMode.getChildAt(i).setEnabled(isEnable);
}
etInterval.setEnabled(isEnable);
etHttpTimeout.setEnabled(isEnable);
cbOnceLocation.setEnabled(isEnable);
cbGpsFirst.setEnabled(isEnable);
cbAddress.setEnabled(isEnable);
cbCacheAble.setEnabled(isEnable);
cbOnceLastest.setEnabled(isEnable);
cbSensorAble.setEnabled(isEnable);
for(int j=0; j<rgGeoLanguage.getChildCount(); j++){
rgGeoLanguage.getChildAt(j).setEnabled(isEnable);
}
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.bt_location) {
if (btLocation.getText().equals(
getResources().getString(R.string.startLocation))) {
setViewEnable(false);
btLocation.setText(getResources().getString(
R.string.stopLocation));
tvResult.setText("正在定位...");
startLocation();
} else {
setViewEnable(true);
btLocation.setText(getResources().getString(
R.string.startLocation));
stopLocation();
tvResult.setText("定位停止");
}
}
}
/**
*
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void initLocation(){
//初始化client
locationClient = new AMapLocationClient(this.getApplicationContext());
locationOption = getDefaultOption();
//设置定位参数
locationClient.setLocationOption(locationOption);
// 设置定位监听
locationClient.setLocationListener(locationListener);
}
/**
*
* @since 2.8.0
* @author hongming.wang
*
*/
private AMapLocationClientOption getDefaultOption(){
AMapLocationClientOption mOption = new AMapLocationClientOption();
mOption.setLocationMode(AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
mOption.setGpsFirst(false);//可选设置是否gps优先只在高精度模式下有效。默认关闭
mOption.setHttpTimeOut(30000);//可选设置网络请求超时时间。默认为30秒。在仅设备模式下无效
mOption.setInterval(2000);//可选设置定位间隔。默认为2秒
mOption.setNeedAddress(true);//可选设置是否返回逆地理地址信息。默认是true
mOption.setOnceLocation(false);//可选设置是否单次定位。默认是false
mOption.setOnceLocationLatest(false);//可选设置是否等待wifi刷新默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationProtocol.HTTP);//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
mOption.setSensorEnable(false);//可选设置是否使用传感器。默认是false
mOption.setWifiScan(true); //可选设置是否开启wifi扫描。默认为true如果设置为false会同时停止主动刷新停止以后完全依赖于系统刷新定位位置可能存在误差
mOption.setLocationCacheEnable(true); //可选设置是否使用缓存定位默认为true
mOption.setGeoLanguage(AMapLocationClientOption.GeoLanguage.DEFAULT);//可选,设置逆地理信息的语言,默认值为默认语言(根据所在地区选择语言)
return mOption;
}
/**
*
*/
AMapLocationListener locationListener = new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation location) {
if (null != location) {
StringBuffer sb = new StringBuffer();
//errCode等于0代表定位成功其他的为定位失败具体的可以参照官网定位错误码说明
if(location.getErrorCode() == 0){
sb.append("定位成功" + "\n");
sb.append("定位类型: " + location.getLocationType() + "\n");
sb.append("经 度 : " + location.getLongitude() + "\n");
sb.append("纬 度 : " + location.getLatitude() + "\n");
sb.append("精 度 : " + location.getAccuracy() + "米" + "\n");
sb.append("提供者 : " + location.getProvider() + "\n");
sb.append("速 度 : " + location.getSpeed() + "米/秒" + "\n");
sb.append("角 度 : " + location.getBearing() + "\n");
// 获取当前提供定位服务的卫星个数
sb.append("星 数 : " + location.getSatellites() + "\n");
sb.append("国 家 : " + location.getCountry() + "\n");
sb.append("省 : " + location.getProvince() + "\n");
sb.append("市 : " + location.getCity() + "\n");
sb.append("城市编码 : " + location.getCityCode() + "\n");
sb.append("区 : " + location.getDistrict() + "\n");
sb.append("区域 码 : " + location.getAdCode() + "\n");
sb.append("地 址 : " + location.getAddress() + "\n");
sb.append("兴趣点 : " + location.getPoiName() + "\n");
//定位完成的时间
sb.append("定位时间: " + Utils.formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
} else {
//定位失败
sb.append("定位失败" + "\n");
sb.append("错误码:" + location.getErrorCode() + "\n");
sb.append("错误信息:" + location.getErrorInfo() + "\n");
sb.append("错误描述:" + location.getLocationDetail() + "\n");
}
sb.append("***定位质量报告***").append("\n");
sb.append("* WIFI开关").append(location.getLocationQualityReport().isWifiAble() ? "开启":"关闭").append("\n");
sb.append("* GPS状态").append(getGPSStatusString(location.getLocationQualityReport().getGPSStatus())).append("\n");
sb.append("* GPS星数").append(location.getLocationQualityReport().getGPSSatellites()).append("\n");
sb.append("* 网络类型:" + location.getLocationQualityReport().getNetworkType()).append("\n");
sb.append("* 网络耗时:" + location.getLocationQualityReport().getNetUseTime()).append("\n");
sb.append("****************").append("\n");
//定位之后的回调时间
sb.append("回调时间: " + Utils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
//解析定位结果,
String result = sb.toString();
Location = "爷危速来!"+"\n"+"地点:"+location.getProvince() + location.getCity()+location.getDistrict()
+location.getAddress()+location.getStreet()+location.getStreetNum()
+"\n"+"北纬"+location.getLatitude()+"东经"+location.getLongitude();
// Intent intent = new Intent();
// intent.putExtra("location",result);
//// startActivity(intent);
// sendBroadcast(intent);
tvResult.setText(result);
} else {
tvResult.setText("定位失败loc is null");
}
}
};
/**
* GPS
* @param statusCode GPS
* @return
*/
private String getGPSStatusString(int statusCode){
String str = "";
switch (statusCode){
case AMapLocationQualityReport.GPS_STATUS_OK:
str = "GPS状态正常";
break;
case AMapLocationQualityReport.GPS_STATUS_NOGPSPROVIDER:
str = "手机中没有GPS Provider无法进行GPS定位";
break;
case AMapLocationQualityReport.GPS_STATUS_OFF:
str = "GPS关闭建议开启GPS提高定位质量";
break;
case AMapLocationQualityReport.GPS_STATUS_MODE_SAVING:
str = "选择的定位模式中不包含GPS定位建议选择包含GPS定位的模式提高定位质量";
break;
case AMapLocationQualityReport.GPS_STATUS_NOGPSPERMISSION:
str = "没有GPS定位权限建议开启gps定位权限";
break;
}
return str;
}
// 根据控件的选择,重新设置定位参数
private void resetOption() {
// 设置是否需要显示地址信息
locationOption.setNeedAddress(cbAddress.isChecked());
/**
* GPS30GPS
*
*/
locationOption.setGpsFirst(cbGpsFirst.isChecked());
// 设置是否开启缓存
locationOption.setLocationCacheEnable(cbCacheAble.isChecked());
// 设置是否单次定位
locationOption.setOnceLocation(cbOnceLocation.isChecked());
//设置是否等待设备wifi刷新如果设置为true,会自动变为单次定位,持续定位时不要使用
locationOption.setOnceLocationLatest(cbOnceLastest.isChecked());
//设置是否使用传感器
locationOption.setSensorEnable(cbSensorAble.isChecked());
//设置是否开启wifi扫描如果设置为false时同时会停止主动刷新停止以后完全依赖于系统刷新定位位置可能存在误差
String strInterval = etInterval.getText().toString();
if (!TextUtils.isEmpty(strInterval)) {
try{
// 设置发送定位请求的时间间隔,最小值为1000如果小于1000按照1000算
locationOption.setInterval(Long.valueOf(strInterval));
}catch(Throwable e){
e.printStackTrace();
}
}
String strTimeout = etHttpTimeout.getText().toString();
if(!TextUtils.isEmpty(strTimeout)){
try{
// 设置网络请求超时时间
locationOption.setHttpTimeOut(Long.valueOf(strTimeout));
}catch(Throwable e){
e.printStackTrace();
}
}
}
/**
*
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void startLocation(){
//根据控件的选择,重新设置定位参数
resetOption();
// 设置定位参数
locationClient.setLocationOption(locationOption);
// 启动定位
locationClient.startLocation();
}
/**
*
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void stopLocation(){
// 停止定位
locationClient.stopLocation();
}
/**
*
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void destroyLocation(){
if (null != locationClient) {
/**
* AMapLocationClientActivity
* ActivityonDestroyAMapLocationClientonDestroy
*/
locationClient.onDestroy();
locationClient = null;
locationOption = null;
}
}
}

@ -0,0 +1,350 @@
package com.example.luyin.activities;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationClientOption.AMapLocationMode;
import com.amap.api.location.AMapLocationClientOption.AMapLocationProtocol;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.AMapLocationQualityReport;
import com.example.luyin.utils.Utils;
import com.example.luyin.R;
/**
*
*/
public class Location_BackGround_Activity extends CheckPermissionsActivity
implements
OnClickListener {
private TextView tvResult;
private Button btLocation;
private Button btEnableBackgroundLocation;
private Button btDisableBackgroundLocation;
private AMapLocationClient locationClient = null;
private AMapLocationClientOption locationOption = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location_background);
setTitle(R.string.title_locationBackground);
initView();
initLocation();
}
@Override
protected void onResume() {
super.onResume();
//切入前台后关闭后台定位功能
if(null != locationClient) {
locationClient.disableBackgroundLocation(true);
}
}
@Override
protected void onStop() {
super.onStop();
boolean isBackground = ((MyApplication)getApplication()).isBackground();
//如果app已经切入到后台启动后台定位功能
if(isBackground){
if(null != locationClient) {
locationClient.enableBackgroundLocation(2001, buildNotification());
}
}
}
@Override
protected void onPause() {
super.onPause();
}
//初始化控件
private void initView(){
tvResult = (TextView) findViewById(R.id.tv_result);
btLocation = (Button) findViewById(R.id.bt_location);
btEnableBackgroundLocation = (Button) findViewById(R.id.bt_enableBackground);
btDisableBackgroundLocation = (Button) findViewById(R.id.bt_disableBackground);
btLocation.setOnClickListener(this);
btEnableBackgroundLocation.setOnClickListener(this);
btDisableBackgroundLocation.setOnClickListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
destroyLocation();
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.bt_location) {
if (btLocation.getText().equals(
getResources().getString(R.string.startLocation))) {
btLocation.setText(getResources().getString(
R.string.stopLocation));
tvResult.setText("正在定位...");
startLocation();
} else {
btLocation.setText(getResources().getString(
R.string.startLocation));
stopLocation();
tvResult.setText("定位停止");
}
}
if(v.getId() == R.id.bt_enableBackground){
if(null == locationClient){
locationClient = new AMapLocationClient(this);
}
//启动后台定位
locationClient.enableBackgroundLocation(2001, buildNotification());
}
if(v.getId() == R.id.bt_disableBackground){
if(null == locationClient){
locationClient = new AMapLocationClient(this);
}
//关闭后台定位
locationClient.disableBackgroundLocation(true);
}
}
/**
*
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void initLocation(){
//初始化client
locationClient = new AMapLocationClient(this.getApplicationContext());
locationOption = getDefaultOption();
//设置定位参数
locationClient.setLocationOption(locationOption);
// 设置定位监听
locationClient.setLocationListener(locationListener);
}
/**
*
* @since 2.8.0
* @author hongming.wang
*
*/
private AMapLocationClientOption getDefaultOption(){
AMapLocationClientOption mOption = new AMapLocationClientOption();
mOption.setLocationMode(AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
mOption.setGpsFirst(false);//可选设置是否gps优先只在高精度模式下有效。默认关闭
mOption.setHttpTimeOut(30000);//可选设置网络请求超时时间。默认为30秒。在仅设备模式下无效
mOption.setInterval(2000);//可选设置定位间隔。默认为2秒
mOption.setNeedAddress(true);//可选设置是否返回逆地理地址信息。默认是true
mOption.setOnceLocation(false);//可选设置是否单次定位。默认是false
mOption.setOnceLocationLatest(false);//可选设置是否等待wifi刷新默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationProtocol.HTTP);//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
mOption.setSensorEnable(false);//可选设置是否使用传感器。默认是false
mOption.setWifiScan(true); //可选设置是否开启wifi扫描。默认为true如果设置为false会同时停止主动刷新停止以后完全依赖于系统刷新定位位置可能存在误差
mOption.setLocationCacheEnable(true); //可选设置是否使用缓存定位默认为true
return mOption;
}
/**
*
*/
AMapLocationListener locationListener = new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation location) {
if (null != location) {
StringBuffer sb = new StringBuffer();
//errCode等于0代表定位成功其他的为定位失败具体的可以参照官网定位错误码说明
if(location.getErrorCode() == 0){
sb.append("定位成功" + "\n");
sb.append("定位类型: " + location.getLocationType() + "\n");
sb.append("经 度 : " + location.getLongitude() + "\n");
sb.append("纬 度 : " + location.getLatitude() + "\n");
sb.append("精 度 : " + location.getAccuracy() + "米" + "\n");
sb.append("提供者 : " + location.getProvider() + "\n");
sb.append("速 度 : " + location.getSpeed() + "米/秒" + "\n");
sb.append("角 度 : " + location.getBearing() + "\n");
// 获取当前提供定位服务的卫星个数
sb.append("星 数 : " + location.getSatellites() + "\n");
sb.append("国 家 : " + location.getCountry() + "\n");
sb.append("省 : " + location.getProvince() + "\n");
sb.append("市 : " + location.getCity() + "\n");
sb.append("城市编码 : " + location.getCityCode() + "\n");
sb.append("区 : " + location.getDistrict() + "\n");
sb.append("区域 码 : " + location.getAdCode() + "\n");
sb.append("地 址 : " + location.getAddress() + "\n");
sb.append("地 址 : " + location.getDescription() + "\n");
sb.append("兴趣点 : " + location.getPoiName() + "\n");
//定位完成的时间
sb.append("定位时间: " + Utils.formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
} else {
//定位失败
sb.append("定位失败" + "\n");
sb.append("错误码:" + location.getErrorCode() + "\n");
sb.append("错误信息:" + location.getErrorInfo() + "\n");
sb.append("错误描述:" + location.getLocationDetail() + "\n");
}
sb.append("***定位质量报告***").append("\n");
sb.append("* WIFI开关").append(location.getLocationQualityReport().isWifiAble() ? "开启":"关闭").append("\n");
sb.append("* GPS状态").append(getGPSStatusString(location.getLocationQualityReport().getGPSStatus())).append("\n");
sb.append("* GPS星数").append(location.getLocationQualityReport().getGPSSatellites()).append("\n");
sb.append("****************").append("\n");
//定位之后的回调时间
sb.append("回调时间: " + Utils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
//解析定位结果,
String result = sb.toString();
tvResult.setText(result);
} else {
tvResult.setText("定位失败loc is null");
}
}
};
/**
* GPS
* @param statusCode GPS
* @return
*/
private String getGPSStatusString(int statusCode){
String str = "";
switch (statusCode){
case AMapLocationQualityReport.GPS_STATUS_OK:
str = "GPS状态正常";
break;
case AMapLocationQualityReport.GPS_STATUS_NOGPSPROVIDER:
str = "手机中没有GPS Provider无法进行GPS定位";
break;
case AMapLocationQualityReport.GPS_STATUS_OFF:
str = "GPS关闭建议开启GPS提高定位质量";
break;
case AMapLocationQualityReport.GPS_STATUS_MODE_SAVING:
str = "选择的定位模式中不包含GPS定位建议选择包含GPS定位的模式提高定位质量";
break;
case AMapLocationQualityReport.GPS_STATUS_NOGPSPERMISSION:
str = "没有GPS定位权限建议开启gps定位权限";
break;
}
return str;
}
/**
*
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void startLocation(){
// 设置定位参数
locationClient.setLocationOption(locationOption);
// 启动定位
locationClient.startLocation();
}
/**
*
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void stopLocation(){
// 停止定位
locationClient.stopLocation();
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
/**
*
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void destroyLocation(){
if (null != locationClient) {
/**
* AMapLocationClientActivity
* ActivityonDestroyAMapLocationClientonDestroy
*/
locationClient.onDestroy();
locationClient = null;
locationOption = null;
}
}
private void createNotificationChannel(){
}
private static final String NOTIFICATION_CHANNEL_NAME = "BackgroundLocation";
private NotificationManager notificationManager = null;
boolean isCreateChannel = false;
@SuppressLint("NewApi")
private Notification buildNotification() {
Notification.Builder builder = null;
Notification notification = null;
if(android.os.Build.VERSION.SDK_INT >= 26) {
//Android O上对Notification进行了修改如果设置的targetSDKVersion>=26建议使用此种方式创建通知栏
if (null == notificationManager) {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
String channelId = getPackageName();
if(!isCreateChannel) {
NotificationChannel notificationChannel = new NotificationChannel(channelId,
NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.enableLights(true);//是否在桌面icon右上角展示小圆点
notificationChannel.setLightColor(Color.WHITE); //小圆点颜色
notificationChannel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
notificationManager.createNotificationChannel(notificationChannel);
isCreateChannel = true;
}
builder = new Notification.Builder(getApplicationContext(), channelId);
} else {
builder = new Notification.Builder(getApplicationContext());
}
builder.setSmallIcon(R.drawable.locate)
.setContentTitle(Utils.getAppName(this))
.setContentText("正在后台运行")
.setWhen(System.currentTimeMillis());
if (android.os.Build.VERSION.SDK_INT >= 16) {
notification = builder.build();
} else {
return builder.getNotification();
}
return notification;
}
}

@ -0,0 +1,729 @@
package com.example.luyin.activities;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.telephony.SmsManager;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.graphics.Color;
import android.widget.CompoundButton;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.example.luyin.services.Location;
import com.example.luyin.speech.setting.TtsSettings;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.util.ResourceUtil;
import com.example.luyin.utils.Utils;
import com.example.luyin.R;
import java.util.ArrayList;
import java.util.Calendar;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicLong;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
public class MainActivity extends Activity implements SensorEventListener {
private static String TAG = MainActivity.class.getSimpleName();
private static final String TAG_EXIT = "程序退出";
private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
private static final String NOTIFICATION_CHANNEL_NAME = "BackgroundLocation";
private final String TAGS = "SMSBroadcastReceiver";
private AMapLocationClient locationClient = null; //声明mLocationOption对象
private AMapLocationClientOption locationOption = null;
public String LocationLLLL = null;
public long lastTime = 0;
public long timeDifference = 1000;
private NotificationManager notificationManager = null;
private SensorManager sensorManager; //sensor管理器
private Vibrator mVibrator; //震动
private TextView start;
private TextView mOffTextView;
private Handler mOffHandler;
private Timer mOffTime;
private Dialog mDialog;
private Button button = null; //按钮
private boolean mIsExit;
private boolean isCreateChannel = false;
private Toast mToast;
private SpeechSynthesizer mTts;
private int mPercentForBuffering = 0;
private int mPercentForPlaying = 0;
private String mEngineType = SpeechConstant.TYPE_CLOUD;
// 默认云端发音人
public static String voicerCloud="xiaoyan";
// 默认本地发音人
public static String voicerLocal="xiaoyan";
public static String voicerXtts="xiaoyan";
private SharedPreferences mSharedPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.getLocation);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setClass(MainActivity.this,Location_Activity.class);
startActivity(intent);
}
});
start=(TextView) findViewById(R.id.start);
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
mVibrator=(Vibrator) getSystemService(VIBRATOR_SERVICE);
initLocation();
if(null == locationClient){
locationClient = new AMapLocationClient(this);
}
boolean isCreateChannel = false;
locationClient.enableBackgroundLocation(2001, buildNotification());
locationClient.startLocation();
// getCurrentLocationLatLng();
Bmob.initialize(this,"f7635857d1eedd1e8949b0ca0d5324de"); //添加bmob数据库
//初始化语音
StringBuffer param = new StringBuffer();
param.append("appid="+getString(R.string.app_id));
param.append(",");
// 设置使用v5+
param.append(SpeechConstant.ENGINE_MODE+"="+ SpeechConstant.MODE_MSC);
SpeechUtility.createUtility(MainActivity.this, param.toString());
mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);
mSharedPreferences = getSharedPreferences(TtsSettings.PREFER_NAME, Activity.MODE_PRIVATE);
}
public void stop(View view) {
Toast.makeText(MainActivity.this, "程序已结束", Toast.LENGTH_SHORT).show();
finish();
}
public void getLocation(View view){
}
public void play(View view) {
Toast.makeText(MainActivity.this, "程序开始", Toast.LENGTH_SHORT).show();
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
}
public void contact(View view) {
Intent intent = new Intent(MainActivity.this, Contact.class);
startActivity(intent);
//finish();
}
public void voice(View view) {
Intent intent = new Intent(MainActivity.this, VoiceActivity.class);
startActivity(intent);
//finish();
//Toast.makeText(MainActivity.this, "cnm", Toast.LENGTH_LONG).show();
}
public void backLocate(View view){
Intent intent = new Intent(MainActivity.this, Location_BackGround_Activity.class);
startActivity(intent);
}
public void wechat(View view) {
Intent intent = new Intent(MainActivity.this, Wechat.class);
startActivity(intent);
//finish();
}
private void showToast(String msg) {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
}
private void showTip(final String str){
runOnUiThread(new Runnable() {
@Override
public void run() {
mToast.setText(str);
mToast.show();
}
});
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume(); //传感器的绑定
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
sensorManager.unregisterListener(this); //传感器的解除绑定
super.onStop();
}
@SuppressLint("HandlerLeak")
@Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
String phonenum = "18577348433";
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
if (Math.abs(event.values[0]) > 20 || Math.abs(event.values[1]) > 20 || Math.abs(event.values[2]) > 20) {
AtomicLong currentTime = new AtomicLong(Calendar.getInstance().getTimeInMillis());
if ((currentTime.get() - lastTime) > timeDifference) {
lastTime = currentTime.get();
//mVibrator.vibrate(100);
//获得Vibrator实例
final Vibrator vibrator = (Vibrator)this.getSystemService(this.VIBRATOR_SERVICE);
//暂停1秒震动2秒暂停1秒震动2秒
long[] patter = {1000, 2000, 1000, 2000};
//设置为持续震动
vibrator.vibrate(patter, 0);
//showToast("开始震动");
setParam();
int code = mTts.startSpeaking(getString(R.string.crash), mTtsListener);
mOffTextView = new TextView(this);
mDialog = new AlertDialog.Builder(this)
.setTitle(getString(R.string.crash))
.setCancelable(false)
.setView(mOffTextView)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
//点击确定后的操作
public void onClick(DialogInterface dialog, int id) {
mOffTime.cancel();
mTts.stopSpeaking();
vibrator.cancel();
sendMessage();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
//点击取消后的操作
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
mOffTime.cancel();
showToast("没有报警");
//震动停止
vibrator.cancel();
mTts.stopSpeaking();
}
})
.create();
mDialog.show();
mDialog.setCanceledOnTouchOutside(false);
mOffHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what > 0) {
//动态显示倒计时
mOffTextView.setText("\n" +
" 倒计时:" + msg.what);
} else {
//倒计时结束自己主动关闭
if (mDialog != null) {
mDialog.dismiss();
}
//callPhone(phonenum);
showToast("您未点击取消,已报警");
//关闭后的操作
mOffTime.cancel();
//震动停止
vibrator.cancel();
}
super.handleMessage(msg);
}
};
//////倒计时
mOffTime = new Timer(true);
TimerTask tt = new TimerTask() {
int countTime = 30;
public void run() {
if (countTime > 0) {
countTime--;
}
Message msg = new Message();
msg.what = countTime;
mOffHandler.sendMessage(msg);
}
};
mOffTime.schedule(tt, 1000, 1000);
}
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
public void callPhone(String phoneNum) {
//android6版本获取动态权限
if (Build.VERSION.SDK_INT >= 23) {
int REQUEST_CODE_CONTACT = 101;
String[] permissions = {Manifest.permission.CALL_PHONE};
//验证是否许可权限
for (String str : permissions) {
if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
return;
}
}
}
//如果需要手动拨号将Intent.ACTION_CALL改为Intent.ACTION_DIAL跳转到拨号界面用户手动点击拨打
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + phoneNum);
intent.setData(data);
startActivity(intent);
}
public void sendMessage() {
// Intent intent = getIntent();
// String content = intent.getStringExtra("location");
String content = LocationLLLL;
String number = "18577348433";
if (TextUtils.isEmpty(number)) {
showToast("请输入手机号");
return;
}
if (TextUtils.isEmpty(content)) {
showToast("请输入内容");
return;
}
ArrayList<String> messages = SmsManager.getDefault().divideMessage(content);
for (String text : messages) {
SmsManager.getDefault().sendTextMessage(number, null, text, null, null);
setParam();
int code = mTts.startSpeaking("救命!我出车祸了!"+text, mTtsListener);
}
showToast("短信已发送");
Location loca1 = new Location();
loca1.setAddress(LocationLLLL);
loca1.setName("ouxiaolan");
loca1.save(new SaveListener<String>() {
@Override
public void done(String s, BmobException e) {
if(e==null){
Toast.makeText(getApplicationContext(),"添加数据成功返回objectID"+s,Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(),"创建数据失败"+e.getMessage(),Toast.LENGTH_LONG).show();
}
}
});
}
private void initLocation(){
//初始化client
locationClient = new AMapLocationClient(this.getApplicationContext());
locationOption = getDefaultOption();
//设置定位参数
locationClient.setLocationOption(locationOption);
// 设置定位监听
locationClient.setLocationListener(locationListener);
}
private Notification buildNotification() {
Notification.Builder builder = null;
Notification notification = null;
if(android.os.Build.VERSION.SDK_INT >= 26) {
//Android O上对Notification进行了修改如果设置的targetSDKVersion>=26建议使用此种方式创建通知栏
if (null == notificationManager) {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
String channelId = getPackageName();
if(!isCreateChannel) {
NotificationChannel notificationChannel = new NotificationChannel(channelId,
NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.enableLights(true);//是否在桌面icon右上角展示小圆点
notificationChannel.setLightColor(Color.WHITE); //小圆点颜色
notificationChannel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
notificationManager.createNotificationChannel(notificationChannel);
isCreateChannel = true;
}
builder = new Notification.Builder(getApplicationContext(), channelId);
} else {
builder = new Notification.Builder(getApplicationContext());
}
builder.setSmallIcon(R.drawable.locate)
.setContentTitle(Utils.getAppName(this))
.setContentText("正在后台运行")
.setWhen(System.currentTimeMillis());
if (android.os.Build.VERSION.SDK_INT >= 16) {
notification = builder.build();
} else {
return builder.getNotification();
}
return notification;
}
private AMapLocationClientOption getDefaultOption(){
AMapLocationClientOption mOption = new AMapLocationClientOption();
mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
mOption.setGpsFirst(false);//可选设置是否gps优先只在高精度模式下有效。默认关闭
mOption.setHttpTimeOut(30000);//可选设置网络请求超时时间。默认为30秒。在仅设备模式下无效
mOption.setInterval(2000);//可选设置定位间隔。默认为2秒
mOption.setNeedAddress(true);//可选设置是否返回逆地理地址信息。默认是true
mOption.setOnceLocation(false);//可选设置是否单次定位。默认是false
mOption.setOnceLocationLatest(false);//可选设置是否等待wifi刷新默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
mOption.setSensorEnable(false);//可选设置是否使用传感器。默认是false
mOption.setWifiScan(true); //可选设置是否开启wifi扫描。默认为true如果设置为false会同时停止主动刷新停止以后完全依赖于系统刷新定位位置可能存在误差
mOption.setLocationCacheEnable(true); //可选设置是否使用缓存定位默认为true
return mOption;
}
AMapLocationListener locationListener = new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation location) {
if (null != location) {
StringBuffer sb = new StringBuffer();
//errCode等于0代表定位成功其他的为定位失败具体的可以参照官网定位错误码说明
if(location.getErrorCode() == 0){
sb.append("定位成功" + "\n");
sb.append("定位类型: " + location.getLocationType() + "\n");
sb.append("经 度 : " + location.getLongitude() + "\n");
sb.append("纬 度 : " + location.getLatitude() + "\n");
sb.append("精 度 : " + location.getAccuracy() + "米" + "\n");
sb.append("提供者 : " + location.getProvider() + "\n");
sb.append("速 度 : " + location.getSpeed() + "米/秒" + "\n");
sb.append("角 度 : " + location.getBearing() + "\n");
// 获取当前提供定位服务的卫星个数
sb.append("星 数 : " + location.getSatellites() + "\n");
sb.append("国 家 : " + location.getCountry() + "\n");
sb.append("省 : " + location.getProvince() + "\n");
sb.append("市 : " + location.getCity() + "\n");
sb.append("城市编码 : " + location.getCityCode() + "\n");
sb.append("区 : " + location.getDistrict() + "\n");
sb.append("区域 码 : " + location.getAdCode() + "\n");
sb.append("地 址 : " + location.getAddress() + "\n");
sb.append("兴趣点 : " + location.getPoiName() + "\n");
//定位完成的时间
sb.append("定位时间: " + Utils.formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
} else {
//定位失败
sb.append("定位失败" + "\n");
sb.append("错误码:" + location.getErrorCode() + "\n");
sb.append("错误信息:" + location.getErrorInfo() + "\n");
sb.append("错误描述:" + location.getLocationDetail() + "\n");
}
sb.append("***定位质量报告***").append("\n");
sb.append("* WIFI开关").append(location.getLocationQualityReport().isWifiAble() ? "开启":"关闭").append("\n");
// sb.append("* GPS状态").append(getGPSStatusString(location.getLocationQualityReport().getGPSStatus())).append("\n");
sb.append("* GPS星数").append(location.getLocationQualityReport().getGPSSatellites()).append("\n");
sb.append("* 网络类型:" + location.getLocationQualityReport().getNetworkType()).append("\n");
sb.append("* 网络耗时:" + location.getLocationQualityReport().getNetUseTime()).append("\n");
sb.append("****************").append("\n");
//定位之后的回调时间
sb.append("回调时间: " + Utils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
//解析定位结果,
String result = sb.toString();
// Log.i(TAG, "onLocationChanged: "+"1111111111111111111111111111");
LocationLLLL = "请速来救援"+"\n"+"地点在国防科技大学三号宿舍楼,具体经纬度为:"+location.getProvince() + location.getCity()+location.getDistrict()
+location.getAddress()+location.getStreet()+location.getStreetNum()
+"\n"+"北纬"+location.getLatitude()+"度"+"东经"+location.getLongitude()+"度";
// Intent intent = new Intent();
// intent.putExtra("location",result);
//// startActivity(intent);
// sendBroadcast(intent);
// tvResult.setText(result);
} else {
// tvResult.setText("定位失败loc is null");
Toast.makeText(MainActivity.this,"定位失败",Toast.LENGTH_SHORT).show();
}
}
};
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null) {
boolean isExit = intent.getBooleanExtra(TAG_EXIT, false);
if (isExit) {
this.finish();
}
}
}
/**
* 退
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (mIsExit) {
this.finish();
} else {
Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
mIsExit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mIsExit = false;
}
}, 2000);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
/**
*
*/
private InitListener mTtsInitListener = new InitListener() {
@Override
public void onInit(int code) {
Log.d(TAG, "InitListener init() code = " + code);
if (code != ErrorCode.SUCCESS) {
showTip("初始化失败,错误码:"+code+",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
} else {
// 初始化成功之后可以调用startSpeaking方法
// 注有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成
// 正确的做法是将onCreate中的startSpeaking调用移至这里
}
}
};
/**
*
*/
private SynthesizerListener mTtsListener = new SynthesizerListener() {
@Override
public void onSpeakBegin() {
//showTip("开始播放");
Log.d(MainActivity.TAG,"开始播放:"+ System.currentTimeMillis());
}
@Override
public void onSpeakPaused() {
showTip("暂停播放");
}
@Override
public void onSpeakResumed() {
showTip("继续播放");
}
@Override
public void onBufferProgress(int percent, int beginPos, int endPos,
String info) {
// 合成进度
mPercentForBuffering = percent;
showTip(String.format(getString(R.string.tts_toast_format),
mPercentForBuffering, mPercentForPlaying));
}
@Override
public void onSpeakProgress(int percent, int beginPos, int endPos) {
// 播放进度
mPercentForPlaying = percent;
showTip(String.format(getString(R.string.tts_toast_format),
mPercentForBuffering, mPercentForPlaying));
}
@Override
public void onCompleted(SpeechError error) {
if (error == null) {
showTip("播放完成");
} else if (error != null) {
showTip(error.getPlainDescription(true));
}
}
@Override
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
// 以下代码用于获取与云端的会话id当业务出错时将会话id提供给技术支持人员可用于查询会话日志定位出错原因
// 若使用本地能力会话id为null
if (SpeechEvent.EVENT_SESSION_ID == eventType) {
String sid = obj.getString(SpeechEvent.KEY_EVENT_AUDIO_URL);
Log.d(TAGS, "session id =" + sid);
}
//实时音频流输出参考
/*if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {
byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);
Log.e("MscSpeechLog", "buf is =" + buf);
}*/
}
};
/**
*
*/
private void setParam(){
// 清空参数
mTts.setParameter(SpeechConstant.PARAMS, null);
//设置合成
if(mEngineType.equals(SpeechConstant.TYPE_CLOUD))
{
//设置使用云端引擎
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
//设置发音人
mTts.setParameter(SpeechConstant.VOICE_NAME,voicerCloud);
}else if(mEngineType.equals(SpeechConstant.TYPE_LOCAL)){
//设置使用本地引擎
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
//设置发音人资源路径
mTts.setParameter(ResourceUtil.TTS_RES_PATH,getResourcePath());
//设置发音人
mTts.setParameter(SpeechConstant.VOICE_NAME,voicerLocal);
}else{
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_XTTS);
//设置发音人资源路径
mTts.setParameter(ResourceUtil.TTS_RES_PATH,getResourcePath());
//设置发音人
mTts.setParameter(SpeechConstant.VOICE_NAME,voicerXtts);
}
//mTts.setParameter(SpeechConstant.TTS_DATA_NOTIFY,"1");//支持实时音频流抛出仅在synthesizeToUri条件下支持
//设置合成语速
mTts.setParameter(SpeechConstant.SPEED, mSharedPreferences.getString("speed_preference", "50"));
//设置合成音调
mTts.setParameter(SpeechConstant.PITCH, mSharedPreferences.getString("pitch_preference", "50"));
//设置合成音量
mTts.setParameter(SpeechConstant.VOLUME, mSharedPreferences.getString("volume_preference", "50"));
//设置播放器音频流类型
mTts.setParameter(SpeechConstant.STREAM_TYPE, mSharedPreferences.getString("stream_preference", "3"));
// mTts.setParameter(SpeechConstant.STREAM_TYPE, AudioManager.STREAM_MUSIC+"");
// 设置播放合成音频打断音乐播放默认为true
mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
// 设置音频保存路径保存音频格式支持pcm、wav设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/tts.wav");
}
//获取发音人资源路径
private String getResourcePath(){
StringBuffer tempBuffer = new StringBuffer();
String type= "tts";
if(mEngineType.equals(SpeechConstant.TYPE_XTTS)){
type="xtts";
}
//合成通用资源
tempBuffer.append(ResourceUtil.generateResourcePath(this, ResourceUtil.RESOURCE_TYPE.assets, type+"/common.jet"));
tempBuffer.append(";");
//发音人资源
if(mEngineType.equals(SpeechConstant.TYPE_XTTS)){
tempBuffer.append(ResourceUtil.generateResourcePath(this, ResourceUtil.RESOURCE_TYPE.assets, type+"/"+ TtsDemo.voicerXtts+".jet"));
}else {
tempBuffer.append(ResourceUtil.generateResourcePath(this, ResourceUtil.RESOURCE_TYPE.assets, type + "/" + TtsDemo.voicerLocal + ".jet"));
}
return tempBuffer.toString();
}
@Override
protected void onDestroy() {
super.onDestroy();
if( null != mTts ){
mTts.stopSpeaking();
// 退出时释放连接
mTts.destroy();
}
}
}

@ -0,0 +1,61 @@
package com.example.luyin.activities;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
public class MyApplication extends Application {
private int count = 0;
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
count ++;
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
if(count > 0) {
count--;
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
/**
* app
* @return
*/
public boolean isBackground(){
if(count <= 0){
return true;
} else {
return false;
}
}
}

@ -0,0 +1,60 @@
package com.example.luyin.activities;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.Toast;
import com.example.luyin.R;
public class SMS extends Activity {
private EditText mNumberText;
private EditText mContentText;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(getString(R.string.app_name));
setContentView(R.layout.activity_sms);
mNumberText = (EditText)this.findViewById(R.id.number);//找到number
mContentText = (EditText)this.findViewById(R.id.msg_content);
}
public void SEND(View view) {
//String content = mContentText.getText().toString();
//String number = mNumberText.getText().toString();
String content = "尼玛1111111111111111";
String number = "18577348433";
if(TextUtils.isEmpty(number)){
showToast("请输入手机号");
return;
}
if(TextUtils.isEmpty(content)){
showToast("请输入内容");
return;
}
ArrayList<String> messages = SmsManager.getDefault().divideMessage(content);
for(String text : messages){
SmsManager.getDefault().sendTextMessage(number, null, text, null, null);
}
showToast("success");
}
private void showToast(String msg) {
Toast.makeText(SMS.this, msg, Toast.LENGTH_LONG).show();
}
}

@ -0,0 +1,431 @@
package com.example.luyin.activities;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
import com.example.luyin.speech.setting.TtsSettings;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;
import com.example.luyin.R;
//import com.iflytek.cloud.param.MscKeys;
public class TtsDemo extends Activity implements OnClickListener {
private static String TAG = TtsDemo.class.getSimpleName();
// 语音合成对象
private SpeechSynthesizer mTts;
// 默认云端发音人
public static String voicerCloud="xiaoyan";
// 默认本地发音人
public static String voicerLocal="xiaoyan";
public static String voicerXtts="xiaoyan";
// 云端发音人列表
private String[] cloudVoicersEntries;
private String[] cloudVoicersValue ;
// 本地发音人列表
private String[] localVoicersEntries;
private String[] localVoicersValue ;
// 增强版发音人列表
private String[] xttsVoicersEntries;
private String[] xttsVoicersValue;
//缓冲进度
private int mPercentForBuffering = 0;
//播放进度
private int mPercentForPlaying = 0;
// 云端/本地选择按钮
private RadioGroup mRadioGroup;
// 引擎类型
private String mEngineType = SpeechConstant.TYPE_CLOUD;
private Toast mToast;
private SharedPreferences mSharedPreferences;
@SuppressLint("ShowToast")
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.ttsdemo);
initLayout();
// 初始化合成对象
mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);
// 云端发音人名称列表
cloudVoicersEntries = getResources().getStringArray(R.array.voicer_cloud_entries);
cloudVoicersValue = getResources().getStringArray(R.array.voicer_cloud_values);
// 本地发音人名称列表
localVoicersEntries = getResources().getStringArray(R.array.voicer_local_entries);
localVoicersValue = getResources().getStringArray(R.array.voicer_local_values);
// 增强版发音人名称列表
xttsVoicersEntries = getResources().getStringArray(R.array.voicer_xtts_entries);
xttsVoicersValue = getResources().getStringArray(R.array.voicer_xtts_values);
mSharedPreferences = getSharedPreferences(TtsSettings.PREFER_NAME, Activity.MODE_PRIVATE);
mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT);
}
/**
* Layout
*/
private void initLayout() {
findViewById(R.id.tts_play).setOnClickListener(this);
findViewById(R.id.tts_cancel).setOnClickListener(this);
findViewById(R.id.tts_pause).setOnClickListener(this);
findViewById(R.id.tts_resume).setOnClickListener(this);
findViewById(R.id.image_tts_set).setOnClickListener(this);
findViewById(R.id.tts_btn_person_select).setOnClickListener(this);
mRadioGroup=((RadioGroup) findViewById(R.id.tts_rediogroup));
mRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.tts_radioCloud:
mEngineType = SpeechConstant.TYPE_CLOUD;
break;
case R.id.tts_radioLocal:
mEngineType = SpeechConstant.TYPE_LOCAL;
break;
case R.id.tts_radioXtts:
mEngineType = SpeechConstant.TYPE_XTTS;
break;
default:
break;
}
}
} );
}
@Override
public void onClick(View view) {
if( null == mTts ){
// 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
this.showTip( "创建对象失败,请确认 libmsc.so 放置正确,\n 且有调用 createUtility 进行初始化" );
return;
}
switch(view.getId()) {
case R.id.image_tts_set:
Intent intent = new Intent(TtsDemo.this, TtsSettings.class);
startActivity(intent);
break;
// 开始合成
// 收到onCompleted 回调时,合成结束、生成合成音频
// 合成的音频格式只支持pcm格式
case R.id.tts_play:
//会话内容在这修改
//String text = ((EditText) findViewById(R.id.tts_text)).getText().toString();
String text = ((EditText) findViewById(R.id.tts_text)).getText().toString();
// 设置参数
setParam();
Log.d(TAG,"准备点击: "+ System.currentTimeMillis());
int code = mTts.startSpeaking(text, mTtsListener);
// /**
// * 只保存音频不进行播放接口,调用此接口请注释startSpeaking接口
// * text:要合成的文本uri:需要保存的音频全路径listener:回调接口
// */
// String path = Environment.getExternalStorageDirectory()+"/tts.pcm";
// int code = mTts.synthesizeToUri(text, path, mTtsListener);
if (code != ErrorCode.SUCCESS) {
showTip("语音合成失败,错误码: " + code+",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
}
break;
// 取消合成
case R.id.tts_cancel:
mTts.stopSpeaking();
break;
// 暂停播放
case R.id.tts_pause:
mTts.pauseSpeaking();
break;
// 继续播放
case R.id.tts_resume:
mTts.resumeSpeaking();
break;
// 选择发音人
case R.id.tts_btn_person_select:
showPresonSelectDialog();
break;
}
}
private static int selectedNumCloud=0;
private static int selectedNumLocal=0;
/**
*
*/
private void showPresonSelectDialog() {
switch (mRadioGroup.getCheckedRadioButtonId()) {
// 选择在线合成
case R.id.tts_radioCloud:
new AlertDialog.Builder(this).setTitle("在线合成发音人选项")
.setSingleChoiceItems(cloudVoicersEntries, // 单选框有几项,各是什么名字
selectedNumCloud, // 默认的选项
new DialogInterface.OnClickListener() { // 点击单选框后的处理
public void onClick(DialogInterface dialog,
int which) { // 点击了哪一项
voicerCloud = cloudVoicersValue[which];
if ("catherine".equals(voicerCloud) || "henry".equals(voicerCloud) || "vimary".equals(voicerCloud)) {
((EditText) findViewById(R.id.tts_text)).setText(R.string.text_tts_source_en);
}else {
((EditText) findViewById(R.id.tts_text)).setText(R.string.text_tts_source);
}
selectedNumCloud = which;
dialog.dismiss();
}
}).show();
break;
// 选择本地合成
case R.id.tts_radioLocal:
new AlertDialog.Builder(this).setTitle("本地合成发音人选项")
.setSingleChoiceItems(localVoicersEntries, // 单选框有几项,各是什么名字
selectedNumLocal, // 默认的选项
new DialogInterface.OnClickListener() { // 点击单选框后的处理
public void onClick(DialogInterface dialog,
int which) { // 点击了哪一项
voicerLocal = localVoicersValue[which];
if ("catherine".equals(voicerLocal) || "henry".equals(voicerLocal) || "vimary".equals(voicerLocal)) {
((EditText) findViewById(R.id.tts_text)).setText(R.string.text_tts_source_en);
}else {
((EditText) findViewById(R.id.tts_text)).setText(R.string.text_tts_source);
}
selectedNumLocal = which;
dialog.dismiss();
}
}).show();
break;
case R.id.tts_radioXtts:
new AlertDialog.Builder(this).setTitle("增强版合成发音人选项")
.setSingleChoiceItems(xttsVoicersEntries, // 单选框有几项,各是什么名字
selectedNumLocal, // 默认的选项
new DialogInterface.OnClickListener() { // 点击单选框后的处理
public void onClick(DialogInterface dialog,
int which) { // 点击了哪一项
voicerXtts = xttsVoicersValue[which];
//Toast.makeText(this,voicerXtts,Toast.LENGTH_LONG);
System.out.println("sssssss:"+voicerXtts);
if ("catherine".equals(voicerXtts) || "henry".equals(voicerXtts) || "vimary".equals(voicerXtts)) {
((EditText) findViewById(R.id.tts_text)).setText(R.string.text_tts_source_en);
}else {
((EditText) findViewById(R.id.tts_text)).setText(R.string.text_tts_source);
}
selectedNumLocal = which;
dialog.dismiss();
}
}).show();
break;
default:
break;
}
}
/**
*
*/
private InitListener mTtsInitListener = new InitListener() {
@Override
public void onInit(int code) {
Log.d(TAG, "InitListener init() code = " + code);
if (code != ErrorCode.SUCCESS) {
showTip("初始化失败,错误码:"+code+",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
} else {
// 初始化成功之后可以调用startSpeaking方法
// 注有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成
// 正确的做法是将onCreate中的startSpeaking调用移至这里
}
}
};
/**
*
*/
private SynthesizerListener mTtsListener = new SynthesizerListener() {
@Override
public void onSpeakBegin() {
//showTip("开始播放");
Log.d(TtsDemo.TAG,"开始播放:"+ System.currentTimeMillis());
}
@Override
public void onSpeakPaused() {
showTip("暂停播放");
}
@Override
public void onSpeakResumed() {
showTip("继续播放");
}
@Override
public void onBufferProgress(int percent, int beginPos, int endPos,
String info) {
// 合成进度
mPercentForBuffering = percent;
showTip(String.format(getString(R.string.tts_toast_format),
mPercentForBuffering, mPercentForPlaying));
}
@Override
public void onSpeakProgress(int percent, int beginPos, int endPos) {
// 播放进度
mPercentForPlaying = percent;
showTip(String.format(getString(R.string.tts_toast_format),
mPercentForBuffering, mPercentForPlaying));
}
@Override
public void onCompleted(SpeechError error) {
if (error == null) {
showTip("播放完成");
} else if (error != null) {
showTip(error.getPlainDescription(true));
}
}
@Override
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
// 以下代码用于获取与云端的会话id当业务出错时将会话id提供给技术支持人员可用于查询会话日志定位出错原因
// 若使用本地能力会话id为null
if (SpeechEvent.EVENT_SESSION_ID == eventType) {
String sid = obj.getString(SpeechEvent.KEY_EVENT_AUDIO_URL);
Log.d(TAG, "session id =" + sid);
}
//实时音频流输出参考
/*if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {
byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);
Log.e("MscSpeechLog", "buf is =" + buf);
}*/
}
};
private void showTip(final String str){
runOnUiThread(new Runnable() {
@Override
public void run() {
mToast.setText(str);
mToast.show();
}
});
}
/**
*
*/
private void setParam(){
// 清空参数
mTts.setParameter(SpeechConstant.PARAMS, null);
//设置合成
if(mEngineType.equals(SpeechConstant.TYPE_CLOUD))
{
//设置使用云端引擎
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
//设置发音人
mTts.setParameter(SpeechConstant.VOICE_NAME,voicerCloud);
}else if(mEngineType.equals(SpeechConstant.TYPE_LOCAL)){
//设置使用本地引擎
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
//设置发音人资源路径
mTts.setParameter(ResourceUtil.TTS_RES_PATH,getResourcePath());
//设置发音人
mTts.setParameter(SpeechConstant.VOICE_NAME,voicerLocal);
}else{
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_XTTS);
//设置发音人资源路径
mTts.setParameter(ResourceUtil.TTS_RES_PATH,getResourcePath());
//设置发音人
mTts.setParameter(SpeechConstant.VOICE_NAME,voicerXtts);
}
//mTts.setParameter(SpeechConstant.TTS_DATA_NOTIFY,"1");//支持实时音频流抛出仅在synthesizeToUri条件下支持
//设置合成语速
mTts.setParameter(SpeechConstant.SPEED, mSharedPreferences.getString("speed_preference", "50"));
//设置合成音调
mTts.setParameter(SpeechConstant.PITCH, mSharedPreferences.getString("pitch_preference", "50"));
//设置合成音量
mTts.setParameter(SpeechConstant.VOLUME, mSharedPreferences.getString("volume_preference", "50"));
//设置播放器音频流类型
mTts.setParameter(SpeechConstant.STREAM_TYPE, mSharedPreferences.getString("stream_preference", "3"));
// mTts.setParameter(SpeechConstant.STREAM_TYPE, AudioManager.STREAM_MUSIC+"");
// 设置播放合成音频打断音乐播放默认为true
mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
// 设置音频保存路径保存音频格式支持pcm、wav设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/tts.wav");
}
//获取发音人资源路径
private String getResourcePath(){
StringBuffer tempBuffer = new StringBuffer();
String type= "tts";
if(mEngineType.equals(SpeechConstant.TYPE_XTTS)){
type="xtts";
}
//合成通用资源
tempBuffer.append(ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, type+"/common.jet"));
tempBuffer.append(";");
//发音人资源
if(mEngineType.equals(SpeechConstant.TYPE_XTTS)){
tempBuffer.append(ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, type+"/"+ TtsDemo.voicerXtts+".jet"));
}else {
tempBuffer.append(ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, type + "/" + TtsDemo.voicerLocal + ".jet"));
}
return tempBuffer.toString();
}
@Override
protected void onDestroy() {
super.onDestroy();
if( null != mTts ){
mTts.stopSpeaking();
// 退出时释放连接
mTts.destroy();
}
}
}

@ -0,0 +1,155 @@
package com.example.luyin.activities;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import com.example.luyin.R;
import com.example.luyin.activities.TtsDemo;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechUtility;
public class VoiceActivity extends Activity implements OnClickListener{
private Toast mToast;
@SuppressLint("ShowToast")
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// 设置标题栏(无标题)
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
requestPermissions();
mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT);
SimpleAdapter listitemAdapter = new SimpleAdapter();
((ListView)findViewById(R.id.listview_main)).setAdapter(listitemAdapter);
StringBuffer param = new StringBuffer();
param.append("appid="+getString(R.string.app_id));
param.append(",");
// 设置使用v5+
param.append(SpeechConstant.ENGINE_MODE+"="+ SpeechConstant.MODE_MSC);
SpeechUtility.createUtility(VoiceActivity.this, param.toString());
}
@Override
public void onClick(View view) {
int tag = Integer.parseInt(view.getTag().toString());
Intent intent = null;
switch (tag) {
case 0:
// 语音听写
showTip("这个功能写不出来!");
break;
case 1:
// 语法识别
showTip("这个功能写不出来!");
break;
case 2:
// 语义理解
showTip("这个功能写不出来!");
break;
case 3 :
case 4:
// 合成(包括增强版)
intent = new Intent(this, TtsDemo.class);
break;
case 5:
// 唤醒
showTip("这个功能写不出来!");
break;
case 6:
// 声纹
showTip("这个功能写不出来!");
break;
default:
showTip("这个功能写不出来!");
break;
}
if (intent != null) {
startActivity(intent);
}
}
//Menu 列表
String items[] = {"立刻体验语音听写","立刻体验语法识别","立刻体验语义理解","立刻体验语音合成","立即体验增强版语音合成","立刻体验语音唤醒","立刻体验声纹密码"};
private class SimpleAdapter extends BaseAdapter{
public View getView(int position, View convertView, ViewGroup parent)
{
if(null == convertView){
LayoutInflater factory = LayoutInflater.from(VoiceActivity.this);
View mView = factory.inflate(R.layout.list_items, null);
convertView = mView;
}
Button btn = (Button)convertView.findViewById(R.id.btn);
btn.setOnClickListener(VoiceActivity.this);
btn.setTag(position);
btn.setText(items[position]);
return convertView;
}
@Override
public int getCount() {
return items.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
private void showTip(final String str)
{
runOnUiThread(new Runnable() {
@Override
public void run() {
mToast.setText(str);
mToast.show();
}
});
}
private void requestPermissions(){
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int permission = ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if(permission!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[] {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.LOCATION_HARDWARE,Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_SETTINGS,Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO,Manifest.permission.READ_CONTACTS},0x0010);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

@ -0,0 +1,426 @@
package com.example.luyin.activities;
import androidx.appcompat.app.AppCompatActivity;
import android.accessibilityservice.AccessibilityService;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.os.Bundle;
import android.os.Vibrator;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.widget.Toast;
import com.example.luyin.wechat.Constants;
import com.example.luyin.R;
import com.example.luyin.wechat.service.utils.SendMessage;
import com.example.luyin.wechat.service.RedEnvelopeService;
import com.example.luyin.wechat.utils.AccessibilityUtil;
import com.example.luyin.wechat.utils.AppUtil;
import java.util.Calendar;
public class Wechat extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemSelectedListener, SensorEventListener {
public static Context AppContext;
public static Context WeChatContext;
public static int Width;
public static int Height;
private static AccessibilityService CurrentService;
public long lastTime = 0;
public long timeDifference = 1000;
private Switch OpenService;
private Switch AutoWeChat;
private Switch AutoSendMsg;
private LinearLayout SendMsgDetail;
private TextView VersionView;
private EditText ToWho;
private EditText WhatMsg;
private Button SendMsgBtn;
private Button InitFriend;
//下拉列表
private Spinner FriendList;
//传感器
private SensorManager sensorManager;
//震动
private Vibrator mVibrator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.autowechat);
init();
initWeChatVersion();
// if(OpenService.isChecked()){
// System.out.println("click");
// SendMessage.NAME = ToWho.getText().toString();
// SendMessage.CONTENT = WhatMsg.getText().toString();
// Constants.CurrentTask = Constants.AutoSendMsgType;
// gotoWeChat();
// } else{
// AppUtil.makeToast("请先打开辅助功能");
// openAccessibility();
// }
}
@Override
protected void onStart() {
super.onStart();
freshOpenServiceSwitch(RedEnvelopeService.class, OpenService);
initList();
}
private void initWeChatVersion(){
Context weChat = AppUtil.getContext(this, Constants.WeChatInfo.WECHAT_PACKAGE);
WeChatContext = weChat;
if(weChat != null){
String weChatVersion = AppUtil.getAppVersion(weChat);
System.out.println(weChatVersion);
Constants.setArgs(weChatVersion);
}
}
private void init(){
AppContext = this;
initScreen();
//initVersion();
SendMsgDetail = findViewById(R.id.send_msg_detail);
SendMsgDetail.clearAnimation();
OpenService = findViewById(R.id.open_accessibility);
setOpenServiceListener(RedEnvelopeService.class, OpenService);
// AutoWeChat = findViewById(R.id.open_we_chat);
// setSwitchListener(AutoWeChat);
AutoSendMsg = findViewById(R.id.auto_send_msg);
setSwitchListener(AutoSendMsg);
//freshOpenServiceSwitch(RedEnvelopeService.class, OpenService);
ToWho = findViewById(R.id.send_name);
WhatMsg = findViewById(R.id.send_msg);
SendMsgBtn = findViewById(R.id.send_WeChat);
SendMsgBtn.setOnClickListener(this);
InitFriend = findViewById(R.id.init_friend_btn);
InitFriend.setOnClickListener(this);
FriendList = findViewById(R.id.friend_list);
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
mVibrator=(Vibrator) getSystemService(VIBRATOR_SERVICE);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
if (Math.abs(event.values[0]) > 20|| Math.abs(event.values[1]) > 20 || Math.abs(event.values[2]) > 20) {
long currentTime = Calendar.getInstance().getTimeInMillis();
if (currentTime - lastTime > timeDifference) {
lastTime = currentTime;
//mVibrator.vibrate(100);
//callPhone(phonenum);
Toast.makeText(Wechat.this,"123",Toast.LENGTH_LONG).show();
if(OpenService.isChecked()){
System.out.println("click");
SendMessage.NAME = ToWho.getText().toString();
SendMessage.CONTENT = WhatMsg.getText().toString();
Constants.CurrentTask = Constants.AutoSendMsgType;
gotoWeChat();
} else{
AppUtil.makeToast("请先打开辅助功能");
openAccessibility();
}
}
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.send_WeChat:
if(OpenService.isChecked()){
System.out.println("click");
SendMessage.NAME = ToWho.getText().toString();
SendMessage.CONTENT = WhatMsg.getText().toString();
Constants.CurrentTask = Constants.AutoSendMsgType;
gotoWeChat();
} else{
AppUtil.makeToast("请先打开辅助功能");
openAccessibility();
}
break;
case R.id.init_friend_btn:
if(OpenService.isChecked()){
Constants.CurrentTask = Constants.InitFriendList;
gotoWeChat();
}else {
AppUtil.makeToast("请先打开辅助功能");
openAccessibility();
}
break;
}
}
private void gotoWeChat(){
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName(Constants.WeChatInfo.WECHAT_PACKAGE, Constants.WeChatInfo.WECHAT_LAUNCHER_UI);
startActivity(intent);
}
public static void performHome(AccessibilityService service) {
if (service == null) {
return;
}
service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}
private void initList(){
if(Constants.FriendList == null) return;
System.out.println(Constants.FriendList);
FriendList.setAdapter(new ArrayAdapter<>(this, R.layout.spinner_item, Constants.FriendList));
FriendList.setOnItemSelectedListener(this);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
System.out.println(Constants.FriendList.get(position));
ToWho.setText(Constants.FriendList.get(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
private void setOpenServiceListener(final Class clazz, Switch s){
s.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.i(Constants.TAG, "onCheckedChanged: " + isChecked);
if(isChecked){
if(!isAccessibilitySettingOn(clazz.getCanonicalName(), AppContext)){
openAccessibility();
}
}else {
if(isAccessibilitySettingOn(clazz.getCanonicalName(), AppContext)){
openAccessibility();
}
}
}
});
}
private void setSwitchListener(final Switch s){
s.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
freshSwitch(s);
}else {
freshSwitch(s);
}
}
});
}
// private void initVersion(){
// VersionView = findViewById(R.id.app_version);
// String version = AppUtil.getAppVersion(this);
// VersionView.setText(version);
// }
//重置服务按钮
private void freshOpenServiceSwitch(Class clazz, Switch s){
if(isAccessibilitySettingOn(clazz.getCanonicalName(), Wechat.this)){
s.setChecked(true);
switch (s.getId()){
case R.id.open_accessibility:
//freshSwitch(AutoWeChat);
freshSwitch(AutoSendMsg);
}
}else {
s.setChecked(false);
switch (s.getId()){
case R.id.open_accessibility:
AutoSendMsg.setChecked(true);
//AutoWeChat.setChecked(false);
}
}
SendMsgDetail.setVisibility(View.VISIBLE);
}
//点击自动发送消息按钮,弹出详细发送界面,需要先点击开启辅助功能,否则打不开
private void freshSwitch(Switch s){
//if(OpenService.isChecked()) {
if(Constants.CurrentTask == Constants.InitFriendList){
Constants.CurrentTask = -1;
}
switch (s.getId()){
// case R.id.open_we_chat:
// if(s.isChecked()){
// if(Constants.IsOver){
// s.setChecked(false);
// Constants.IsOver = false;
// break;
// }else if(AutoSendMsg.isChecked()){
// AutoSendMsg.setChecked(false);
// SendMsgDetail.setVisibility(View.GONE);
// }
// Constants.CurrentTask = Constants.RedEnvelopeType;
// }else {
// Constants.CurrentTask = -1;
// }
// break;
case R.id.auto_send_msg:
//if(OpenService.isChecked()) {
if (s.isChecked()) {
if (Constants.IsOver) {
s.setChecked(false);
Constants.IsOver = false;
break;
}
//}else if(AutoWeChat.isChecked()){
//AutoWeChat.setChecked(false);
//}
if (s.isChecked()) {
SendMsgDetail.setVisibility(View.VISIBLE);
}
} else {
SendMsgDetail.setVisibility(View.GONE);
Constants.CurrentTask = -1;
}
// }
break;
default:
break;
}
// }else {
// AppUtil.makeToast("请先打开辅助功能");
// // s.setChecked(false);
// }
}
private boolean isAccessibilitySettingOn(String accessibilityServiceName, Context context){
int enable = 0;
String serviceName = context.getPackageName() + "/" + accessibilityServiceName;
Log.i(Constants.TAG, "isAccessibilitySettingOn: " + serviceName);
try {
enable = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0);
} catch (Exception e) {
e.printStackTrace();
}
if(enable == 1){
TextUtils.SimpleStringSplitter stringSplitter = new TextUtils.SimpleStringSplitter(':');
String settingVal = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if(settingVal != null){
stringSplitter.setString(settingVal);
while(stringSplitter.hasNext()){
String accessibilityService = stringSplitter.next();
if(accessibilityService.equals(serviceName)){
return true;
}
}
}
}
return false;
}
//打开系统设置
private void openAccessibility(){
DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(intent);
}
};
DialogInterface.OnClickListener cancelListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
freshOpenServiceSwitch(RedEnvelopeService.class, OpenService);
}
};
DialogInterface.OnCancelListener cancel = new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
freshOpenServiceSwitch(RedEnvelopeService.class, OpenService);
}
};
AlertDialog dialog = new AlertDialog.Builder(this)
.setMessage(R.string.tips)
.setOnCancelListener(cancel)
.setNegativeButton("取消", cancelListener)
.setPositiveButton("确定", clickListener)
.create();
dialog.show();
}
private void initScreen(){
WindowManager manager = this.getWindowManager();
DisplayMetrics metrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(metrics);
Width = metrics.widthPixels;
Height = metrics.heightPixels;
}
// @Override
// public boolean onKeyDown(int keyCode, KeyEvent event) {
// if(keyCode == KeyEvent.KEYCODE_BACK){
// moveTaskToBack(true);
// return true;
// }
// return super.onKeyDown(keyCode, event);
// }
// @Override
// public void onBackPressed() {
// moveTaskToBack(true);
// }
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
}

@ -0,0 +1,22 @@
package com.example.luyin.services;
import cn.bmob.v3.BmobObject;
public class EmergencyPeople extends BmobObject {
private String name;
private String phoneNumber;
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber=phoneNumber;
}
}

@ -0,0 +1,21 @@
package com.example.luyin.services;
import cn.bmob.v3.BmobObject;
public class Location extends BmobObject{
private String name;
private String address;
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

@ -0,0 +1,39 @@
package com.example.luyin.speech.setting;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.view.Window;
import com.example.luyin.R;
import com.example.luyin.speech.util.SettingTextWatcher;
/**
*
*/
public class IatSettings extends PreferenceActivity implements OnPreferenceChangeListener {
public static final String PREFER_NAME = "com.iflytek.setting";
private EditTextPreference mVadbosPreference;
private EditTextPreference mVadeosPreference;
@SuppressWarnings("deprecation")
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
getPreferenceManager().setSharedPreferencesName(PREFER_NAME);
addPreferencesFromResource(R.xml.iat_setting);
mVadbosPreference = (EditTextPreference)findPreference("iat_vadbos_preference");
mVadbosPreference.getEditText().addTextChangedListener(new SettingTextWatcher(IatSettings.this,mVadbosPreference,0,10000));
mVadeosPreference = (EditTextPreference)findPreference("iat_vadeos_preference");
mVadeosPreference.getEditText().addTextChangedListener(new SettingTextWatcher(IatSettings.this,mVadeosPreference,0,10000));
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
}

@ -0,0 +1,49 @@
package com.example.luyin.speech.setting;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.view.Window;
import com.example.luyin.R;
import com.example.luyin.speech.util.SettingTextWatcher;
/**
*
*/
public class TtsSettings extends PreferenceActivity implements OnPreferenceChangeListener {
public static final String PREFER_NAME = "com.iflytek.setting";
private EditTextPreference mSpeedPreference;
private EditTextPreference mPitchPreference;
private EditTextPreference mVolumePreference;
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
// 指定保存文件名字
getPreferenceManager().setSharedPreferencesName(PREFER_NAME);
addPreferencesFromResource(R.xml.tts_setting);
mSpeedPreference = (EditTextPreference)findPreference("speed_preference");
mSpeedPreference.getEditText().addTextChangedListener(new SettingTextWatcher(TtsSettings.this,mSpeedPreference,0,200));
mPitchPreference = (EditTextPreference)findPreference("pitch_preference");
mPitchPreference.getEditText().addTextChangedListener(new SettingTextWatcher(TtsSettings.this,mPitchPreference,0,100));
mVolumePreference = (EditTextPreference)findPreference("volume_preference");
mVolumePreference.getEditText().addTextChangedListener(new SettingTextWatcher(TtsSettings.this,mVolumePreference,0,100));
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
}

@ -0,0 +1,56 @@
package com.example.luyin.speech.util;
import android.content.Context;
import java.io.IOException;
import java.io.InputStream;
/**
*
*/
public class FucUtil {
/**
* asset
* @return content
*/
public static String readFile(Context mContext,String file,String code)
{
int len = 0;
byte []buf = null;
String result = "";
try {
InputStream in = mContext.getAssets().open(file);
len = in.available();
buf = new byte[len];
in.read(buf, 0, len);
result = new String(buf,code);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* asset
*
* @return
*/
public static byte[] readAudioFile(Context context, String filename) {
try {
InputStream ins = context.getAssets().open(filename);
byte[] data = new byte[ins.available()];
ins.read(data);
ins.close();
return data;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}

@ -0,0 +1,147 @@
package com.example.luyin.speech.util;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
/**
* Json
*/
public class JsonParser {
public static String parseIatResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
// 转写结果词,默认使用第一个结果
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
JSONObject obj = items.getJSONObject(0);
ret.append(obj.getString("w"));
// 如果需要多候选结果,解析数组其他字段
// for(int j = 0; j < items.length(); j++)
// {
// JSONObject obj = items.getJSONObject(j);
// ret.append(obj.getString("w"));
// }
}
} catch (Exception e) {
e.printStackTrace();
}
return ret.toString();
}
public static String parseGrammarResult(String json, String engType) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
// 云端和本地结果分情况解析
if ("cloud".equals(engType)) {
for (int i = 0; i < words.length(); i++) {
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
for(int j = 0; j < items.length(); j++)
{
JSONObject obj = items.getJSONObject(j);
if(obj.getString("w").contains("nomatch"))
{
ret.append("没有匹配结果.");
return ret.toString();
}
ret.append("【结果】" + obj.getString("w"));
ret.append("【置信度】" + obj.getInt("sc"));
ret.append("\n");
}
}
} else if ("local".equals(engType)) {
ret.append("【结果】");
for (int i = 0; i < words.length(); i++) {
JSONObject wsItem = words.getJSONObject(i);
JSONArray items = wsItem.getJSONArray("cw");
if ("<contact>".equals(wsItem.getString("slot"))) {
// 可能会有多个联系人供选择,用中括号括起来,这些候选项具有相同的置信度
ret.append("【");
for(int j = 0; j < items.length(); j++)
{
JSONObject obj = items.getJSONObject(j);
if(obj.getString("w").contains("nomatch"))
{
ret.append("没有匹配结果.");
return ret.toString();
}
ret.append(obj.getString("w")).append("|");
}
ret.setCharAt(ret.length() - 1, '】');
} else {
//本地多候选按照置信度高低排序,一般选取第一个结果即可
JSONObject obj = items.getJSONObject(0);
if(obj.getString("w").contains("nomatch"))
{
ret.append("没有匹配结果.");
return ret.toString();
}
ret.append(obj.getString("w"));
}
}
ret.append("【置信度】" + joResult.getInt("sc"));
ret.append("\n");
}
} catch (Exception e) {
e.printStackTrace();
ret.append("没有匹配结果.");
}
return ret.toString();
}
public static String parseGrammarResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
for(int j = 0; j < items.length(); j++)
{
JSONObject obj = items.getJSONObject(j);
if(obj.getString("w").contains("nomatch"))
{
ret.append("没有匹配结果.");
return ret.toString();
}
ret.append("【结果】" + obj.getString("w"));
ret.append("【置信度】" + obj.getInt("sc"));
ret.append("\n");
}
}
} catch (Exception e) {
e.printStackTrace();
ret.append("没有匹配结果.");
}
return ret.toString();
}
public static String parseTransResult(String json,String key) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
String errorCode = joResult.optString("ret");
if(!errorCode.equals("0")) {
return joResult.optString("errmsg");
}
JSONObject transResult = joResult.optJSONObject("trans_result");
ret.append(transResult.optString(key));
} catch (Exception e) {
e.printStackTrace();
}
return ret.toString();
}
}

@ -0,0 +1,71 @@
package com.example.luyin.speech.util;
import android.content.Context;
import android.preference.EditTextPreference;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.widget.Toast;
import java.util.regex.Pattern;
/**
*
*/
public class SettingTextWatcher implements TextWatcher {
private int editStart ;
private int editCount ;
private EditTextPreference mEditTextPreference;
int minValue;//最小值
int maxValue;//最大值
private Context mContext;
public SettingTextWatcher(Context context,EditTextPreference e,int min, int max) {
mContext = context;
mEditTextPreference = e;
minValue = min;
maxValue = max;
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Log.e("demo", "onTextChanged start:"+start+" count:"+count+" before:"+before);
editStart = start;
editCount = count;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
// Log.e("demo", "beforeTextChanged start:"+start+" count:"+count+" after:"+after);
}
@Override
public void afterTextChanged(Editable s) {
if (TextUtils.isEmpty(s)) {
return;
}
String content = s.toString();
// Log.e("demo", "content:"+content);
if (isNumeric(content)) {
int num = Integer.parseInt(content);
if (num > maxValue || num < minValue) {
s.delete(editStart, editStart+editCount);
mEditTextPreference.getEditText().setText(s);
Toast.makeText(mContext, "超出有效值范围", Toast.LENGTH_SHORT).show();
}
}else {
s.delete(editStart, editStart+editCount);
mEditTextPreference.getEditText().setText(s);
Toast.makeText(mContext, "只能输入数字哦", Toast.LENGTH_SHORT).show();
}
}
/**
* -
*/
public static boolean isNumeric(String str){
Pattern pattern = Pattern.compile("[0-9]*");
return pattern.matcher(str).matches();
}
};

@ -0,0 +1,58 @@
package com.example.luyin.speech.util;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
/**
* Xml
*/
public class XmlParser {
public static String parseNluResult(String xml)
{
StringBuffer buffer = new StringBuffer();
try
{
// DOM builder
DocumentBuilder domBuilder = null;
// DOM doc
Document domDoc = null;
// init DOM
DocumentBuilderFactory domFact = DocumentBuilderFactory.newInstance();
domBuilder = domFact.newDocumentBuilder();
InputStream is = new ByteArrayInputStream(xml.getBytes());
domDoc = domBuilder.parse(is);
// 获取根节点
Element root = (Element) domDoc.getDocumentElement();
Element raw = (Element)root.getElementsByTagName("rawtext").item(0);
buffer.append("【识别结果】" + raw.getFirstChild().getNodeValue());
buffer.append("\n");
Element e = (Element)root.getElementsByTagName("result").item(0);
Element focus = (Element)e.getElementsByTagName("focus").item(0);
buffer.append("【FOCUS】" + focus.getFirstChild().getNodeValue());
buffer.append("\n");
Element action = (Element)e.getElementsByTagName("action").item(0);
Element operation = (Element)action.getElementsByTagName("operation").item(0);
buffer.append("【ACTION】" + operation.getFirstChild().getNodeValue());
buffer.append("\n");
}catch(Exception e){
e.printStackTrace();
};
buffer.append("【ALL】" + xml);
return buffer.toString();
}
}

@ -0,0 +1,115 @@
/**
*
*/
package com.example.luyin.utils;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import com.amap.api.location.AMapLocation;
import java.text.SimpleDateFormat;
import java.util.Locale;
/**
*
*/
public class Utils {
/**
*
*/
public final static int MSG_LOCATION_START = 0;
/**
*
*/
public final static int MSG_LOCATION_FINISH = 1;
/**
*
*/
public final static int MSG_LOCATION_STOP= 2;
public final static String KEY_URL = "URL";
public final static String URL_H5LOCATION = "file:///android_asset/sdkLoc.html";
/**
*
* @param location
* @return
*/
public synchronized static String getLocationStr(AMapLocation location){
if(null == location){
return null;
}
StringBuffer sb = new StringBuffer();
//errCode等于0代表定位成功其他的为定位失败具体的可以参照官网定位错误码说明
if(location.getErrorCode() == 0){
sb.append("定位成功" + "\n");
sb.append("定位类型: " + location.getLocationType() + "\n");
sb.append("经 度 : " + location.getLongitude() + "\n");
sb.append("纬 度 : " + location.getLatitude() + "\n");
sb.append("精 度 : " + location.getAccuracy() + "米" + "\n");
sb.append("提供者 : " + location.getProvider() + "\n");
sb.append("速 度 : " + location.getSpeed() + "米/秒" + "\n");
sb.append("角 度 : " + location.getBearing() + "\n");
// 获取当前提供定位服务的卫星个数
sb.append("星 数 : " + location.getSatellites() + "\n");
sb.append("国 家 : " + location.getCountry() + "\n");
sb.append("省 : " + location.getProvince() + "\n");
sb.append("市 : " + location.getCity() + "\n");
sb.append("城市编码 : " + location.getCityCode() + "\n");
sb.append("区 : " + location.getDistrict() + "\n");
sb.append("区域 码 : " + location.getAdCode() + "\n");
sb.append("地 址 : " + location.getAddress() + "\n");
sb.append("兴趣点 : " + location.getPoiName() + "\n");
//定位完成的时间
sb.append("定位时间: " + formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
} else {
//定位失败
sb.append("定位失败" + "\n");
sb.append("错误码:" + location.getErrorCode() + "\n");
sb.append("错误信息:" + location.getErrorInfo() + "\n");
sb.append("错误描述:" + location.getLocationDetail() + "\n");
}
//定位之后的回调时间
sb.append("回调时间: " + formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
return sb.toString();
}
private static SimpleDateFormat sdf = null;
public static String formatUTC(long l, String strPattern) {
if (TextUtils.isEmpty(strPattern)) {
strPattern = "yyyy-MM-dd HH:mm:ss";
}
if (sdf == null) {
try {
sdf = new SimpleDateFormat(strPattern, Locale.CHINA);
} catch (Throwable e) {
}
} else {
sdf.applyPattern(strPattern);
}
return sdf == null ? "NULL" : sdf.format(l);
}
/**
* app
* @param context
* @return
*/
public static String getAppName(Context context) {
String appName = "";
try {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(
context.getPackageName(), 0);
int labelRes = packageInfo.applicationInfo.labelRes;
appName = context.getResources().getString(labelRes);
} catch (Throwable e) {
e.printStackTrace();
}
return appName;
}
}

@ -0,0 +1,81 @@
package com.example.luyin.wechat;
import com.example.luyin.wechat.utils.AppUtil;
import java.util.List;
public class Constants {
public static String Version = "";
public static boolean IsOver = false;
public static int CurrentTask = -1;
public static final int RedEnvelopeType = 1000;
public static final int AutoSendMsgType = 1001;
public static final int InitFriendList = 1002;
public static List<String> FriendList;
public static final String TAG = "Accessibility";
public static class WeChatInfo{
public static final String WECHAT_PACKAGE = "com.tencent.mm";
//首页
public static final String WECHAT_LAUNCHER_UI = "com.tencent.mm.ui.LauncherUI";
//红包界面
public static final String LUCKY_MONEY_UI = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyNotHookReceiveUI";
//聊天界面
public static final String TALKING_UI = "com.tencent.mm.ui.chatting.ChattingUI";
//微信联系人页面
public static final String WECHAT_CLASS_CONTACT_INFO_UI = "com.tencent.mm.plugin.profile.ui.ContactInfoUI";
/**
*
*/
//聊天框左上角名字id
public static String ID_CHATTING_NAME;
//聊天语音切换按钮id
public static String ID_VOICE_BTN;
//聊天界面输入框id
public static String ID_EDIT_VIEW;
//发送按钮
public static String ID_SEND_BTN;
/**
*
*/
//通讯录listViewId
public static String ID_CONTACT_LIST;
//联系人textViewID
public static String ID_CONTACTOR_TEXT;
}
public static void setArgs(String version){
switch (version){
case "7.0.6":
WeChatInfo.ID_CHATTING_NAME = "com.tencent.mm:id/l5";
WeChatInfo.ID_VOICE_BTN = "com.tencent.mm:id/aok";
WeChatInfo.ID_EDIT_VIEW = "com.tencent.mm:id/aom";
WeChatInfo.ID_CONTACT_LIST = "com.tencent.mm:id/nn";
WeChatInfo.ID_CONTACTOR_TEXT = "com.tencent.mm:id/ol";
WeChatInfo.ID_SEND_BTN = "com.tencent.mm:id/aot";
break;
case "7.0.10":
WeChatInfo.ID_CHATTING_NAME = "com.tencent.mm:id/lt";
WeChatInfo.ID_VOICE_BTN = "com.tencent.mm:id/aqc";
WeChatInfo.ID_EDIT_VIEW = "com.tencent.mm:id/aqe";
WeChatInfo.ID_CONTACT_LIST = "com.tencent.mm:id/oc";
WeChatInfo.ID_CONTACTOR_TEXT = "com.tencent.mm:id/pa";
WeChatInfo.ID_SEND_BTN = "com.tencent.mm:id/aql";
break;
default:
AppUtil.makeToast( "初始化版本失败");
}
}
public static void init(String version){
switch (version){
case "7.0.10":
}
}
}

@ -0,0 +1,54 @@
package com.example.luyin.wechat.service;
import android.accessibilityservice.AccessibilityService;
import android.os.Build;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.RequiresApi;
import com.example.luyin.wechat.Constants;
import com.example.luyin.wechat.service.utils.AutoRedEnvelope;
import com.example.luyin.wechat.service.utils.InitFriendList;
import com.example.luyin.wechat.service.utils.SendMessage;
import com.example.luyin.wechat.utils.AccessibilityUtil;
import com.example.luyin.wechat.utils.AppUtil;
public class RedEnvelopeService extends AccessibilityService {
@Override
protected void onServiceConnected() {
AppUtil.makeToast("初始化成功");
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if(event == null || event.getPackageName() == null){
return;
}
if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED){
switch (Constants.CurrentTask){
case Constants.RedEnvelopeType:
AutoRedEnvelope.getInstance(this).startEnvelope(event);
break;
case Constants.AutoSendMsgType:
SendMessage.getInstance(this).startSedMessage(event);
break;
case Constants.InitFriendList:
InitFriendList.getInstance(this).initList(event);
break;
}
}
}
@Override
public void onInterrupt() {
Log.i(Constants.TAG, "onInterrupt");
}
}

@ -0,0 +1,86 @@
package com.example.luyin.wechat.service.utils;
import android.accessibilityservice.AccessibilityService;
import android.os.SystemClock;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.example.luyin.wechat.Constants;
import com.example.luyin.activities.Wechat;
import com.example.luyin.wechat.utils.AccessibilityUtil;
import com.example.luyin.wechat.utils.AppUtil;
import java.util.List;
import static com.example.luyin.wechat.utils.AppUtil.weakUpScreen;
public class AutoRedEnvelope {
private static AutoRedEnvelope autoRedEnvelope;
private static AccessibilityService Service;
private AutoRedEnvelope(AccessibilityService service){
Service = service;
}
public static AutoRedEnvelope getInstance(AccessibilityService service){
if(autoRedEnvelope == null){
synchronized (AutoRedEnvelope.class){
if(autoRedEnvelope == null){
autoRedEnvelope = new AutoRedEnvelope(service);
}
}
}
return autoRedEnvelope;
}
public void startEnvelope(AccessibilityEvent event){
switch (event.getEventType()){
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
Log.i(Constants.TAG, "CurrentPackage: " + event.getPackageName().toString());
List<CharSequence> texts = event.getText();
for(CharSequence ch : texts){
Log.i(Constants.TAG, "NotificationContent: " + ch.toString());
AppUtil.makeToast("Msg: " + ch.toString());
if(ch.toString().contains("[微信红包]")){
weakUpScreen();
AccessibilityUtil.gotoApp(event);
Log.i(Constants.TAG, "Get Red Envelope!");
}
}
break;
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED :
String className = event.getClassName().toString();
if(className.equals(Constants.WeChatInfo.WECHAT_LAUNCHER_UI)){
AccessibilityNodeInfo nodeInfo = event.getSource();
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("微信红包");
if(list != null && list.size() > 0){
AccessibilityUtil.performClick(list.get(list.size() - 1));
}
}else if(className.equals(Constants.WeChatInfo.LUCKY_MONEY_UI)){
openRedEnvelope(event.getSource());
}
break;
default:
break;
}
}
//开启红包
private void openRedEnvelope(AccessibilityNodeInfo node){
if(node == null) {
Log.i(Constants.TAG, "node = null");
}
SystemClock.sleep(50);
Log.i(Constants.TAG, "openRedEnvelope: fakeClick");
float x = Wechat.Width / 2.0F;
float y = Wechat.Height * 2 / 3.0F;
for(int i = 0; i < 10; i++){
SystemClock.sleep(17);
AccessibilityUtil.performXYClick(Service, x, y);
}
SystemClock.sleep(500);
AccessibilityUtil.globalGoHome(Service);
}
}

@ -0,0 +1,105 @@
package com.example.luyin.wechat.service.utils;
import android.accessibilityservice.AccessibilityService;
import android.app.ActivityManager;
import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.example.luyin.wechat.Constants;
import com.example.luyin.wechat.utils.AccessibilityUtil;
import com.example.luyin.wechat.utils.AppUtil;
import java.util.ArrayList;
import java.util.List;
public class InitFriendList {
private static AccessibilityService CurrentService;
private static InitFriendList mInstance;
private InitFriendList(AccessibilityService service){
CurrentService = service;
}
public static InitFriendList getInstance(AccessibilityService service){
if(mInstance == null){
synchronized (InitFriendList.class){
if(mInstance == null){
mInstance = new InitFriendList(service);
}
}
}
return mInstance;
}
public void initList(AccessibilityEvent event){
String currentActivity = event.getClassName().toString();
Log.i(Constants.TAG, "initList: " + currentActivity);
switch (currentActivity){
case Constants.WeChatInfo.WECHAT_LAUNCHER_UI:
headToContactUI();
break;
default:
AppUtil.makeToast("请回到主界面");
}
}
//
private void headToContactUI(){
if(!AccessibilityUtil.findTextAndClick(CurrentService,"通讯录")) {
AccessibilityUtil.globalGoBack(CurrentService);
}
freshContactUI();
getList();
resetApp();
}
//找到通讯录UI界面并点击
private void freshContactUI(){
AccessibilityUtil.findTextAndClick(CurrentService,"通讯录");
SystemClock.sleep(500);
AccessibilityUtil.findTextAndClick(CurrentService,"通讯录");
}
private void getList(){
AccessibilityNodeInfo nodeInfo = CurrentService.getRootInActiveWindow();
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(Constants.WeChatInfo.ID_CONTACT_LIST);
if(list != null && !list.isEmpty()){
List<String> userList = new ArrayList<>();
while (true){
List<AccessibilityNodeInfo> users = nodeInfo.findAccessibilityNodeInfosByViewId(Constants.WeChatInfo.ID_CONTACTOR_TEXT);
if(users != null && !users.isEmpty()){
for(int i = 0; i < users.size(); i++){
AccessibilityNodeInfo node = users.get(i);
String name = node.getText().toString();
if(!userList.contains(name)){
userList.add(name);
}else{
if(i == users.size() - 1){
AppUtil.makeToast("扫描完毕");
Constants.FriendList = userList;
return;
}
}
}
list.get(0).performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
SystemClock.sleep(500);
}
}
}
}
public void resetApp(){
ActivityManager manager = (ActivityManager) CurrentService.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfos = manager.getRunningTasks(3);
for(ActivityManager.RunningTaskInfo info : taskInfos){
if(CurrentService.getPackageName().equals(info.topActivity.getPackageName())){
manager.moveTaskToFront(info.id, ActivityManager.MOVE_TASK_WITH_HOME);
}
}
}
}

@ -0,0 +1,144 @@
package com.example.luyin.wechat.service.utils;
import android.accessibilityservice.AccessibilityService;
import android.app.ActivityManager;
import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.example.luyin.wechat.Constants;
import com.example.luyin.wechat.utils.AccessibilityUtil;
import com.example.luyin.wechat.utils.AppUtil;
import java.util.ArrayList;
import java.util.List;
public class SendMessage {
public static String NAME;
public static String CONTENT;
private static AccessibilityService CurrentService;
private static SendMessage mInstance;
private SendMessage(AccessibilityService service){
CurrentService = service;
}
public static SendMessage getInstance(AccessibilityService service){
if(mInstance == null){
synchronized (SendMessage.class){
if(mInstance == null){
mInstance = new SendMessage(service);
}
}
}
return mInstance;
}
public void startSedMessage(AccessibilityEvent event){
String currentActivity = event.getClassName().toString();
Log.i(Constants.TAG, "startSedMessage: " + currentActivity);
switch (currentActivity){
case Constants.WeChatInfo.WECHAT_LAUNCHER_UI://首页
headToContactUI();
break;
case "android.widget.LinearLayout":
case Constants.WeChatInfo.TALKING_UI://聊天界面
sendMsg();
break;
case Constants.WeChatInfo.WECHAT_CLASS_CONTACT_INFO_UI://联系人界面
headToChattingUi();
break;
default:
AppUtil.makeToast("请回到主界面");
}
}
private void headToContactUI(){
if(!AccessibilityUtil.findTextAndClick(CurrentService,"通讯录")){
String talker = AccessibilityUtil.findTextById(CurrentService, Constants.WeChatInfo.ID_CHATTING_NAME);
if(talker.equals(NAME)){
sendMsg();
}else {
AccessibilityUtil.globalGoBack(CurrentService);
freshContactUI();
}
}else {
freshContactUI();
}
}
private void freshContactUI(){
AccessibilityUtil.findTextAndClick(CurrentService,"通讯录");
SystemClock.sleep(300);
AccessibilityUtil.findTextAndClick(CurrentService,"通讯录");
SystemClock.sleep(300);
AccessibilityNodeInfo node = findTalker();
if(node != null){
AccessibilityUtil.performClick(node);
}
}
private void headToChattingUi(){
AccessibilityUtil.findTextAndClick(CurrentService, "发消息");
}
private AccessibilityNodeInfo findTalker(){
AccessibilityNodeInfo nodeInfo = CurrentService.getRootInActiveWindow();
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(Constants.WeChatInfo.ID_CONTACT_LIST);
if(list != null && !list.isEmpty()){
List<String> userList = new ArrayList<>();
while (true){
List<AccessibilityNodeInfo> users = nodeInfo.findAccessibilityNodeInfosByViewId(Constants.WeChatInfo.ID_CONTACTOR_TEXT);
if(users != null && !users.isEmpty()){
for(int i = 0; i < users.size(); i++){
AccessibilityNodeInfo node = users.get(i);
String name = node.getText().toString();
if(name.equals(NAME)) return node;
if(!userList.contains(name)){
userList.add(name);
}else{
if(i == users.size() - 1){
AppUtil.makeToast("未找到联系人");
return null;
}
}
}
list.get(0).performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
SystemClock.sleep(300);
}
}
}
return null;
}
private void sendMsg(){
String talker = AccessibilityUtil.findTextById(CurrentService, Constants.WeChatInfo.ID_CHATTING_NAME);
if(talker != null && talker.equals(NAME)){
if(!AccessibilityUtil.findIdAndWrite(CurrentService, Constants.WeChatInfo.ID_EDIT_VIEW, CONTENT)){
AccessibilityUtil.findAndClickById(CurrentService, Constants.WeChatInfo.ID_VOICE_BTN);
AccessibilityUtil.findIdAndWrite(CurrentService, Constants.WeChatInfo.ID_EDIT_VIEW, CONTENT);
}
AccessibilityUtil.findAndClickById(CurrentService, Constants.WeChatInfo.ID_SEND_BTN);
resetApp();
Constants.CurrentTask = -1;
Constants.IsOver = true;
}else {
AccessibilityUtil.globalGoBack(CurrentService);
freshContactUI();
}
}
public void resetApp(){
ActivityManager manager = (ActivityManager) CurrentService.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfos = manager.getRunningTasks(3);
for(ActivityManager.RunningTaskInfo info : taskInfos){
if(CurrentService.getPackageName().equals(info.topActivity.getPackageName())){
manager.moveTaskToFront(info.id, ActivityManager.MOVE_TASK_WITH_HOME);
}
}
}
}

@ -0,0 +1,136 @@
package com.example.luyin.wechat.utils;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.Path;
import android.os.Parcelable;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.example.luyin.activities.Wechat;
import java.util.List;
import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_BACK;
import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_HOME;
public class AccessibilityUtil {
//点击文字所属按钮事件
public static boolean findTextAndClick(AccessibilityService service, String text){
AccessibilityNodeInfo nodeInfo = service.getRootInActiveWindow();
if(nodeInfo == null) return false;
List<AccessibilityNodeInfo> nodeInfoList = nodeInfo.findAccessibilityNodeInfosByText(text);
if(nodeInfoList != null && !nodeInfoList.isEmpty()){
for(AccessibilityNodeInfo info : nodeInfoList){
if(info != null && (text.equals(info.getText())) || text.equals(info.getContentDescription())){
performClick(info);
return true;
}
}
}
return false;
}
//点击id所属按钮文字
public static void findAndClickById(AccessibilityService service, String id){
AccessibilityNodeInfo nodeInfo = service.getRootInActiveWindow();
if(nodeInfo == null) return;
List<AccessibilityNodeInfo> nodeInfoList = nodeInfo.findAccessibilityNodeInfosByViewId(id);
if(nodeInfoList != null && nodeInfoList.size() > 0){
performClick(nodeInfoList.get(0));
}
}
//获取id所属按钮文字
public static String findTextById(AccessibilityService service, String id){
AccessibilityNodeInfo nodeInfo = service.getRootInActiveWindow();
if(nodeInfo == null) return null;
List<AccessibilityNodeInfo> nodeInfoList = nodeInfo.findAccessibilityNodeInfosByViewId(id);
if(nodeInfoList != null && nodeInfoList.size() > 0){
return nodeInfoList.get(0).getText().toString();
}
return null;
}
//编辑EditView
public static boolean findIdAndWrite(AccessibilityService service, String id, String text){
AccessibilityNodeInfo nodeInfo = service.getRootInActiveWindow();
List<AccessibilityNodeInfo> edit = nodeInfo.findAccessibilityNodeInfosByViewId(id);
if(edit != null && !edit.isEmpty()){
AccessibilityNodeInfo node = edit.get(0);
ClipboardManager clipboardManager = (ClipboardManager) Wechat.AppContext.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = ClipData.newPlainText("text", text);
clipboardManager.setPrimaryClip(clipData);
node.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
node.performAction(AccessibilityNodeInfo.ACTION_PASTE);
return true;
}
return false;
}
//输入x, y坐标模拟点击事件
@TargetApi(android.os.Build.VERSION_CODES.N)
public static void performXYClick(AccessibilityService service, float x, float y){
Path path = new Path();
path.moveTo(x, y);
GestureDescription.Builder builder = new GestureDescription.Builder();
builder.addStroke(new GestureDescription.StrokeDescription(path, 0, 1));
GestureDescription gestureDescription = builder.build();
service.dispatchGesture(gestureDescription, new AccessibilityService.GestureResultCallback() {
@Override
public void onCompleted(GestureDescription gestureDescription) {
super.onCompleted(gestureDescription);
//Log.i(Constants.TAG, "onCompleted: completed");
}
@Override
public void onCancelled(GestureDescription gestureDescription) {
super.onCancelled(gestureDescription);
//Log.i(Constants.TAG, "onCancelled: cancelled");
}
}, null);
}
//对某个节点进行点击
public static void performClick(AccessibilityNodeInfo nodeInfo){
if(nodeInfo == null) return;
while (nodeInfo != null){
if(nodeInfo.isClickable()){
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
break;
}
nodeInfo = nodeInfo.getParent();
}
}
//通知栏事件进入应用
public static void gotoApp(AccessibilityEvent event){
Parcelable data = event.getParcelableData();
if(data != null && data instanceof Notification){
Notification notification = (Notification) data;
PendingIntent intent = notification.contentIntent;
try {
intent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
}
//模拟点击返回键
public static void globalGoBack(AccessibilityService service){
service.performGlobalAction(GLOBAL_ACTION_BACK);
}
//模拟点击Home键
public static void globalGoHome(AccessibilityService service){
service.performGlobalAction(GLOBAL_ACTION_HOME);
}
}

@ -0,0 +1,64 @@
package com.example.luyin.wechat.utils;
import android.annotation.SuppressLint;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.PowerManager;
import android.widget.Toast;
import com.example.luyin.activities.Wechat;
public class AppUtil {
public static String getVersion(Context context, String packageName){
try {
return context.getPackageManager().getPackageInfo(packageName, 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return "";
}
@SuppressLint("InvalidWakeLockTag")
public static void weakUpScreen(){
PowerManager pm = (PowerManager)Wechat.AppContext.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "WakeLock");
wakeLock.acquire();
wakeLock.release();
KeyguardManager km = (KeyguardManager) Wechat.AppContext.getSystemService(Context.KEYGUARD_SERVICE);
KeyguardManager.KeyguardLock lock = km.newKeyguardLock("unlock");
lock.disableKeyguard();
}
public static void makeToast(String text){
Toast.makeText(Wechat.AppContext, text, Toast.LENGTH_SHORT).show();
}
//获取版本号
public static String getAppVersion(Context context){
PackageManager packageManager = context.getPackageManager();
PackageInfo info = null;
try {
info = packageManager.getPackageInfo(context.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return info.versionName;
}
//创建context
public static Context getContext(Context t, String packageName){
Context context = null;
try {
context = t.createPackageContext(packageName, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return context;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/btn_left_p"/>
<item android:state_focused="true"
android:drawable="@drawable/btn_left_f"/>
<item android:drawable="@drawable/btn_left_n" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/btn_right_p"/>
<item android:state_focused="true"
android:drawable="@drawable/btn_right_f"/>
<item android:drawable="@drawable/btn_right_n" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/login_p" />
<item android:state_enabled="false" android:drawable="@drawable/login" />
<item android:drawable="@drawable/login" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save