commit 56a1285f52675035277ee1745ab35f60a0965855 Author: iweizime Date: Wed Sep 6 20:50:40 2017 +0800 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d9fd409 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +/build diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..96cc43e --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/dictionaries/iweiz.xml b/.idea/dictionaries/iweiz.xml new file mode 100644 index 0000000..ed051c2 --- /dev/null +++ b/.idea/dictionaries/iweiz.xml @@ -0,0 +1,11 @@ + + + + alipay + gphone + pedo + stepchanger + stepinfo + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/markdown-navigator.xml b/.idea/markdown-navigator.xml new file mode 100644 index 0000000..d819570 --- /dev/null +++ b/.idea/markdown-navigator.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/markdown-navigator/profiles_settings.xml b/.idea/markdown-navigator/profiles_settings.xml new file mode 100644 index 0000000..57927c5 --- /dev/null +++ b/.idea/markdown-navigator/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..5d19981 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..ee64ef8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d902812 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# 运动修改器 + +## 下载 +[步数修改器](https://github.com/iweizime/StepChanger/releases) + +## 注意 + +- 需要手机支持`Step Counter Sensor` + +- 需要`Root`权限 + +- 不要一次改的太多,会被检测为异常 + +支持Android 5.1以上系统,仅在Android 7.x系统上测试过。 + + +## 界面 + +
+ 微信主界面 + 微信详情界面 + 支付宝主界面 + 支付宝详情界面 +
\ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..ad1987d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,2 @@ +/build +/StepChanger-*-release.apk diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..5fec960 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,42 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 26 + buildToolsVersion "26.0.1" + defaultConfig { + applicationId "me.iweizi.stepchanger" + minSdkVersion 21 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + applicationVariants.all { variant -> + variant.outputs.each { output -> + output.outputFile = new File( + output.outputFile.parent, + "StepChanger-${variant.versionName}-${variant.buildType.name}.apk") + } + } +} + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + + compile 'com.android.support:recyclerview-v7:26.0.0-alpha1' + compile 'com.android.support:appcompat-v7:26.0.0-alpha1' + compile 'com.android.support:support-v4:26.0.0-alpha1' + compile 'com.android.support:design:26.0.0-alpha1' + compile 'eu.chainfire:libsuperuser:1.0.0.201704021214' + compile 'com.alibaba:fastjson:1.1.63.android' + testCompile 'junit:junit:4.12' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..9e6f20a --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\Users\iweiz\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# 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 diff --git a/app/src/androidTest/java/me/iweizi/stepchanger/ExampleInstrumentedTest.java b/app/src/androidTest/java/me/iweizi/stepchanger/ExampleInstrumentedTest.java new file mode 100644 index 0000000..e93fea6 --- /dev/null +++ b/app/src/androidTest/java/me/iweizi/stepchanger/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package me.iweizi.stepchanger; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; + +/** + * Instrumentation test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("me.iweizi.stepchanger", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..acac6ab --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/me/iweizi/stepchanger/BaseDetailsActivity.java b/app/src/main/java/me/iweizi/stepchanger/BaseDetailsActivity.java new file mode 100644 index 0000000..2e3ffbf --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/BaseDetailsActivity.java @@ -0,0 +1,103 @@ +package me.iweizi.stepchanger; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public abstract class BaseDetailsActivity extends AppCompatActivity { + private Button mLoadButton; + private Button mBackButton; + private Button mStoreButton; + private TextView mLastUploadStepTV; + private TextView mLastUploadTimeTV; + private TextView mLastSaveTimeTV; + private TextView mLastSaveSensorStepTV; + + protected int mLayoutId; + protected StepData mStepData; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(mLayoutId); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + findView(); + setListener(); + + } + + private void findView() { + mLastUploadStepTV = (TextView) findViewById(R.id.last_upload_step_text_view); + mLastUploadTimeTV = (TextView) findViewById(R.id.last_upload_time_text_view); + mLastSaveTimeTV = (TextView) findViewById(R.id.last_save_time_text_view); + mLastSaveSensorStepTV = (TextView) findViewById(R.id.last_save_sensor_step_text_view); + + mLoadButton = (Button) findViewById(R.id.details_load_button); + mBackButton = (Button) findViewById(R.id.details_back_button); + mStoreButton = (Button) findViewById(R.id.details_store_button); + } + + private void setListener() { + mLoadButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int result = mStepData.load(BaseDetailsActivity.this); + if (result == StepData.SUCCESS) { + updateUI(); + Toast.makeText(BaseDetailsActivity.this, R.string.loaded, Toast.LENGTH_SHORT).show(); + } + } + }); + + mBackButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + finish(); + } + }); + + mStoreButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int result = mStepData.store(BaseDetailsActivity.this); + if (result == StepData.SUCCESS) { + Toast.makeText(BaseDetailsActivity.this, R.string.stored, Toast.LENGTH_SHORT).show(); + } else if (result == StepData.CANCEL) { + Toast.makeText(BaseDetailsActivity.this, R.string.canceled, Toast.LENGTH_SHORT).show(); + } else if (result == StepData.NEED_LOAD) { + Toast.makeText(BaseDetailsActivity.this, R.string.need_load, Toast.LENGTH_SHORT).show(); + } + } + }); + } + + @Override + protected void onResume() { + super.onResume(); + updateUI(); + } + + private void updateUI() { + if (mStepData.isLoaded()) { + DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss.SSS", Locale.CHINA); + Date date = new Date(); + mLastUploadStepTV.setText(String.valueOf(mStepData.getLastUploadStep())); + date.setTime(mStepData.getLastUploadTime()); + mLastUploadTimeTV.setText(dateFormat.format(date)); + date.setTime(mStepData.getLastSaveTime()); + mLastSaveTimeTV.setText(dateFormat.format(date)); + mLastSaveSensorStepTV.setText(String.valueOf(mStepData.getLastSaveSensorStep())); + } + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/BaseFragment.java b/app/src/main/java/me/iweizi/stepchanger/BaseFragment.java new file mode 100644 index 0000000..6e30b66 --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/BaseFragment.java @@ -0,0 +1,137 @@ +package me.iweizi.stepchanger; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.Toast; + +/** + * Created by iweiz on 2017/9/5. + * BaseFragment是 WechatFragment和 AlipayFragment的父类 + */ + +public class BaseFragment extends Fragment { + + private static final int COUNTER_DIFF = 1000; + + protected Button mLoadButton; + protected Button mStoreButton; + protected Button mDetailsButton; + + protected EditText mCurrentTodayStepEditText; + protected ImageButton mStepIncImageButton; + protected ImageButton mStepDecImageButton; + + protected int mLayoutId; + protected StepData mStepData; + protected Class mDetailsClass; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(mLayoutId, container, false); + findView(view); + setListener(); + + return view; + } + + private void setListener() { + + mStepIncImageButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mStepData.changeStep(COUNTER_DIFF); + updateUI(); + } + }); + + mStepDecImageButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mStepData.changeStep(-COUNTER_DIFF); + updateUI(); + } + }); + + mCurrentTodayStepEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (s.length() == 0) { + s = "0"; + } + mStepData.setStep(Integer.valueOf(s.toString())); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + mLoadButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int result = mStepData.load(getActivity()); + if (result == StepData.SUCCESS) { + updateUI(); + Toast.makeText(getActivity(), R.string.loaded, Toast.LENGTH_SHORT).show(); + } + } + }); + + mStoreButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int result = mStepData.store(getActivity()); + if (result == StepData.SUCCESS) { + Toast.makeText(getActivity(), R.string.stored, Toast.LENGTH_SHORT).show(); + } else if (result == StepData.CANCEL) { + Toast.makeText(getActivity(), R.string.canceled, Toast.LENGTH_SHORT).show(); + } else if (result == StepData.NEED_LOAD) { + Toast.makeText(getContext(), R.string.need_load, Toast.LENGTH_SHORT).show(); + } + } + }); + + mDetailsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mDetailsClass != null) { + Intent intent = new Intent(getActivity(), mDetailsClass); + startActivity(intent); + } + } + }); + } + + // 子类应该实现 + protected void findView(View view) { + } + + @Override + public void onResume() { + super.onResume(); + updateUI(); + } + + private void updateUI() { + if (mStepData.getStep() >= 0) { + mCurrentTodayStepEditText.setText(String.valueOf(mStepData.getStep())); + } + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/MainActivity.java b/app/src/main/java/me/iweizi/stepchanger/MainActivity.java new file mode 100644 index 0000000..7a11462 --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/MainActivity.java @@ -0,0 +1,84 @@ +package me.iweizi.stepchanger; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomNavigationView; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.view.MenuItem; + +import java.util.ArrayList; + +import me.iweizi.stepchanger.alipay.AlipayFragment; +import me.iweizi.stepchanger.utils.StepCounterSensorListener; +import me.iweizi.stepchanger.wechat.WechatFragment; + +public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener { + + private BottomNavigationView mBottomNavigationView; + private ViewPager mViewPager; + private ArrayList mFragments; + + private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener + = new BottomNavigationView.OnNavigationItemSelectedListener() { + + @Override + public boolean onNavigationItemSelected(@NonNull MenuItem item) { + mViewPager.setCurrentItem(item.getOrder()); + return true; + } + + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + StepCounterSensorListener.get(this).register(); + mBottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation); + mBottomNavigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); + + // mFragments.add顺序需要和res/menu/navigation.xml中的orderInCategory 0,1保持一致 + mFragments = new ArrayList<>(); + mFragments.add(WechatFragment.newInstance()); + mFragments.add(AlipayFragment.newInstance()); + + FragmentManager fragmentManager = getSupportFragmentManager(); + mViewPager = (ViewPager) findViewById(R.id.view_pager); + mViewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) { + @Override + public Fragment getItem(int position) { + return mFragments.get(position); + } + + @Override + public int getCount() { + return mFragments.size(); + } + }); + mViewPager.addOnPageChangeListener(this); + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + mBottomNavigationView.getMenu().getItem(position).setChecked(true); + } + + @Override + public void onDestroy() { + StepCounterSensorListener.get(this).unregister(); + super.onDestroy(); + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/StepData.java b/app/src/main/java/me/iweizi/stepchanger/StepData.java new file mode 100644 index 0000000..bc3cc20 --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/StepData.java @@ -0,0 +1,254 @@ +package me.iweizi.stepchanger; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.AsyncTask; +import android.support.v7.app.AlertDialog; + +import eu.chainfire.libsuperuser.Shell; + +/** + * Created by iweiz on 2017/9/5. + * 步数数据父类 + */ + +public class StepData { + + public static final int SUCCESS = 0; + public static final int FAIL = 1; + public static final int ROOTING = 2; + public static final int CANCEL = 3; + public static final int NEED_LOAD = 4; + + private static final int TOO_FAST = 5; + private static final int TOO_MANY = 6; + private static final int TOO_MANY_FAST = 7; + + private static final double MAX_STEP_PER_SEC = 5.0; + private static final int MAX_STEP = 80000; + + private long mStep; + private boolean isChecked; + private boolean isContinue; + + protected String[] ROOT_CMD; + protected int mLoadButtonId; + protected int mStoreButtonId; + + class RootTask extends AsyncTask { + private Context mContext = null; + private boolean mSuAvailable; + @SuppressWarnings("deprecation") + private ProgressDialog mProgressDialog = null; + private AlertDialog mAlertDialog = null; + private boolean isRead; + + public RootTask(Context context) { + mContext = context; + } + + @Override + protected void onPreExecute() { + //noinspection deprecation + mProgressDialog = new ProgressDialog(mContext); + mProgressDialog.setTitle(R.string.require_access_title); + mProgressDialog.setMessage(mContext.getString(R.string.require_access_message)); + mProgressDialog.setIndeterminate(true); + mProgressDialog.setCancelable(false); + mProgressDialog.show(); + } + + @Override + protected Void doInBackground(Boolean... booleans) { + isRead = booleans[0]; + mSuAvailable = Shell.SU.available(); + if (mSuAvailable) { + Shell.SU.run(ROOT_CMD); + } + return null; + } + + @Override + protected void onPostExecute(Void results) { + mProgressDialog.dismiss(); + + if (mSuAvailable) { + if (isRead && canRead()) { + ((Activity) mContext).findViewById(mLoadButtonId).performClick(); + } else if (canWrite()) { + ((Activity) mContext).findViewById(mStoreButtonId).performClick(); + } + } else { + AlertDialog.Builder builder = new AlertDialog.Builder(mContext) + .setTitle(R.string.note) + .setMessage(R.string.require_failed_message) + .setCancelable(true); + mAlertDialog = builder.create(); + mAlertDialog.show(); + } + } + } + + protected StepData() { + mStep = -1; + isChecked = false; + isContinue = true; + } + + public final long getStep() { + return mStep; + } + + public final void setStep(long step) { + mStep = step; + } + + public final void changeStep(long diff) { + mStep = mStep + diff; + if (mStep < 0) { + mStep = 0; + } + } + + private int check() { + long current = System.currentTimeMillis(); + long lastUploadTime = getLastUploadTime(); + double timeDiff = (current - lastUploadTime) / 1000; + long step = getStep(); + long stepDiff = step - getLastUploadStep(); + double stepPerSec = stepDiff / timeDiff; + if (step > MAX_STEP && stepPerSec > MAX_STEP_PER_SEC) { + return TOO_MANY_FAST; + } else if (step > MAX_STEP) { + return TOO_MANY; + } else if (stepPerSec > MAX_STEP_PER_SEC) { + return TOO_FAST; + } + return SUCCESS; + } + + public final int load(final Context context) { + int readResult; + if (!canRead()) { + (new RootTask(context)).execute(true); + return ROOTING; + } + + readResult = read(context); + mStep = getLastUploadStep(); + return readResult; + } + + public final int store(final Context context) { + int checkResult; + int writeResult; + if (!isLoaded()) { + return NEED_LOAD; + } + + if (!isChecked) { + checkResult = check(); + isChecked = true; + if (checkResult != SUCCESS) { + String message; + switch (checkResult) { + case TOO_FAST: + message = context.getString(R.string.too_fast); + break; + case TOO_MANY: + message = context.getString(R.string.too_many); + break; + case TOO_MANY_FAST: + message = context.getString(R.string.too_many_fast); + break; + default: + message = ""; + } + + AlertDialog.Builder builder = new AlertDialog.Builder(context) + .setTitle(R.string.note) + .setMessage(message + context.getString(R.string.is_continue)) + .setCancelable(false) + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + isContinue = true; + ((Activity) context).findViewById(mStoreButtonId).performClick(); + } + }) + .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + isContinue = false; + ((Activity) context).findViewById(mStoreButtonId).performClick(); + } + }); + builder.create().show(); + return checkResult; + } + } + + if (!isContinue) { + isContinue = true; + isChecked = false; + return CANCEL; + } + + if (!canWrite()) { + (new RootTask(context)).execute(false); + return ROOTING; + } + + writeResult = write(context); + isChecked = false; + isContinue = true; + return writeResult; + } + + // 子类应该实现 + protected boolean canRead() { + return false; + } + + // 子类应该实现 + protected boolean canWrite() { + return false; + } + + // 子类应该实现 + protected int read(Context context) { + return FAIL; + } + + // 子类应该实现 + protected int write(Context context) { + return FAIL; + } + + // 子类应该实现 + public long getLastUploadTime() { + return -1; + } + + // 子类应该实现 + public long getLastUploadStep() { + return -1; + } + + // 子类应该实现 + public long getLastSaveTime() { + return -1; + } + + // 子类应该实现 + public long getLastSaveSensorStep() { + return -1; + } + + // 子类应该实现 + public boolean isLoaded() { + return false; + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/alipay/APStepInfo.java b/app/src/main/java/me/iweizi/stepchanger/alipay/APStepInfo.java new file mode 100644 index 0000000..5c2cb54 --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/alipay/APStepInfo.java @@ -0,0 +1,43 @@ +package me.iweizi.stepchanger.alipay; + +/** + * Created by iweiz on 2017/9/5. + * 支付宝步数数据记录 + */ + +@SuppressWarnings("unused") +class APStepInfo { + private String biz; + private int steps; + private long time; + + APStepInfo() { + biz = ""; + steps = 0; + time = 0; + } + + public String getBiz() { + return biz; + } + + public void setBiz(String biz) { + this.biz = biz; + } + + public int getSteps() { + return steps; + } + + public void setSteps(int steps) { + this.steps = steps; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/alipay/AlipayDetailsActivity.java b/app/src/main/java/me/iweizi/stepchanger/alipay/AlipayDetailsActivity.java new file mode 100644 index 0000000..5f790ff --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/alipay/AlipayDetailsActivity.java @@ -0,0 +1,16 @@ +package me.iweizi.stepchanger.alipay; + +import android.os.Bundle; + +import me.iweizi.stepchanger.BaseDetailsActivity; +import me.iweizi.stepchanger.R; + +public class AlipayDetailsActivity extends BaseDetailsActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + mLayoutId = R.layout.activity_alipay_details; + mStepData = NewPedoMeter.get(); + super.onCreate(savedInstanceState); + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/alipay/AlipayFragment.java b/app/src/main/java/me/iweizi/stepchanger/alipay/AlipayFragment.java new file mode 100644 index 0000000..0b24348 --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/alipay/AlipayFragment.java @@ -0,0 +1,34 @@ +package me.iweizi.stepchanger.alipay; + + +import android.os.Bundle; +import android.view.View; + +import me.iweizi.stepchanger.BaseFragment; +import me.iweizi.stepchanger.R; + +public class AlipayFragment extends BaseFragment { + + public AlipayFragment() { + mLayoutId = R.layout.fragment_alipay; + mStepData = NewPedoMeter.get(); + mDetailsClass = AlipayDetailsActivity.class; + } + + public static AlipayFragment newInstance() { + AlipayFragment fragment = new AlipayFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + @Override + protected void findView(View view) { + mLoadButton = view.findViewById(R.id.alipay_load_button); + mStoreButton = view.findViewById(R.id.alipay_store_button); + mDetailsButton = view.findViewById(R.id.alipay_details_button); + mStepIncImageButton = view.findViewById(R.id.alipay_add_button); + mStepDecImageButton = view.findViewById(R.id.alipay_sub_button); + mCurrentTodayStepEditText = view.findViewById(R.id.alipay_current_today_step_edit_text); + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/alipay/NewPedoMeter.java b/app/src/main/java/me/iweizi/stepchanger/alipay/NewPedoMeter.java new file mode 100644 index 0000000..94ce3ed --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/alipay/NewPedoMeter.java @@ -0,0 +1,236 @@ +package me.iweizi.stepchanger.alipay; + +import android.annotation.SuppressLint; +import android.app.ActivityManager; +import android.content.Context; +import android.content.SharedPreferences; + +import com.alibaba.fastjson.JSON; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import eu.chainfire.libsuperuser.Shell; +import me.iweizi.stepchanger.R; +import me.iweizi.stepchanger.StepData; +import me.iweizi.stepchanger.utils.StepCounterSensorListener; + +/** + * Created by iweiz on 2017/9/5. + * 支付宝的步数数据类 + */ + +public class NewPedoMeter extends StepData { + @SuppressLint("SdCardPath") + private static final String ALIPAY_SP_DIR = + "/data/data/com.eg.android.AlipayGphone/shared_prefs/"; + @SuppressLint("SdCardPath") + private static final String SP_DIR = + "/data/data/me.iweizi.stepchanger/shared_prefs/"; + private static final String NEW_PEDOMETER = "NewPedoMeter.xml"; + private static final String NEW_PEDOMETER_PRIVATE = "NewPedoMeter_private.xml"; + + private static final String ALIPAY = "com.eg.android.AlipayGphone"; + private static final String ALIPAY_EXT = "com.eg.android.AlipayGphone:ext"; + private static final NewPedoMeter sNewPedoMeter = new NewPedoMeter(); + private final String mNewPedometer; + private final String mNewPedometerPrivate; + private final String mAlipayNewPedometer; + private final String mAlipayNewPedometerPrivate; + private SharedPreferences mNewPedometerSP; + private SharedPreferences mNewPedometerPrivateSP; + private final File mAlipayNewPedometerFile; + private final File mAlipayNewPedometerPrivateFile; + + private NewPedoMeter() { + super(); + mNewPedometer = SP_DIR + NEW_PEDOMETER; + mNewPedometerPrivate = SP_DIR + NEW_PEDOMETER_PRIVATE; + mAlipayNewPedometer = ALIPAY_SP_DIR + NEW_PEDOMETER; + mAlipayNewPedometerPrivate = ALIPAY_SP_DIR + NEW_PEDOMETER_PRIVATE; + + mAlipayNewPedometerFile = new File(mAlipayNewPedometer); + mAlipayNewPedometerPrivateFile = new File(mAlipayNewPedometerPrivate); + + File sp_dir = new File(SP_DIR); + if (!sp_dir.exists()) { + //noinspection ResultOfMethodCallIgnored + sp_dir.mkdir(); + } + + ROOT_CMD = new String[]{ + "chmod o+rw " + mAlipayNewPedometer, + "chmod o+rw " + mAlipayNewPedometerPrivate, + }; + + mLoadButtonId = R.id.alipay_load_button; + mStoreButtonId = R.id.alipay_store_button; + } + + public static NewPedoMeter get() { + return sNewPedoMeter; + } + + @Override + public int read(Context context) { + killAlipayProcess(context); + Shell.SH.run(new String[]{ + "cp " + mAlipayNewPedometerPrivate + " " + mNewPedometerPrivate, + "cp " + mAlipayNewPedometer + " " + mNewPedometer + }); + mNewPedometerSP = context.getSharedPreferences("NewPedoMeter", Context.MODE_PRIVATE); + mNewPedometerPrivateSP = context.getSharedPreferences("NewPedoMeter_private", Context.MODE_PRIVATE); + return SUCCESS; + } + + @Override + public int write(Context context) { + killAlipayProcess(context); + List stepRecord = getStepRecord(); + APStepInfo lastRecord = getLastRecord(); + if (lastRecord == null) { + lastRecord = new APStepInfo(); + } + long stepDiff = getStep() - getLastUploadStep(); + long sensorStep = StepCounterSensorListener.get(context).getStep(); + stepDiff = stepDiff - sensorStep + lastRecord.getSteps(); + for (APStepInfo apStepInfo : + stepRecord) { + apStepInfo.setSteps(apStepInfo.getSteps() - (int) stepDiff); + } + saveStepRecord(stepRecord); + Shell.SH.run(new String[]{ + "cat " + mNewPedometerPrivate + " > " + mAlipayNewPedometerPrivate + }); + return SUCCESS; + } + + private APStepInfo getBaseStep() { + if (mNewPedometerSP == null) { + return null; + } + String baseStepStr = mNewPedometerSP.getString("baseStep", null); + if (baseStepStr == null || baseStepStr.isEmpty()) { + return null; + } + return JSON.parseObject(baseStepStr, APStepInfo.class); + } + + private APStepInfo getLastStepInfoToday() { + if (mNewPedometerSP == null) { + return null; + } + String lastStepInfoTodayStr = mNewPedometerSP.getString("last_stepinfo_today", null); + + if (lastStepInfoTodayStr == null || lastStepInfoTodayStr.isEmpty()) { + return null; + } + + return JSON.parseObject(lastStepInfoTodayStr, APStepInfo.class); + } + + private List getStepRecord() { + if (mNewPedometerPrivateSP == null) { + return new ArrayList<>(); + } + String stepRecordStr = mNewPedometerPrivateSP.getString("stepRecord", null); + if (stepRecordStr == null) { + return new ArrayList<>(); + } + return JSON.parseArray(stepRecordStr, APStepInfo.class); + } + + @SuppressLint("ApplySharedPref") + private void saveStepRecord(List stepRecord) { + SharedPreferences.Editor editor = mNewPedometerPrivateSP.edit(); + String stepRecordStr = JSON.toJSON(stepRecord).toString(); + editor.putString("stepRecord", stepRecordStr); + editor.commit(); + } + + private void killAlipayProcess(Context context) { + ActivityManager am = (ActivityManager) + context.getSystemService(Context.ACTIVITY_SERVICE); + am.killBackgroundProcesses(ALIPAY); + am.killBackgroundProcesses(ALIPAY_EXT); + } + + @Override + protected boolean canRead() { + return mAlipayNewPedometerFile.canRead() && mAlipayNewPedometerPrivateFile.canRead(); + } + + @Override + protected boolean canWrite() { + return mAlipayNewPedometerFile.canWrite() && mAlipayNewPedometerPrivateFile.canWrite(); + + } + + @Override + public long getLastUploadStep() { + APStepInfo stepInfo = getBaseStep(); + if (stepInfo != null) { + return stepInfo.getSteps(); + } + stepInfo = getLastStepInfoToday(); + if (stepInfo != null) { + return stepInfo.getSteps(); + } + return -1; + } + + @Override + public long getLastUploadTime() { + APStepInfo stepInfo = getBaseStep(); + if (stepInfo != null) { + return stepInfo.getTime(); + } + stepInfo = getLastStepInfoToday(); + if (stepInfo != null) { + return stepInfo.getTime(); + } + return -1; + } + + private APStepInfo getLastRecord() { + if (mNewPedometerPrivateSP == null) { + return null; + } + + String stepRecordStr = mNewPedometerPrivateSP.getString("stepRecord", null); + if (stepRecordStr == null || stepRecordStr.isEmpty()) { + return null; + } + List stepRecord = JSON.parseArray(stepRecordStr, APStepInfo.class); + if (stepRecord == null || stepRecord.isEmpty()) { + return null; + } + return stepRecord.get(stepRecord.size() - 1); + } + + @Override + public long getLastSaveTime() { + APStepInfo lastRecord = getLastRecord(); + if (lastRecord != null) { + return lastRecord.getTime(); + } else { + return -1; + } + } + + @Override + public long getLastSaveSensorStep() { + APStepInfo lastRecord = getLastRecord(); + if (lastRecord != null) { + return lastRecord.getSteps(); + } else { + return -1; + } + } + + @Override + public boolean isLoaded() { + return mNewPedometerSP != null && mNewPedometerPrivateSP != null; + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/utils/StepCounterSensorListener.java b/app/src/main/java/me/iweizi/stepchanger/utils/StepCounterSensorListener.java new file mode 100644 index 0000000..34da5aa --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/utils/StepCounterSensorListener.java @@ -0,0 +1,59 @@ +package me.iweizi.stepchanger.utils; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; + +/** + * Created by iweiz on 2017/9/5. + * 计步传感器事件监听类,用于获取当前传感器步数 + */ + +public class StepCounterSensorListener implements SensorEventListener { + + private static StepCounterSensorListener sStepCounterSensorListener; + private final SensorManager mSensorManager; + private int mStep; + + private StepCounterSensorListener(Context context) { + mStep = -1; + mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + } + + public static StepCounterSensorListener get(Context context) { + if (sStepCounterSensorListener == null) { + sStepCounterSensorListener = new StepCounterSensorListener(context); + } + return sStepCounterSensorListener; + } + + public void register() { + if (mSensorManager == null) { + return; + } + Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); + mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL); + } + + public void unregister() { + if (mSensorManager == null) { + return; + } + mSensorManager.unregisterListener(this); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + + @Override + public void onSensorChanged(SensorEvent event) { + mStep = (int) event.values[0]; + } + + public int getStep() { + return mStep; + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/wechat/StepCounterCfg.java b/app/src/main/java/me/iweizi/stepchanger/wechat/StepCounterCfg.java new file mode 100644 index 0000000..17fdc6e --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/wechat/StepCounterCfg.java @@ -0,0 +1,166 @@ +package me.iweizi.stepchanger.wechat; + +import android.annotation.SuppressLint; +import android.app.ActivityManager; +import android.content.Context; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; + +import me.iweizi.stepchanger.R; +import me.iweizi.stepchanger.StepData; + +/** + * Created by iweiz on 2017/9/4. + * 微信的步数数据类 + */ + +class StepCounterCfg extends StepData { + private static final int CURRENT_TODAY_STEP = 201; + private static final int PRE_SENSOR_STEP = 203; + private static final int LAST_SAVE_STEP_TIME = 204; +/* + static final int BEGIN_OF_TODAY = 202; + static final int REBOOT_TIME = 205; + static final int SENSOR_TIME_STAMP = 209; +*/ + private static final int LAST_UPLOAD_TIME = 3; + private static final int LAST_UPLOAD_STEP = 4; + + @SuppressLint("SdCardPath") + private static final String STEP_COUNTER_CFG = "/data/data/com.tencent.mm/MicroMsg/stepcounter.cfg"; + @SuppressLint("SdCardPath") + private static final String MM_STEP_COUNTER_CFG = "/data/data/com.tencent.mm/MicroMsg/MM_stepcounter.cfg"; + private static final String WECHAT = "com.tencent.mm"; + private static final StepCounterCfg sStepCounterCfg = new StepCounterCfg(); + private final File mStepCounterCfgFile; + private final File mMMStepCounterCfgFile; + private HashMap mStepCounterMap = null; + private HashMap mMMStepCounterMap = null; + + private StepCounterCfg() { + super(); + + mStepCounterCfgFile = new File(STEP_COUNTER_CFG); + mMMStepCounterCfgFile = new File(MM_STEP_COUNTER_CFG); + + ROOT_CMD = new String[]{ + "chmod o+rw " + mStepCounterCfgFile.getAbsolutePath(), + "chmod o+rw " + mMMStepCounterCfgFile.getAbsolutePath(), + "chmod o+x " + mStepCounterCfgFile.getParent(), + "chmod o+x " + mMMStepCounterCfgFile.getParent() + }; + mLoadButtonId = R.id.wechat_load_button; + mStoreButtonId = R.id.wechat_store_button; + } + + static StepCounterCfg get() { + return sStepCounterCfg; + } + + @Override + protected int read(Context context) { + FileInputStream fis; + ObjectInputStream ois; + + try { + + fis = new FileInputStream(mStepCounterCfgFile); + ois = new ObjectInputStream(fis); + //noinspection unchecked + mStepCounterMap = (HashMap) ois.readObject(); + ois.close(); + fis.close(); + + fis = new FileInputStream(mMMStepCounterCfgFile); + ois = new ObjectInputStream(fis); + //noinspection unchecked + mMMStepCounterMap = (HashMap) ois.readObject(); + return SUCCESS; + } catch (Exception e) { + return FAIL; + } + } + + + @Override + protected int write(Context context) { + FileOutputStream fos; + ObjectOutputStream oos; + + if (mStepCounterMap == null) { + return FAIL; + } + try { + ActivityManager am = (ActivityManager) + context.getSystemService(Context.ACTIVITY_SERVICE); + am.killBackgroundProcesses(WECHAT); + fos = new FileOutputStream(STEP_COUNTER_CFG); + oos = new ObjectOutputStream(fos); + mStepCounterMap.put(CURRENT_TODAY_STEP, getStep()); + oos.writeObject(mStepCounterMap); + oos.close(); + fos.close(); + return SUCCESS; + } catch (Exception e) { + return FAIL; + } + } + + @Override + protected boolean canRead() { + return mStepCounterCfgFile.canRead() && mMMStepCounterCfgFile.canRead(); + } + + @Override + protected boolean canWrite() { + return mStepCounterCfgFile.canWrite() && mMMStepCounterCfgFile.canWrite(); + } + + @Override + public long getLastUploadStep() { + if (mMMStepCounterMap != null) { + //noinspection unchecked + return ((HashMap) mMMStepCounterMap).get(LAST_UPLOAD_STEP); + } else { + return -1; + } + } + + @Override + public long getLastUploadTime() { + if (mMMStepCounterMap != null) { + //noinspection unchecked + return ((HashMap) mMMStepCounterMap).get(LAST_UPLOAD_TIME); + } else { + return -1; + } + } + + @Override + public long getLastSaveTime() { + if (mStepCounterMap != null) { + return mStepCounterMap.get(LAST_SAVE_STEP_TIME); + } else { + return -1; + } + } + + @Override + public long getLastSaveSensorStep() { + if (mStepCounterMap != null) { + return mStepCounterMap.get(PRE_SENSOR_STEP); + } else { + return -1; + } + } + + @Override + public boolean isLoaded() { + return mMMStepCounterMap != null && mStepCounterMap != null; + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/wechat/WechatDetailsActivity.java b/app/src/main/java/me/iweizi/stepchanger/wechat/WechatDetailsActivity.java new file mode 100644 index 0000000..ac3c7dc --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/wechat/WechatDetailsActivity.java @@ -0,0 +1,16 @@ +package me.iweizi.stepchanger.wechat; + +import android.os.Bundle; + +import me.iweizi.stepchanger.BaseDetailsActivity; +import me.iweizi.stepchanger.R; + +public class WechatDetailsActivity extends BaseDetailsActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + mLayoutId = R.layout.activity_wechat_details; + mStepData = StepCounterCfg.get(); + super.onCreate(savedInstanceState); + } +} diff --git a/app/src/main/java/me/iweizi/stepchanger/wechat/WechatFragment.java b/app/src/main/java/me/iweizi/stepchanger/wechat/WechatFragment.java new file mode 100644 index 0000000..04bd3bd --- /dev/null +++ b/app/src/main/java/me/iweizi/stepchanger/wechat/WechatFragment.java @@ -0,0 +1,33 @@ +package me.iweizi.stepchanger.wechat; + +import android.os.Bundle; +import android.view.View; + +import me.iweizi.stepchanger.BaseFragment; +import me.iweizi.stepchanger.R; + +public class WechatFragment extends BaseFragment { + + public WechatFragment() { + mLayoutId = R.layout.fragment_wechat; + mStepData = StepCounterCfg.get(); + mDetailsClass = WechatDetailsActivity.class; + } + + public static WechatFragment newInstance() { + WechatFragment fragment = new WechatFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + @Override + protected void findView(View view) { + mLoadButton = view.findViewById(R.id.wechat_load_button); + mStoreButton = view.findViewById(R.id.wechat_store_button); + mDetailsButton = view.findViewById(R.id.wechat_details_button); + mStepIncImageButton = view.findViewById(R.id.wechat_add_button); + mStepDecImageButton = view.findViewById(R.id.wechat_sub_button); + mCurrentTodayStepEditText = view.findViewById(R.id.wechat_current_today_step_edit_text); + } +} diff --git a/app/src/main/res/drawable-hdpi/alipay_icon.png b/app/src/main/res/drawable-hdpi/alipay_icon.png new file mode 100644 index 0000000..79d28a2 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/alipay_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/alipay_icon_round.png b/app/src/main/res/drawable-hdpi/alipay_icon_round.png new file mode 100644 index 0000000..f6feb06 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/alipay_icon_round.png differ diff --git a/app/src/main/res/drawable-hdpi/alipay_icon_transparent.png b/app/src/main/res/drawable-hdpi/alipay_icon_transparent.png new file mode 100644 index 0000000..7b19dd9 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/alipay_icon_transparent.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_add.png b/app/src/main/res/drawable-hdpi/ic_action_add.png new file mode 100644 index 0000000..8517212 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_add.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_sub.png b/app/src/main/res/drawable-hdpi/ic_action_sub.png new file mode 100644 index 0000000..c5803b2 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_sub.png differ diff --git a/app/src/main/res/drawable-hdpi/wechat_icon.png b/app/src/main/res/drawable-hdpi/wechat_icon.png new file mode 100644 index 0000000..8b4814c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/wechat_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/wechat_icon_round.png b/app/src/main/res/drawable-hdpi/wechat_icon_round.png new file mode 100644 index 0000000..2628c48 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/wechat_icon_round.png differ diff --git a/app/src/main/res/drawable-hdpi/wechat_icon_transparent.png b/app/src/main/res/drawable-hdpi/wechat_icon_transparent.png new file mode 100644 index 0000000..ac1d482 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/wechat_icon_transparent.png differ diff --git a/app/src/main/res/drawable-mdpi/alipay_icon.png b/app/src/main/res/drawable-mdpi/alipay_icon.png new file mode 100644 index 0000000..95fac95 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/alipay_icon.png differ diff --git a/app/src/main/res/drawable-mdpi/alipay_icon_round.png b/app/src/main/res/drawable-mdpi/alipay_icon_round.png new file mode 100644 index 0000000..7bc253f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/alipay_icon_round.png differ diff --git a/app/src/main/res/drawable-mdpi/alipay_icon_transparent.png b/app/src/main/res/drawable-mdpi/alipay_icon_transparent.png new file mode 100644 index 0000000..7c9cbf7 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/alipay_icon_transparent.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_add.png b/app/src/main/res/drawable-mdpi/ic_action_add.png new file mode 100644 index 0000000..b13ffb5 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_add.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_sub.png b/app/src/main/res/drawable-mdpi/ic_action_sub.png new file mode 100644 index 0000000..402110b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_sub.png differ diff --git a/app/src/main/res/drawable-mdpi/wechat_icon.png b/app/src/main/res/drawable-mdpi/wechat_icon.png new file mode 100644 index 0000000..509bea9 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/wechat_icon.png differ diff --git a/app/src/main/res/drawable-mdpi/wechat_icon_round.png b/app/src/main/res/drawable-mdpi/wechat_icon_round.png new file mode 100644 index 0000000..f5703c0 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/wechat_icon_round.png differ diff --git a/app/src/main/res/drawable-mdpi/wechat_icon_transparent.png b/app/src/main/res/drawable-mdpi/wechat_icon_transparent.png new file mode 100644 index 0000000..692872c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/wechat_icon_transparent.png differ diff --git a/app/src/main/res/drawable-xhdpi/alipay_icon.png b/app/src/main/res/drawable-xhdpi/alipay_icon.png new file mode 100644 index 0000000..1303c77 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/alipay_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/alipay_icon_round.png b/app/src/main/res/drawable-xhdpi/alipay_icon_round.png new file mode 100644 index 0000000..f64452a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/alipay_icon_round.png differ diff --git a/app/src/main/res/drawable-xhdpi/alipay_icon_transparent.png b/app/src/main/res/drawable-xhdpi/alipay_icon_transparent.png new file mode 100644 index 0000000..593d951 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/alipay_icon_transparent.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_add.png b/app/src/main/res/drawable-xhdpi/ic_action_add.png new file mode 100644 index 0000000..cbe4b60 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_add.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_sub.png b/app/src/main/res/drawable-xhdpi/ic_action_sub.png new file mode 100644 index 0000000..fc000db Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_sub.png differ diff --git a/app/src/main/res/drawable-xhdpi/wechat_icon.png b/app/src/main/res/drawable-xhdpi/wechat_icon.png new file mode 100644 index 0000000..d55bc87 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/wechat_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/wechat_icon_round.png b/app/src/main/res/drawable-xhdpi/wechat_icon_round.png new file mode 100644 index 0000000..f41cfe7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/wechat_icon_round.png differ diff --git a/app/src/main/res/drawable-xhdpi/wechat_icon_transparent.png b/app/src/main/res/drawable-xhdpi/wechat_icon_transparent.png new file mode 100644 index 0000000..9447ca4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/wechat_icon_transparent.png differ diff --git a/app/src/main/res/drawable-xxhdpi/alipay_icon.png b/app/src/main/res/drawable-xxhdpi/alipay_icon.png new file mode 100644 index 0000000..c080033 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/alipay_icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/alipay_icon_round.png b/app/src/main/res/drawable-xxhdpi/alipay_icon_round.png new file mode 100644 index 0000000..c36bb68 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/alipay_icon_round.png differ diff --git a/app/src/main/res/drawable-xxhdpi/alipay_icon_transparent.png b/app/src/main/res/drawable-xxhdpi/alipay_icon_transparent.png new file mode 100644 index 0000000..2755a98 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/alipay_icon_transparent.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_add.png b/app/src/main/res/drawable-xxhdpi/ic_action_add.png new file mode 100644 index 0000000..d97861c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_add.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_sub.png b/app/src/main/res/drawable-xxhdpi/ic_action_sub.png new file mode 100644 index 0000000..9958832 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_sub.png differ diff --git a/app/src/main/res/drawable-xxhdpi/wechat_icon.png b/app/src/main/res/drawable-xxhdpi/wechat_icon.png new file mode 100644 index 0000000..dd0dd4e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/wechat_icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/wechat_icon_round.png b/app/src/main/res/drawable-xxhdpi/wechat_icon_round.png new file mode 100644 index 0000000..eafa38c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/wechat_icon_round.png differ diff --git a/app/src/main/res/drawable-xxhdpi/wechat_icon_transparent.png b/app/src/main/res/drawable-xxhdpi/wechat_icon_transparent.png new file mode 100644 index 0000000..02bc80f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/wechat_icon_transparent.png differ diff --git a/app/src/main/res/drawable/shadow.xml b/app/src/main/res/drawable/shadow.xml new file mode 100644 index 0000000..7a36204 --- /dev/null +++ b/app/src/main/res/drawable/shadow.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_alipay_details.xml b/app/src/main/res/layout/activity_alipay_details.xml new file mode 100644 index 0000000..116bfda --- /dev/null +++ b/app/src/main/res/layout/activity_alipay_details.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..59f904f --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_wechat_details.xml b/app/src/main/res/layout/activity_wechat_details.xml new file mode 100644 index 0000000..c8b1b15 --- /dev/null +++ b/app/src/main/res/layout/activity_wechat_details.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/content_details.xml b/app/src/main/res/layout/content_details.xml new file mode 100644 index 0000000..103f95d --- /dev/null +++ b/app/src/main/res/layout/content_details.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +