commit 779c2393e5da34cbfaff75a8bd235ce10e6b8169 Author: 杨万里 <1726150332@qq.com> Date: Mon Mar 9 09:31:52 2026 +0800 first commit: upload android project diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/.gitignore @@ -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 diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..23a89bb --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a8b9fd1 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d5d35ec --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..4f36ed1 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,61 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 30 + defaultConfig { + applicationId "com.example.uhf" + minSdkVersion 26 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + //testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + signingConfigs { + debug { + File strFile = new File("/chainway.keystore") + storeFile file(strFile) + storePassword "123456" + keyPassword "123456" + keyAlias "chainway" + } + release { + File strFile = new File("/chainway.keystore") + storeFile file(strFile) + storePassword "123456" + keyPassword "123456" + keyAlias "chainway" + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } + compileOptions { + sourceCompatibility = '1.8' + targetCompatibility = '1.8' + } + productFlavors { + } +} + +repositories { + flatDir { + dirs 'libs' + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + + implementation files('libs/xUtils-2.5.5.jar') //implementation files('org.xutils:xutils:2.5.+') + implementation files('libs/jxl.jar') + implementation(name: 'DeviceAPI_ver20210618', ext: 'aar') + + //compile 'com.android.support:support-v4:18.0.0' + implementation 'androidx.appcompat:appcompat:1.2.+' + implementation 'androidx.constraintlayout:constraintlayout:2.0.+' +} diff --git a/app/chainway.keystore b/app/chainway.keystore new file mode 100644 index 0000000..4f3e1c7 Binary files /dev/null and b/app/chainway.keystore differ diff --git a/app/libs/DeviceAPI_ver20210618.aar b/app/libs/DeviceAPI_ver20210618.aar new file mode 100644 index 0000000..9c8178a Binary files /dev/null and b/app/libs/DeviceAPI_ver20210618.aar differ diff --git a/app/libs/IGLBarDecoder.jar b/app/libs/IGLBarDecoder.jar new file mode 100644 index 0000000..29fa68c Binary files /dev/null and b/app/libs/IGLBarDecoder.jar differ diff --git a/app/libs/jxl.jar b/app/libs/jxl.jar new file mode 100644 index 0000000..e759c9d Binary files /dev/null and b/app/libs/jxl.jar differ diff --git a/app/libs/xUtils-2.5.5.jar b/app/libs/xUtils-2.5.5.jar new file mode 100644 index 0000000..3cdf65b Binary files /dev/null and b/app/libs/xUtils-2.5.5.jar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..2e2cc49 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,18 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in D:\soft\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 *; +#} +-keep class * extends java.lang.annotation.Annotation { *; } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a39d77f --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/example/uhf/activity/BaseTabFragmentActivity.java b/app/src/main/java/com/example/uhf/activity/BaseTabFragmentActivity.java new file mode 100644 index 0000000..b73a665 --- /dev/null +++ b/app/src/main/java/com/example/uhf/activity/BaseTabFragmentActivity.java @@ -0,0 +1,288 @@ +package com.example.uhf.activity; + +import android.app.ActionBar; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuInflater; +import android.widget.Toast; + +import com.example.uhf.R; +import com.example.uhf.adapter.ViewPagerAdapter; +import com.example.uhf.fragment.KeyDwonFragment; +import com.example.uhf.tools.UIHelper; +import com.example.uhf.widget.NoScrollViewPager; +import com.rscja.deviceapi.RFIDWithUHFUART; +import com.rscja.utility.StringUtility; + +import java.util.ArrayList; +import java.util.List; + +import androidx.fragment.app.FragmentActivity; + +/** + * Created by wskyo on 2021-06-18. + */ +public class BaseTabFragmentActivity extends FragmentActivity { + + private final int offscreenPage = 2; + + protected ActionBar mActionBar; + + protected NoScrollViewPager mViewPager; + protected ViewPagerAdapter mViewPagerAdapter; + + protected List lstFrg = new ArrayList(); + protected List lstTitles = new ArrayList(); + + // public Reader mReader; + public RFIDWithUHFUART mReader; + private int index = 0; + + private ActionBar.Tab tab_kill, tab_lock, tab_set; + private DisplayMetrics metrics; + private AlertDialog dialog; + private long[] timeArr; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + public void initUHF() { + + mActionBar = getActionBar(); + mActionBar.setDisplayShowTitleEnabled(true); + mActionBar.setDisplayShowHomeEnabled(true); + mActionBar.setDisplayHomeAsUpEnabled(true); + mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + try { + mReader = RFIDWithUHFUART.getInstance(); + } catch (Exception ex) { + + toastMessage(ex.getMessage()); + return; + } + + if (mReader != null) { + new InitTask().execute(); + } + } + + protected void initViewPageData() { + + } + + /** + * ����ActionBar + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // TODO Auto-generated method stub + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main, menu); + return true; +// return super.onCreateOptionsMenu(menu); + } + + protected void initViewPager() { + + mViewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), lstFrg, lstTitles); + + mViewPager = (NoScrollViewPager) findViewById(R.id.pager); + mViewPager.setAdapter(mViewPagerAdapter); + mViewPager.setOffscreenPageLimit(offscreenPage); + } + + protected void initTabs() { + for (int i = 0; i < mViewPagerAdapter.getCount() - 3; ++i) { + mActionBar.addTab(mActionBar.newTab().setText(mViewPagerAdapter.getPageTitle(i)).setTabListener(mTabListener)); + } + tab_kill = mActionBar.newTab().setText(mViewPagerAdapter.getPageTitle(3)).setTabListener(mTabListener); + tab_lock = mActionBar.newTab().setText(mViewPagerAdapter.getPageTitle(4)).setTabListener(mTabListener); + tab_set = mActionBar.newTab().setText(mViewPagerAdapter.getPageTitle(5)).setTabListener(mTabListener); + + //��Ӳ˵� +// mActionBar.addTab(mActionBar.newTab().setText(getString(R.string.myMenu)).setTabListener(mTabListener)); + } + + protected ActionBar.TabListener mTabListener = new ActionBar.TabListener() { + + @Override + public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) { + if (mActionBar.getTabCount() > 3 && tab.getPosition() != 3) { + mActionBar.removeTabAt(3); + } + if (tab.getPosition() == 3) { + mViewPager.setCurrentItem(index, false); + } else { + mViewPager.setCurrentItem(tab.getPosition()); + } + } + + @Override + public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) { + + } + + @Override + public void onTabReselected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) { + + } + }; + + public boolean onOptionsItemSelected(android.view.MenuItem item) { + // + if (mActionBar.getSelectedTab().getText().equals(item.getTitle())) { + return true; + } + if (mActionBar.getTabCount() > 3 && item.getItemId() != android.R.id.home && item.getItemId() != R.id.UHF_ver) { + mActionBar.removeTabAt(3); + } + switch (item.getItemId()) { + case android.R.id.home: + finish(); + break; + case R.id.action_kill: + index = 3; + mActionBar.addTab(tab_kill, true); + break; + case R.id.action_lock: + index = 4; + mActionBar.addTab(tab_lock, true); + break; + case R.id.action_set: + index = 5; + mActionBar.addTab(tab_set, true); + break; + + case R.id.UHF_ver: + getUHFVersion(); + break; + default: + break; + } + + return true; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + + if (keyCode == 139 || keyCode == 280 || keyCode == 293) { + Log.e("TAG", "onKeyDown: "+ keyCode); + if (event.getRepeatCount() == 0) { + + if (mViewPager != null) { + + KeyDwonFragment sf = (KeyDwonFragment) mViewPagerAdapter.getItem(mViewPager.getCurrentItem()); + sf.myOnKeyDwon(); + + } + } + return true; + } + + return super.onKeyDown(keyCode, event); + } + + public void gotoActivity(Intent it) { + startActivity(it); + } + + public void gotoActivity(Class clz) { + Intent it = new Intent(this, clz); + gotoActivity(it); + } + + public void toastMessage(String msg) { + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + public void toastMessage(int resId) { + Toast.makeText(this, resId, Toast.LENGTH_SHORT).show(); + } + + /** + * �豸�ϵ��첽�� + * + * @author liuruifeng + */ + public class InitTask extends AsyncTask { + ProgressDialog mypDialog; + + @Override + protected Boolean doInBackground(String... params) { + // TODO Auto-generated method stub + return mReader.init(); + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + + mypDialog.cancel(); + + if (!result) { + Toast.makeText(BaseTabFragmentActivity.this, "init fail", Toast.LENGTH_SHORT).show(); + } + } + + @Override + protected void onPreExecute() { + // TODO Auto-generated method stub + super.onPreExecute(); + + mypDialog = new ProgressDialog(BaseTabFragmentActivity.this); + mypDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); + mypDialog.setMessage("init..."); + mypDialog.setCanceledOnTouchOutside(false); + mypDialog.show(); + } + } + + @Override + protected void onDestroy() { + + if (mReader != null) { + mReader.free(); + } + super.onDestroy(); + } + + /** + * ��֤ʮ����������Ƿ���ȷ + * + * @param str + * @return + */ + public boolean vailHexInput(String str) { + + if (str == null || str.length() == 0) { + return false; + } + + // ���ȱ�����ż�� + if (str.length() % 2 == 0) { + return StringUtility.isHexNumberRex(str); + } + + return false; + } + + public void getUHFVersion() { + + if (mReader != null) { + + String rfidVer = mReader.getVersion();//.getHardwareType(); + UIHelper.alert(this, R.string.action_uhf_ver, rfidVer, R.drawable.webtext); + } + } + +} diff --git a/app/src/main/java/com/example/uhf/activity/UHFMainActivity.java b/app/src/main/java/com/example/uhf/activity/UHFMainActivity.java new file mode 100644 index 0000000..2eb5be8 --- /dev/null +++ b/app/src/main/java/com/example/uhf/activity/UHFMainActivity.java @@ -0,0 +1,205 @@ +package com.example.uhf.activity; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.media.AudioManager; +import android.media.SoundPool; +import android.os.AsyncTask; +import android.os.Bundle; +import android.widget.Toast; + +import com.example.uhf.R; +import com.example.uhf.fragment.UHFKillFragment; +import com.example.uhf.fragment.UHFLockFragment; +import com.example.uhf.fragment.UHFReadFragment; +import com.example.uhf.fragment.UHFReadTagFragment; +import com.example.uhf.fragment.UHFSetFragment; +import com.example.uhf.fragment.UHFWriteFragment; +import com.rscja.utility.StringUtility; + +import java.util.HashMap; + +/** + * UHF使用demo + * + * 1、使用前请确认您的机器已安装此模块。 + * 2、要正常使用模块需要在\libs\armeabi\目录放置libDeviceAPI.so文件,同时在\libs\DeviceAPI_ver20210618.aar文件。 + * 3、在操作设备前需要调用 init()打开设备,使用完后调用 free() 关闭设备 + * + * + * 更多函数的使用方法请查看API说明文档 + * + * @author + * 更新于 2021年6月21日 + */ +public class UHFMainActivity extends BaseTabFragmentActivity { + + public final static String TAG = "MainActivity"; +// public AppContext appContext;// ȫ��Context +// + // public Reader mReader; +//public RFIDWithUHF mReader; + +// public void playSound(int id) { +// appContext.playSound(id); +// } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + +// if (Build.VERSION.SDK_INT > 21) { +// +// +// //读写内存权限 +// if (ContextCompat.checkSelfPermission(this, +// Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { +// // 请求权限 +// ActivityCompat +// .requestPermissions( +// this, +// new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, +// 1); +// } +// +// int checkCallPhonePermission = ContextCompat.checkSelfPermission( +// this, Manifest.permission.READ_EXTERNAL_STORAGE); +// if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) { +// ActivityCompat.requestPermissions(this, new String[]{ +// Manifest.permission.WRITE_EXTERNAL_STORAGE, +// Manifest.permission.READ_EXTERNAL_STORAGE,}, 1); +// return; +// } else { +// // 已申请权限直接跳转到下一个界面 +// +// +// } +// } + +// appContext = (AppContext) getApplication(); + initSound(); + initUHF(); // + initViewPageData(); + initViewPager(); + initTabs(); + + } + + @Override + protected void initViewPageData() { + lstFrg.add(new UHFReadTagFragment()); + lstFrg.add(new UHFReadFragment()); + lstFrg.add(new UHFWriteFragment()); + lstFrg.add(new UHFKillFragment()); + lstFrg.add(new UHFLockFragment()); + lstFrg.add(new UHFSetFragment()); + + lstTitles.add(getString(R.string.uhf_msg_tab_scan)); + lstTitles.add(getString(R.string.uhf_msg_tab_read)); + lstTitles.add(getString(R.string.uhf_msg_tab_write)); + lstTitles.add(getString(R.string.uhf_msg_tab_kill)); + lstTitles.add(getString(R.string.uhf_msg_tab_lock)); + lstTitles.add(getString(R.string.uhf_msg_tab_set)); + } + + @Override + protected void onDestroy() { + + if (mReader != null) { + mReader.free(); + } + super.onDestroy(); + } + + /** + * �豸�ϵ��첽�� + * + * @author liuruifeng + */ + public class InitTask extends AsyncTask { + ProgressDialog mypDialog; + + @Override + protected Boolean doInBackground(String... params) { + // TODO Auto-generated method stub + return mReader.init(); + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + mypDialog.cancel(); + + if (!result) { + Toast.makeText(UHFMainActivity.this, "init fail", Toast.LENGTH_SHORT).show(); + } + } + + @Override + protected void onPreExecute() { + // TODO Auto-generated method stub + super.onPreExecute(); + + mypDialog = new ProgressDialog(UHFMainActivity.this); + mypDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); + mypDialog.setMessage("init..."); + mypDialog.setCanceledOnTouchOutside(false); + mypDialog.show(); + } + } + + /** + * ��֤ʮ����������Ƿ���ȷ + * + * @param str + * @return + */ + public boolean vailHexInput(String str) { + + if (str == null || str.length() == 0) { + return false; + } + + // ���ȱ�����ż�� + if (str.length() % 2 == 0) { + return StringUtility.isHexNumberRex(str); + } + + return false; + } + + private HashMap soundMap = new HashMap(); + private SoundPool soundPool; + private float volumnRatio; + private AudioManager am; + + private void initSound() { + soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 5); + soundMap.put(1, soundPool.load(this, R.raw.barcodebeep, 1)); + soundMap.put(2, soundPool.load(this, R.raw.serror, 1)); + am = (AudioManager) this.getSystemService(AUDIO_SERVICE);// 实例化AudioManager对象 + } + + /** + * 播放提示音 + * + * @param id 成功1,失败2 + */ + public void playSound(int id) { + + float audioMaxVolumn = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); // 返回当前AudioManager对象的最大音量值 + float audioCurrentVolumn = am.getStreamVolume(AudioManager.STREAM_MUSIC);// 返回当前AudioManager对象的音量值 + volumnRatio = audioCurrentVolumn / audioMaxVolumn; + try { + soundPool.play(soundMap.get(id), volumnRatio, // 左声道音量 + volumnRatio, // 右声道音量 + 1, // 优先级,0为最低 + 0, // 循环次数,0无不循环,-1无永远循环 + 1 // 回放速度 ,该值在0.5-2.0之间,1为正常速度 + ); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/example/uhf/adapter/ViewPagerAdapter.java b/app/src/main/java/com/example/uhf/adapter/ViewPagerAdapter.java new file mode 100644 index 0000000..30ffbd5 --- /dev/null +++ b/app/src/main/java/com/example/uhf/adapter/ViewPagerAdapter.java @@ -0,0 +1,48 @@ +package com.example.uhf.adapter; + + +import com.example.uhf.fragment.KeyDwonFragment; + +import java.util.ArrayList; +import java.util.List; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; + +/** + * Created by Administrator on 2021/6/22. + */ +public class ViewPagerAdapter extends FragmentPagerAdapter { + + private List lstFrg = new ArrayList(); + private List lstTitles = new ArrayList(); + + public ViewPagerAdapter(FragmentManager fm, List fragments, List titles) { + super(fm); + + lstFrg = fragments; + lstTitles = titles; + } + + @Override + public Fragment getItem(int position) { + if (lstFrg.size() > 0) { + return lstFrg.get(position); + } + throw new IllegalStateException("No fragment at position " + position); + } + + @Override + public int getCount() { + return lstFrg.size(); + } + + @Override + public CharSequence getPageTitle(int position) { + if (lstTitles.size() > 0) { + return lstTitles.get(position); + } + return null; + } +} diff --git a/app/src/main/java/com/example/uhf/fragment/FileImport.java b/app/src/main/java/com/example/uhf/fragment/FileImport.java new file mode 100644 index 0000000..b78326e --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/FileImport.java @@ -0,0 +1,109 @@ +package com.example.uhf.fragment; + +import android.os.Environment; +import android.util.Log; + +import com.example.uhf.activity.UHFMainActivity; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +/** + * Created by Administrator on 2021/6/22. + */ + +public class FileImport { + static String xlsFilePath = Environment.getExternalStorageDirectory() + "/outxmldata/"; + + public static boolean daochu(String tmpname, ArrayList> lists2) { + + try { + + String file = ""; + if (tmpname.isEmpty()) + file = xlsFilePath + "xls" + + GetTimesyyyymmddhhmmss() + ".xls"; + else + file = xlsFilePath + tmpname; + File path2 = new File(xlsFilePath); + + if (path2.mkdirs()) { + + } + List al22 = new ArrayList(); + List al2 = new ArrayList(); + al2.add("编号"); + + // al2.add("筛选栏"); + + al22.add(al2); + FileXls.writeXLS(file, al22); + List ac = new ArrayList(); + + int adds = -1; + String id = ""; + // String sxl = ""; + for (int i = 0; i < lists2.size(); i++) { + List al = new ArrayList(); + Set> sets = lists2.get(i).entrySet(); + + + for (Entry entry : sets) { + + if (entry.getKey().equals("tagUii")) { + id = entry.getValue().toString(); + id = id.replace("EPC:", ""); + id = id.replace("TID:", ""); + id = id.substring(0, 12); + } else { + } + // Object value=entry.getValue(); + } + al.add(id); + + // al.add(sxl); + ac.add(al); + } + + return FileXls.writeXLS(file, ac); + } catch (Exception ex) { + Log.i(UHFMainActivity.TAG, "导出异常=" + ex.getMessage()); + return false; + } + } + + public static String GetTimesyyyymmdd() { + + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + Date curDate = new Date(System.currentTimeMillis());// 获取当前时间 + String dt = formatter.format(curDate); + + return dt; + + } + + public static String GetTimesddMMyy() { + + SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yy"); + Date curDate = new Date(System.currentTimeMillis());// 获取当前时间 + String dt = formatter.format(curDate); + + return dt; + + } + + public static String GetTimesyyyymmddhhmmss() { + + SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss"); + Date curDate = new Date(System.currentTimeMillis());// 获取当前时间 + String dt = formatter.format(curDate); + + return dt; + + } +} diff --git a/app/src/main/java/com/example/uhf/fragment/FileXls.java b/app/src/main/java/com/example/uhf/fragment/FileXls.java new file mode 100644 index 0000000..4b2d1c1 --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/FileXls.java @@ -0,0 +1,260 @@ +package com.example.uhf.fragment; + +import android.util.Xml; + +import org.xmlpull.v1.XmlPullParser; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import jxl.Cell; +import jxl.CellType; +import jxl.DateCell; +import jxl.NumberCell; +import jxl.Sheet; +import jxl.Workbook; +import jxl.read.biff.BiffException; +import jxl.write.Label; +import jxl.write.WritableSheet; +import jxl.write.WritableWorkbook; +import jxl.write.WriteException; +import jxl.write.biff.RowsExceededException; +/** + * Created by Administrator on 2018/7/25. + */ + +public class FileXls { + + private static final int DEFAULT_SHEET = 0; + + public static String readXLS(String path) { + String str = ""; + + try { + Workbook workbook = Workbook.getWorkbook(new File(path)); + Sheet sheet = workbook.getSheet(0); + int columnCount = sheet.getColumns(); + int rowCount = sheet.getRows(); + + Cell cell = null; + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + cell = sheet.getCell(j, i); + String temp2 = ""; + if (cell.getType() == CellType.NUMBER) { + temp2 = ((NumberCell) cell).getValue() + ""; + } else if (cell.getType() == CellType.DATE) { + temp2 = "" + ((DateCell) cell).getDate(); + } else { + temp2 = "" + cell.getContents(); + } + str = str + " " + temp2; + } + str += "\n"; + } + workbook.close(); + } catch (Exception e) { + } + + return str; + } + + public static ArrayList> readXLSmap(String path) { + String str = ""; + ArrayList> listmap = new ArrayList>(); + try { + Workbook workbook = Workbook.getWorkbook(new File(path)); + Sheet sheet = workbook.getSheet(0); + int columnCount = sheet.getColumns(); + int rowCount = sheet.getRows(); + + Cell cell = null; + for (int i = 1; i < rowCount; i++) { + HashMap map = new HashMap(); + map.put("tagUii", sheet.getCell(0, i).getContents()); + // map.put("jl", sheet.getCell(1, i).getContents()); + + listmap.add(map); + } + workbook.close(); + } catch (Exception e) { + } + + return listmap; + } + + public static List> readXLSX(String path) { + String v = null; + List list = new ArrayList(); + List> table = new ArrayList>(); + + try { + ZipFile file = new ZipFile(new File(path)); + + ZipEntry sharedStringXML = file.getEntry("xl/sharedStrings.xml"); + InputStream inputStream = file.getInputStream(sharedStringXML); + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(inputStream, "utf-8"); + int event = parser.getEventType(); + while (event != XmlPullParser.END_DOCUMENT) { + switch (event) { + case XmlPullParser.START_TAG: + String tag = parser.getName(); + if (tag.equalsIgnoreCase("t")) { + list.add(parser.nextText()); + } + break; + case XmlPullParser.END_TAG: + break; + default: + break; + } + + event = parser.next(); + } + + ZipEntry sheetXML = file.getEntry("xl/worksheets/sheet1.xml"); + InputStream inputStreamsheet = file.getInputStream(sheetXML); + parser = Xml.newPullParser(); + parser.setInput(inputStreamsheet, "utf-8"); + event = parser.getEventType(); + + ArrayList row = null; + boolean isText = false; + while (event != XmlPullParser.END_DOCUMENT) { + + switch (event) { + case XmlPullParser.START_TAG: + String tag = parser.getName(); + + if (tag.equalsIgnoreCase("row")) { + row = new ArrayList(); + table.add(row); + } else if (tag.equalsIgnoreCase("c")) { + String t = parser.getAttributeValue(null, "t"); + + if (t != null) { + isText = true; + } else { + isText = false; + } + } else if (tag.equalsIgnoreCase("v")) { + String cell = parser.nextText(); + + if (cell != null) { + if (isText) { + row.add(list.get(Integer.parseInt(cell))); + } else { + row.add(cell); + } + } + } + break; + case XmlPullParser.END_TAG: + if (parser.getName().equalsIgnoreCase("row") && v != null) { + } + break; + } + + event = parser.next(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return table; + } + + public static boolean writeXLS(String path, List table) { + File file = createXLS(path); + + if (file == null) { + return false; + } else { + + try { + return addData(file, table); + } catch (RowsExceededException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + + } catch (WriteException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + + } + + } + + private static File createXLS(String path) { + + File file = null; + + try { + file = new File(path); + if (file.exists()) + return file; + WritableWorkbook book = Workbook.createWorkbook(file); + WritableSheet sheet = book.createSheet("sheet1", 0); + + book.write(); + book.close(); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + return file; + } + } + + private static boolean addData(File file, List table) + throws IOException, RowsExceededException, WriteException { + + Workbook wb = null; + try { + wb = Workbook.getWorkbook(file); + } catch (BiffException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + WritableWorkbook book = Workbook.createWorkbook(file, wb); + WritableSheet sheet = book.getSheet(0); + // List attrs = table; + int i = sheet.getRows(); + for (int j = 0; j < table.size(); j++) { + List attrs = (List) table.get(j); + for (int attr = 0; attr < attrs.size(); attr++) { + Label label = new Label(attr, i + j, attrs.get(attr)); + sheet.addCell(label); + + } + } + /* + * for (int attr = 0; attr < attrs.size(); attr++) { Label label = new + * Label(attr, i, attrs.get(attr)); sheet.addCell(label); } + */ + + book.write(); + book.close(); + wb.close(); + return true; + + } + + public static final int CREATE_FAIL = -1; + public static final int ADD_DATA_FAIL = -2; +} diff --git a/app/src/main/java/com/example/uhf/fragment/KeyDwonFragment.java b/app/src/main/java/com/example/uhf/fragment/KeyDwonFragment.java new file mode 100644 index 0000000..0c5e919 --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/KeyDwonFragment.java @@ -0,0 +1,15 @@ +package com.example.uhf.fragment; + + +import androidx.fragment.app.Fragment; + +/** + * Created by Administrator on 2015-03-10. + */ +public class KeyDwonFragment extends Fragment { + + public void myOnKeyDwon() { + + } + +} diff --git a/app/src/main/java/com/example/uhf/fragment/UHFKillFragment.java b/app/src/main/java/com/example/uhf/fragment/UHFKillFragment.java new file mode 100644 index 0000000..48b3c1e --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/UHFKillFragment.java @@ -0,0 +1,211 @@ +package com.example.uhf.fragment; + + +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.EditText; +import android.widget.RadioButton; + +import com.example.uhf.R; +import com.example.uhf.activity.UHFMainActivity; +import com.example.uhf.tools.UIHelper; +import com.rscja.deviceapi.entity.UHFTAGInfo; +import com.rscja.deviceapi.interfaces.IUHF; + +import static com.example.uhf.R.id.etPtr_filterK; + + +public class UHFKillFragment extends KeyDwonFragment implements OnClickListener { + + private static final String TAG = "UHFKillFragment"; + private UHFMainActivity mContext; + + private EditText EtTagUii_Write; + private EditText EtAccessPwd_Kill; + private EditText etLen_Read; + private EditText etData_filter; + private EditText etPtr_Read; + + private Button BtUii_Kill; + private Button btnKill; + private CheckBox CkWithUii_Kill; + + private RadioButton rbEPC_filter; + private RadioButton rbTID_filter; + private RadioButton rbUser_filter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.uhf_kill_fragment, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mContext = (UHFMainActivity) getActivity(); + etPtr_Read = (EditText) getView().findViewById(etPtr_filterK); + etLen_Read = (EditText) getView().findViewById(R.id.etLen_filterK); + etData_filter = (EditText) getView().findViewById(R.id.etData_filterK); + EtAccessPwd_Kill = (EditText) getView().findViewById(R.id.EtAccessPwd_Kill); + + CkWithUii_Kill = (CheckBox) getView().findViewById(R.id.CkWithUii_Kill); + btnKill = (Button) getView().findViewById(R.id.btnKill); + + rbEPC_filter = (RadioButton) getView().findViewById(R.id.rbEPC_filterK); + rbTID_filter = (RadioButton) getView().findViewById(R.id.rbTID_filterK); + rbUser_filter = (RadioButton) getView().findViewById(R.id.rbUser_filterK); + + btnKill.setOnClickListener(new btnKillOnClickListener()); + rbEPC_filter.setOnClickListener(this); + rbTID_filter.setOnClickListener(this); + rbUser_filter.setOnClickListener(this); + } + + public class BtUii_WriteClickListener implements OnClickListener { + + @Override + public void onClick(View v) { + + UHFTAGInfo uiiStr = mContext.mReader.inventorySingleTag(); + + if (uiiStr != null) { + EtTagUii_Write.setText(uiiStr.getEPC()); + } else { + EtTagUii_Write.setText(""); + + UIHelper.ToastMessage(mContext, R.string.uhf_msg_read_tag_fail); +// mContext.playSound(2); + } + } + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.rbEPC_filter: + if (rbEPC_filter.isChecked()) { + etPtr_Read.setText("32"); + } + break; + case R.id.rbTID_filter: + if (rbTID_filter.isChecked()) { + etPtr_Read.setText("0"); + } + break; + case R.id.rbUser_filter: + if (rbUser_filter.isChecked()) { + etPtr_Read.setText("0"); + } + break; + + } + + } + + public class btnKillOnClickListener implements OnClickListener { + + @Override + public void onClick(View v) { + + String strPWD = EtAccessPwd_Kill.getText().toString().trim();// 访问密码 + + if (!TextUtils.isEmpty(strPWD)) { + if (strPWD.length() != 8) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_addr_must_len8); + return; + } else if (!mContext.vailHexInput(strPWD)) { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nohex); + return; + } + } else { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nopwd); + return; + } + + if (CkWithUii_Kill.isChecked())// 指定标签 + { + + if (etPtr_Read.getText().toString() == null || etPtr_Read.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据的起始地址不能为空"); + return; + } + if (etData_filter.getText().toString() == null || etData_filter.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据不能为空"); + return; + } + if (etLen_Read.getText().toString() == null || etLen_Read.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据长度不能为空"); + return; + } + + int filterPtr = Integer.parseInt(etPtr_Read.getText().toString()); + String filterData = etData_filter.getText().toString(); + int filterCnt = Integer.parseInt(etLen_Read.getText().toString()); + int filterBank = 0; + if (rbEPC_filter.isChecked()) { + filterBank = IUHF.Bank_EPC; + } else if (rbTID_filter.isChecked()) { + filterBank = IUHF.Bank_TID; + } else if (rbUser_filter.isChecked()) { + filterBank = IUHF.Bank_USER; + + } + + String strUII = EtTagUii_Write.getText().toString().trim(); + if (TextUtils.isEmpty(strUII)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_tag_must_not_null); + return; + } + + if (mContext.mReader.killTag(strPWD, filterBank, filterPtr, filterCnt, filterData)) { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_kill_succ); + mContext.playSound(1); + } else { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_kill_fail); + mContext.playSound(2); + } + + } else { + Boolean strKillUII = mContext.mReader.killTag(strPWD); + if (strKillUII) { + UIHelper.ToastMessage(mContext, strKillUII + " " + getString(R.string.rfid_mgs_kill_succ)); + mContext.playSound(1); + } else { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_kill_fail); +// mContext.playSound(2); + mContext.playSound(2); + } + } + } + } + + public class CkWithUii_WriteCheckedChangedListener implements OnCheckedChangeListener { + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + // TODO Auto-generated method stub + EtTagUii_Write.setText(""); + + if (isChecked) { + BtUii_Kill.setBackgroundResource(R.drawable.button_bg); + BtUii_Kill.setEnabled(true); +// BtUii_Write.setVisibility(View.VISIBLE); + } else { + BtUii_Kill.setBackgroundResource(R.drawable.button_bg_gray); + BtUii_Kill.setEnabled(false); +// BtUii_Write.setVisibility(View.INVISIBLE); + } + } + } + +} diff --git a/app/src/main/java/com/example/uhf/fragment/UHFLockFragment.java b/app/src/main/java/com/example/uhf/fragment/UHFLockFragment.java new file mode 100644 index 0000000..76ad022 --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/UHFLockFragment.java @@ -0,0 +1,304 @@ +package com.example.uhf.fragment; + + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.RadioButton; + +import com.example.uhf.R; +import com.example.uhf.activity.UHFMainActivity; +import com.example.uhf.tools.UIHelper; +import com.rscja.deviceapi.interfaces.IUHF; + + +public class UHFLockFragment extends KeyDwonFragment implements OnClickListener { + + private static final String TAG = "UHFLockFragment"; + private UHFMainActivity mContext; + + private EditText EtAccessPwd_Lock; + private EditText etLockCode; + private EditText etPtr_filter_lock; + private EditText etLen_filter_lock; + private EditText etData_filter_lock; + + private Button btnLock; + private CheckBox cb_filter_lock; + + private RadioButton rbEPC_filter_lock; + private RadioButton rbTID_filter_lock; + private RadioButton rbUser_filter_lock; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.uhf_lock_fragment, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mContext = (UHFMainActivity) getActivity(); + + etLockCode = (EditText) getView().findViewById(R.id.etLockCode); + EtAccessPwd_Lock = (EditText) getView().findViewById(R.id.EtAccessPwd_Lock); + etPtr_filter_lock = (EditText) getView().findViewById(R.id.etPtr_filter_lock); + etLen_filter_lock = (EditText) getView().findViewById(R.id.etLen_filter_lock); + etData_filter_lock = (EditText) getView().findViewById(R.id.etData_filter_lock); + + btnLock = (Button) getView().findViewById(R.id.btnLock); + cb_filter_lock = (CheckBox) getView().findViewById(R.id.cb_filter_lock); + + rbEPC_filter_lock = (RadioButton) getView().findViewById(R.id.rbEPC_filter_lock); + rbTID_filter_lock = (RadioButton) getView().findViewById(R.id.rbTID_filter_lock); + rbUser_filter_lock = (RadioButton) getView().findViewById(R.id.rbUser_filter_lock); + + rbEPC_filter_lock.setOnClickListener(this); + rbTID_filter_lock.setOnClickListener(this); + rbUser_filter_lock.setOnClickListener(this); + + cb_filter_lock.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + String data = etData_filter_lock.getText().toString().trim(); + String rex = "[\\da-fA-F]*"; //匹配正则表达式,数据为十六进制格式 + if (data == null || data.isEmpty() || !data.matches(rex)) { + UIHelper.ToastMessage(mContext, "过滤的数据必须是十六进制数据"); + cb_filter_lock.setChecked(false); + return; + } + } + } + }); + + etLockCode.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + builder.setTitle(R.string.tvLockCode); + final View vv = LayoutInflater.from(mContext).inflate(R.layout.uhf_dialog_lock_code, null); + builder.setView(vv); + builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.dismiss(); + etLockCode.getText().clear(); + } + }); + + builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + RadioButton rbOpen = (RadioButton) vv.findViewById(R.id.rbOpen); + RadioButton rbLock = (RadioButton) vv.findViewById(R.id.rbLock); + CheckBox cbPerm = (CheckBox) vv.findViewById(R.id.cbPerm); + + CheckBox cbKill = (CheckBox) vv.findViewById(R.id.cbKill); + CheckBox cbAccess = (CheckBox) vv.findViewById(R.id.cbAccess); + CheckBox cbEPC = (CheckBox) vv.findViewById(R.id.cbEPC); + CheckBox cbTid = (CheckBox) vv.findViewById(R.id.cbTid); + CheckBox cbUser = (CheckBox) vv.findViewById(R.id.cbUser); + String mask = ""; + String value = ""; + int[] data = new int[20]; + if (cbUser.isChecked()) { + data[11] = 1; + if (cbPerm.isChecked()) { + data[0] = 1; + data[10] = 1; + } + if (rbLock.isChecked()) { + data[1] = 1; + } + } + if (cbTid.isChecked()) { + data[13] = 1; + if (cbPerm.isChecked()) { + data[12] = 1; + data[2] = 1; + } + if (rbLock.isChecked()) { + data[3] = 1; + } + } + if (cbEPC.isChecked()) { + data[15] = 1; + if (cbPerm.isChecked()) { + data[14] = 1; + data[4] = 1; + } + if (rbLock.isChecked()) { + data[5] = 1; + } + } + if (cbAccess.isChecked()) { + data[17] = 1; + if (cbPerm.isChecked()) { + data[16] = 1; + data[6] = 1; + } + if (rbLock.isChecked()) { + data[7] = 1; + } + } + if (cbKill.isChecked()) { + data[19] = 1; + if (cbPerm.isChecked()) { + data[18] = 1; + data[8] = 1; + } + if (rbLock.isChecked()) { + data[9] = 1; + } + } + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append("0000"); + for (int k = data.length - 1; k >= 0; k--) { + stringBuffer.append(data[k] + ""); + } + + String code = binaryString2hexString(stringBuffer.toString()); + Log.i(UHFMainActivity.TAG, " tempCode=" + stringBuffer.toString() + " code=" + code); + + etLockCode.setText(code.replace(" ", "0") + ""); + } + }); + builder.create().show(); + } + }); + +// etLockCode.setOnClickListener(new OnClickListener() { +// @Override +// public void onClick(View view) { +// AlertDialog.Builder builder= new AlertDialog.Builder(mContext); +// +// builder.setTitle(R.string.tvLockCode); +// builder.create().show(); +// } +// }); + + btnLock.setOnClickListener(new btnLockOnClickListener()); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.rbEPC_filter_lock: + etPtr_filter_lock.setText("32"); + break; + case R.id.rbTID_filter_lock: + etPtr_filter_lock.setText("0"); + break; + case R.id.rbUser_filter_lock: + etPtr_filter_lock.setText("0"); + break; + } + } + + public class btnLockOnClickListener implements OnClickListener { + + @Override + public void onClick(View v) { + + String strPWD = EtAccessPwd_Lock.getText().toString().trim();// 访问密码 + String strLockCode = etLockCode.getText().toString().trim(); + + if (!TextUtils.isEmpty(strPWD)) { + if (strPWD.length() != 8) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_addr_must_len8); + return; + } else if (!mContext.vailHexInput(strPWD)) { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nohex); + return; + } + } else { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nopwd); + return; + } + + if (TextUtils.isEmpty(strLockCode)) { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nolockcode); + return; + } + boolean result = false; + if (cb_filter_lock.isChecked()) { + String filterData = etData_filter_lock.getText().toString(); + if (filterData == null || filterData.isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据不能为空!"); + return; + } + if (etPtr_filter_lock.getText().toString() == null || etPtr_filter_lock.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤起始地址不能为空"); + return; + } + if (etLen_filter_lock.getText().toString() == null || etLen_filter_lock.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据长度不能为空"); + return; + } + int filterPtr = Integer.parseInt(etPtr_filter_lock.getText().toString()); + int filterCnt = Integer.parseInt(etLen_filter_lock.getText().toString()); + int filterBank = 0; + if (rbEPC_filter_lock.isChecked()) { + filterBank = IUHF.Bank_EPC; + } else if (rbTID_filter_lock.isChecked()) { + filterBank = IUHF.Bank_TID; + } else if (rbUser_filter_lock.isChecked()) { + filterBank = IUHF.Bank_USER; + } + + if (mContext.mReader.lockMem(strPWD, + filterBank, + filterPtr, + filterCnt, + filterData, + strLockCode)) { + result = true; + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_lock_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_lock_fail); + } + } else { + if (mContext.mReader.lockMem(strPWD, strLockCode)) { + result = true; + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_lock_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_lock_fail); + } + } + if (!result) { + mContext.playSound(2); + } else { + mContext.playSound(1); + } + + } + } + + public static String binaryString2hexString(String bString) { + if (bString == null || bString.equals("") || bString.length() % 8 != 0) + return null; + StringBuffer tmp = new StringBuffer(); + int iTmp = 0; + for (int i = 0; i < bString.length(); i += 4) { + iTmp = 0; + for (int j = 0; j < 4; j++) { + iTmp += Integer.parseInt(bString.substring(i + j, i + j + 1)) << (4 - j - 1); + } + tmp.append(Integer.toHexString(iTmp)); + } + return tmp.toString(); + } + +} diff --git a/app/src/main/java/com/example/uhf/fragment/UHFReadFragment.java b/app/src/main/java/com/example/uhf/fragment/UHFReadFragment.java new file mode 100644 index 0000000..14f4319 --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/UHFReadFragment.java @@ -0,0 +1,277 @@ +package com.example.uhf.fragment; + + +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.Spinner; + +import com.example.uhf.R; +import com.example.uhf.activity.UHFMainActivity; +import com.example.uhf.tools.UIHelper; +import com.rscja.deviceapi.interfaces.IUHF; + +public class UHFReadFragment extends KeyDwonFragment implements OnClickListener { + + private UHFMainActivity mContext; + + private Spinner SpinnerBank_Read; + private Spinner SpinnerOption_Read; + + private EditText EtPtr_Read; + private EditText EtLen_Read; + private EditText EtAccessPwd_Read; + private EditText EtPtr2_Read; + private EditText EtLen2_Read; + private EditText EtData_Read; + private EditText etPtr_filter; + private EditText etData_filter; + private EditText etLen_filter; + + private Button BtRead; + private CheckBox cb_filter; + private CheckBox cb_QT_R; + + private RadioButton rbEPC_filter; + private RadioButton rbTID_filter; + private RadioButton rbUser_filter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.uhf_read_fragment, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mContext = (UHFMainActivity) getActivity(); + SpinnerBank_Read = (Spinner) getView().findViewById(R.id.SpinnerBank_Read); + SpinnerOption_Read = (Spinner) getView().findViewById(R.id.SpinnerOption_Read); + + EtPtr_Read = (EditText) getView().findViewById(R.id.EtPtr_Read); + EtLen_Read = (EditText) getView().findViewById(R.id.EtLen_Read); + EtAccessPwd_Read = (EditText) getView().findViewById(R.id.EtAccessPwd_Read); + EtPtr2_Read = (EditText) getView().findViewById(R.id.EtPtr2_Read); + EtLen2_Read = (EditText) getView().findViewById(R.id.EtLen2_Read); + EtData_Read = (EditText) getView().findViewById(R.id.EtData_Read); + etLen_filter = (EditText) getView().findViewById(R.id.etLen_filter); + etPtr_filter = (EditText) getView().findViewById(R.id.etPtr_filter); + etData_filter = (EditText) getView().findViewById(R.id.etData_filter); + + BtRead = (Button) getView().findViewById(R.id.BtRead); + cb_QT_R = (CheckBox) getView().findViewById(R.id.cb_QT_R); + cb_filter = (CheckBox) getView().findViewById(R.id.cb_filter); + + rbEPC_filter = (RadioButton) getView().findViewById(R.id.rbEPC_filter); + rbTID_filter = (RadioButton) getView().findViewById(R.id.rbTID_filter); + rbUser_filter = (RadioButton) getView().findViewById(R.id.rbUser_filter); + + rbEPC_filter.setOnClickListener(this); + rbTID_filter.setOnClickListener(this); + rbUser_filter.setOnClickListener(this); + BtRead.setOnClickListener(this); + + EtData_Read.setKeyListener(null); + EtPtr2_Read.setEnabled(false); + EtLen2_Read.setEnabled(false); + EtData_Read.setText(""); + + cb_filter.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + String data = etData_filter.getText().toString().trim(); + String rex = "[\\da-fA-F]*"; //匹配正则表达式,数据为十六进制格式 + if (data == null || data.isEmpty() || !data.matches(rex)) { + UIHelper.ToastMessage(mContext, "过滤的数据必须是十六进制数据"); + cb_filter.setChecked(false); + return; + } + } + } + }); + SpinnerBank_Read.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + String element = adapterView.getItemAtPosition(i).toString();// 得到spanner的值 + if (element.equals("EPC")) { + EtPtr_Read.setText("2"); + } else { + EtPtr_Read.setText("0"); + } + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + + } + }); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.rbEPC_filter: + if (rbEPC_filter.isChecked()) { + etPtr_filter.setText("32"); + } + break; + case R.id.rbTID_filter: + if (rbTID_filter.isChecked()) { + etPtr_filter.setText("0"); + } + break; + case R.id.rbUser_filter: + if (rbUser_filter.isChecked()) { + etPtr_filter.setText("0"); + } + break; + case R.id.BtRead: + read(); + break; + } + + } + + private void read() { + String ptrStr = EtPtr_Read.getText().toString().trim(); + if (ptrStr.equals("")) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_addr_not_null); + return; + } else if (!TextUtils.isDigitsOnly(ptrStr)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_addr_must_decimal); + return; + } + + String cntStr = EtLen_Read.getText().toString().trim(); + if (cntStr.equals("")) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_len_not_null); + return; + } else if (!TextUtils.isDigitsOnly(cntStr)) { + + UIHelper.ToastMessage(mContext, R.string.uhf_msg_len_must_decimal); + return; + } + + String pwdStr = EtAccessPwd_Read.getText().toString().trim(); + if (!TextUtils.isEmpty(pwdStr)) { + if (pwdStr.length() != 8) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_addr_must_len8); + return; + } else if (!mContext.vailHexInput(pwdStr)) { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nohex); + return; + } + } else { + pwdStr = "00000000"; + } + + boolean result = false; + int Bank = 0; + if (SpinnerBank_Read.getSelectedItemPosition() == 0) { + Bank = IUHF.Bank_RESERVED; + } else if (SpinnerBank_Read.getSelectedItemPosition() == 1) { + Bank = IUHF.Bank_EPC; + } else if (SpinnerBank_Read.getSelectedItemPosition() == 2) { + Bank = IUHF.Bank_TID; + } else if (SpinnerBank_Read.getSelectedItemPosition() == 3) { + Bank = IUHF.Bank_USER; + } + if (cb_filter.isChecked())// 过滤 + { + if (etPtr_filter.getText().toString() == null || etPtr_filter.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据的起始地址不能为空"); + return; + } + if (etData_filter.getText().toString() == null || etData_filter.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据不能为空"); + return; + } + if (etLen_filter.getText().toString() == null || etLen_filter.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据长度不能为空"); + return; + } + + int filterPtr = Integer.parseInt(etPtr_filter.getText().toString()); + String filterData = etData_filter.getText().toString(); + int filterCnt = Integer.parseInt(etLen_filter.getText().toString()); + int filterBank = 0; + if (rbEPC_filter.isChecked()) { + filterBank = IUHF.Bank_EPC; + } else if (rbTID_filter.isChecked()) { + filterBank = IUHF.Bank_TID; + } else if (rbUser_filter.isChecked()) { + filterBank = IUHF.Bank_USER; + } + String data = ""; + if (cb_QT_R.isChecked()) { + data = mContext.mReader.readData(pwdStr, + filterBank, + filterPtr, + filterCnt, + filterData, + Bank, + Integer.parseInt(ptrStr), + Integer.parseInt(cntStr) + ); + } else { + data = mContext.mReader.readData(pwdStr, + filterBank, + filterPtr, + filterCnt, + filterData, + Bank, + Integer.parseInt(ptrStr), + Integer.parseInt(cntStr) + ); + } + if (data != null && data.length() > 0) { + result = true; + } else { + result = false; + } + EtData_Read.setText("data:" + data); + } else { + String entity = ""; + if (cb_QT_R.isChecked()) { + entity = mContext.mReader.readData(pwdStr, + Bank, + Integer.parseInt(ptrStr), + Integer.parseInt(cntStr)); + } else { + entity = mContext.mReader.readData(pwdStr, + Bank, + Integer.parseInt(ptrStr), + Integer.parseInt(cntStr)); + } + if (entity != null) { + result = true; + EtData_Read.setText("data:" + entity); + } else { + result = false; + UIHelper.ToastMessage(mContext, R.string.uhf_msg_read_data_fail); + EtData_Read.setText(""); + } + } + if (!result) { + mContext.playSound(2); + } else { + mContext.playSound(1); + } + } + + public void myOnKeyDwon() { + read(); + } +} diff --git a/app/src/main/java/com/example/uhf/fragment/UHFReadTagFragment.java b/app/src/main/java/com/example/uhf/fragment/UHFReadTagFragment.java new file mode 100644 index 0000000..81b034d --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/UHFReadTagFragment.java @@ -0,0 +1,454 @@ +package com.example.uhf.fragment; + +import android.graphics.drawable.BitmapDrawable; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.PopupWindow; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.RadioGroup.OnCheckedChangeListener; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +import com.example.uhf.R; +import com.example.uhf.activity.UHFMainActivity; +import com.example.uhf.tools.StringUtils; +import com.example.uhf.tools.UIHelper; +import com.rscja.deviceapi.entity.UHFTAGInfo; +import com.rscja.deviceapi.interfaces.IUHF; + +import java.util.ArrayList; +import java.util.HashMap; + + +public class UHFReadTagFragment extends KeyDwonFragment { + + private boolean loopFlag = false; + private int inventoryFlag = 1; + private Handler handler; + private ArrayList> tagList; + private SimpleAdapter adapter; + + private TextView tv_count; + + private RadioGroup RgInventory; + private RadioButton RbInventorySingle; + private RadioButton RbInventoryLoop; + + private Button BtClear; + private Button Btimport; + private Button BtInventory; + private Button btnFilter;//过滤 + + private ListView LvTags; + private LinearLayout llContinuous; + private UHFMainActivity mContext; + private HashMap map; + private PopupWindow popFilter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + Log.i(UHFMainActivity.TAG, "UHFReadTagFragment.onCreateView"); + return inflater.inflate(R.layout.uhf_readtag_fragment, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + Log.i(UHFMainActivity.TAG, "UHFReadTagFragment.onActivityCreated"); + + String tr = ""; + mContext = (UHFMainActivity) getActivity(); + tagList = new ArrayList>(); + + BtClear = (Button) getView().findViewById(R.id.BtClear); + Btimport = (Button) getView().findViewById(R.id.BtImport); + tv_count = (TextView) getView().findViewById(R.id.tv_count); + RgInventory = (RadioGroup) getView().findViewById(R.id.RgInventory); + RbInventorySingle = (RadioButton) getView().findViewById(R.id.RbInventorySingle); + RbInventoryLoop = (RadioButton) getView().findViewById(R.id.RbInventoryLoop); + BtInventory = (Button) getView().findViewById(R.id.BtInventory); + LvTags = (ListView) getView().findViewById(R.id.LvTags); + llContinuous = (LinearLayout) getView().findViewById(R.id.llContinuous); + + adapter = new SimpleAdapter(mContext, tagList, R.layout.listtag_items, + new String[]{"tagUii", "tagLen", "tagCount", "tagRssi"}, + new int[]{R.id.TvTagUii, R.id.TvTagLen, R.id.TvTagCount, + R.id.TvTagRssi}); + + BtClear.setOnClickListener(new BtClearClickListener()); + Btimport.setOnClickListener(new BtImportClickListener()); + RgInventory.setOnCheckedChangeListener(new RgInventoryCheckedListener()); + BtInventory.setOnClickListener(new BtInventoryClickListener()); + btnFilter = (Button) getView().findViewById(R.id.btnFilter); + + btnFilter.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (popFilter == null) { + View viewPop = LayoutInflater.from(mContext).inflate(R.layout.popwindow_filter, null); + + popFilter = new PopupWindow(viewPop, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT, true); + + popFilter.setTouchable(true); + popFilter.setOutsideTouchable(true); + popFilter.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + popFilter.setBackgroundDrawable(new BitmapDrawable()); + + final EditText etLen = (EditText) viewPop.findViewById(R.id.etLen); + final EditText etPtr = (EditText) viewPop.findViewById(R.id.etPtr); + final EditText etData = (EditText) viewPop.findViewById(R.id.etData); + final RadioButton rbEPC = (RadioButton) viewPop.findViewById(R.id.rbEPC); + final RadioButton rbTID = (RadioButton) viewPop.findViewById(R.id.rbTID); + final RadioButton rbUser = (RadioButton) viewPop.findViewById(R.id.rbUser); + final Button btSet = (Button) viewPop.findViewById(R.id.btSet); + + btSet.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + int filterBank = 0; + if (rbEPC.isChecked()) { + filterBank = IUHF.Bank_EPC; + } else if (rbTID.isChecked()) { + filterBank = IUHF.Bank_TID; + } else if (rbUser.isChecked()) { + filterBank = IUHF.Bank_USER; + } + if (etLen.getText().toString() == null || etLen.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "数据长度不能为空"); + return; + } + if (etPtr.getText().toString() == null || etPtr.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "起始地址不能为空"); + return; + } + int ptr = StringUtils.toInt(etPtr.getText().toString(), 0); + int len = StringUtils.toInt(etLen.getText().toString(), 0); + String data = etData.getText().toString().trim(); + if (len > 0) { + String rex = "[\\da-fA-F]*"; //匹配正则表达式,数据为十六进制格式 + if (data == null || data.isEmpty() || !data.matches(rex)) { + UIHelper.ToastMessage(mContext, "过滤的数据必须是十六进制数据"); +// mContext.playSound(2); + return; + } + + if (mContext.mReader.setFilter(filterBank, ptr, len, data)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_filter_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_filter_fail); +// mContext.playSound(2); + } + } else { + //禁用过滤 + String dataStr = ""; + if (mContext.mReader.setFilter(filterBank, 0, 0, dataStr)) { + UIHelper.ToastMessage(mContext, R.string.msg_disable_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.msg_disable_fail); + } + } + + + } + }); + CheckBox cb_filter = (CheckBox) viewPop.findViewById(R.id.cb_filter); + rbEPC.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (rbEPC.isChecked()) { + etPtr.setText("32"); + } + } + }); + rbTID.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (rbTID.isChecked()) { + etPtr.setText("0"); + } + } + }); + rbUser.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (rbUser.isChecked()) { + etPtr.setText("0"); + } + } + }); + + cb_filter.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { //启用过滤 + + } else { //禁用过滤 + + } + popFilter.dismiss(); + } + }); + } + if (popFilter.isShowing()) { + popFilter.dismiss(); + popFilter = null; + } else { + popFilter.showAsDropDown(view); + } + } + }); + LvTags.setAdapter(adapter); + clearData(); + Log.i(UHFMainActivity.TAG, "UHFReadTagFragment.EtCountOfTags=" + tv_count.getText()); + handler = new Handler() { + @Override + public void handleMessage(Message msg) { + String result = msg.obj + ""; + String[] strs = result.split("@"); + addEPCToList(strs[0], strs[1]); + mContext.playSound(1); + } + }; + } + + @Override + public void onPause() { + Log.i(UHFMainActivity.TAG, "UHFReadTagFragment.onPause"); + super.onPause(); + + // 停止识别 + stopInventory(); + } + + /** + * 添加EPC到列表中 + * + * @param epc + */ + private void addEPCToList(String epc, String rssi) { + if (!TextUtils.isEmpty(epc)) { + int index = checkIsExist(epc); + + map = new HashMap(); + + map.put("tagUii", epc); + map.put("tagCount", String.valueOf(1)); + map.put("tagRssi", rssi); + + // mContext.getAppContext().uhfQueue.offer(epc + "\t 1"); + + if (index == -1) { + tagList.add(map); + LvTags.setAdapter(adapter); + tv_count.setText("" + adapter.getCount()); + } else { + int tagcount = Integer.parseInt(tagList.get(index).get("tagCount"), 10) + 1; + + map.put("tagCount", String.valueOf(tagcount)); + tagList.set(index, map); + + } + + adapter.notifyDataSetChanged(); + } + } + + public class BtClearClickListener implements OnClickListener { + + @Override + public void onClick(View v) { + clearData(); + } + } + + public class BtImportClickListener implements OnClickListener { + + @Override + public void onClick(View v) { + + if (BtInventory.getText().equals(mContext.getString(R.string.btInventory))) { + if (tagList.size() == 0) { + + UIHelper.ToastMessage(mContext, "无数据导出"); + return; + } + boolean re = FileImport.daochu("", tagList); + if (re) { + UIHelper.ToastMessage(mContext, "导出成功"); + + tv_count.setText("0"); + tagList.clear(); + + Log.i(UHFMainActivity.TAG, "tagList.size " + tagList.size()); + adapter.notifyDataSetChanged(); + } + } else { + UIHelper.ToastMessage(mContext, "请停止扫描后再导出"); + } + } + + } + + private void clearData() { + tv_count.setText("0"); + tagList.clear(); + + Log.i(UHFMainActivity.TAG, "tagList.size " + tagList.size()); + adapter.notifyDataSetChanged(); + } + + public class RgInventoryCheckedListener implements OnCheckedChangeListener { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + llContinuous.setVisibility(View.GONE); + if (checkedId == RbInventorySingle.getId()) { + // 单步识别 + inventoryFlag = 0; + } else if (checkedId == RbInventoryLoop.getId()) { + // 单标签循环识别 + inventoryFlag = 1; + llContinuous.setVisibility(View.VISIBLE); + } + } + } + + public class BtInventoryClickListener implements OnClickListener { + @Override + public void onClick(View v) { + readTag(); + } + } + + private void readTag() { + if (BtInventory.getText().equals(mContext.getString(R.string.btInventory)))// 识别标签 + { + switch (inventoryFlag) { + case 0:// 单步 + { + UHFTAGInfo strUII = mContext.mReader.inventorySingleTag(); + if (strUII != null) { + String strEPC = strUII.getEPC(); + addEPCToList(strEPC, strUII.getRssi()); + tv_count.setText("" + adapter.getCount()); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_inventory_fail); +// mContext.playSound(2); + } + } + break; + case 1:// 单标签循环 .startInventoryTag((byte) 0, (byte) 0)) + { + // mContext.mReader.setEPCTIDMode(true); + + if (mContext.mReader.startInventoryTag()) { + BtInventory.setText(mContext + .getString(R.string.title_stop_Inventory)); + loopFlag = true; + setViewEnabled(false); + new TagThread().start(); + } else { + mContext.mReader.stopInventory(); + UIHelper.ToastMessage(mContext, R.string.uhf_msg_inventory_open_fail); +// mContext.playSound(2); + } + } + break; + default: + break; + } + } else {// 停止识别 + stopInventory(); + } + } + + private void setViewEnabled(boolean enabled) { + RbInventorySingle.setEnabled(enabled); + RbInventoryLoop.setEnabled(enabled); + btnFilter.setEnabled(enabled); + BtClear.setEnabled(enabled); + } + + /** + * 停止识别 + */ + private void stopInventory() { + if (loopFlag) { + loopFlag = false; + setViewEnabled(true); + if (mContext.mReader.stopInventory()) { + BtInventory.setText(mContext.getString(R.string.btInventory)); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_inventory_stop_fail); + } + } + } + + /** + * 判断EPC是否在列表中 + * + * @param strEPC 索引 + * @return + */ + public int checkIsExist(String strEPC) { + int existFlag = -1; + if (StringUtils.isEmpty(strEPC)) { + return existFlag; + } + String tempStr = ""; + for (int i = 0; i < tagList.size(); i++) { + HashMap temp = new HashMap(); + temp = tagList.get(i); + tempStr = temp.get("tagUii"); + if (strEPC.equals(tempStr)) { + existFlag = i; + break; + } + } + return existFlag; + } + + private class TagThread extends Thread { + public void run() { + String strTid; + String strResult; + UHFTAGInfo res = null; + while (loopFlag) { + res = mContext.mReader.readTagFromBuffer(); + if (res != null) { + strTid = res.getTid(); + if (strTid.length() != 0 && !strTid.equals("0000000" + "000000000") && !strTid.equals("000000000000000000000000")) { + strResult = "TID:" + strTid + "\n"; + } else { + strResult = ""; + } + Log.i(UHFMainActivity.TAG, "EPC:" + res.getEPC() + "|" + strResult); + Message msg = handler.obtainMessage(); + msg.obj = strResult + "EPC:" + res.getEPC() + "@" + res.getRssi(); + + handler.sendMessage(msg); + } + } + } + } + + @Override + public void myOnKeyDwon() { + readTag(); + } + +} diff --git a/app/src/main/java/com/example/uhf/fragment/UHFSetFragment.java b/app/src/main/java/com/example/uhf/fragment/UHFSetFragment.java new file mode 100644 index 0000000..e052973 --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/UHFSetFragment.java @@ -0,0 +1,705 @@ +package com.example.uhf.fragment; + + +import android.app.AlertDialog; +import android.os.Bundle; +import android.os.Handler; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RadioButton; +import android.widget.Spinner; +import android.widget.TextView; + +import com.example.uhf.R; +import com.example.uhf.activity.UHFMainActivity; +import com.example.uhf.tools.UIHelper; +import com.lidroid.xutils.ViewUtils; +import com.lidroid.xutils.view.annotation.ViewInject; +import com.lidroid.xutils.view.annotation.event.OnClick; +import com.rscja.utility.StringUtility; + +import static android.content.ContentValues.TAG; + +public class UHFSetFragment extends KeyDwonFragment implements OnClickListener { + private UHFMainActivity mContext; + + private Button btnSetFre; + private Button btnGetFre; + private Spinner spMode; + @ViewInject(R.id.ll_freHop) + private LinearLayout ll_freHop; + + @ViewInject(R.id.btnSetPower) + private Button btnSetPower; + @ViewInject(R.id.btnGetPower) + private Button btnGetPower; + @ViewInject(R.id.spPower) + private Spinner spPower; + @ViewInject(R.id.et_worktime) + private EditText et_worktime; + @ViewInject(R.id.et_waittime) + private EditText et_waittime; + @ViewInject(R.id.btnWorkWait) + private Button btnWorkWait; + @ViewInject(R.id.spFreHop) + private Spinner spFreHop; //频点列表 + @ViewInject(R.id.btnSetFreHop) + private Button btnSetFreHop; //设置频点设置 + @ViewInject(R.id.tv_normal_set) + private TextView tv_normal_set; //普通设置(点击5次设置频点设置) + @ViewInject(R.id.btnGetWait) + private Button btnGetWait; //获取空占比 + @ViewInject(R.id.btnSetAgreement) + private Button btnSetAgreement; //设置协议 + @ViewInject(R.id.SpinnerAgreement) + private Spinner SpinnerAgreement; //协议列表 + @ViewInject(R.id.btnSetLinkParams) + private Button btnSetLinkParams; //设置链路参数 + @ViewInject(R.id.btnGetLinkParams) + private Button btnGetLinkParams; //获取链路参数 + @ViewInject(R.id.splinkParams) + private Spinner splinkParams; //链路参数列表 + @ViewInject(R.id.btnSetQTParams) + private Button btnSetQTParams; //设置QT参数 + @ViewInject(R.id.btnGetQTParams) + private Button btnGetQTParams; //获取QT参数 + @ViewInject(R.id.cbQT) + private CheckBox cbQt; //打开QT + @ViewInject(R.id.cbTagFocus) + private CheckBox cbTagFocus; //打开tagFocus + @ViewInject(R.id.cbFastID) + private CheckBox cbFastID; //打开FastID + @ViewInject(R.id.cbEPC_TID) + private CheckBox cbEPC_TID; //打开EPC+TID + + @ViewInject(R.id.rb_America) + private RadioButton rb_America; //美国频点 + @ViewInject(R.id.rb_Others) + private RadioButton rb_Others; //其他频点 + private ArrayAdapter adapter; //频点列表适配器 + + @ViewInject(R.id.spsession)//session + private Spinner SpSession; + + @ViewInject(R.id.spinv)// + private Spinner SpInv; + + @ViewInject(R.id.btnGetSession) + private Button btnGetSession; + + @ViewInject(R.id.btnSetSession) + private Button btnSetSession; + + private DisplayMetrics metrics; + private AlertDialog dialog; + private long[] timeArr; + + private Handler mHandler = new Handler(); + private int arrPow; //输出功率 + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.activity_uhfset, container, false); + ViewUtils.inject(this, root); + + return root; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mContext = (UHFMainActivity) getActivity(); + + btnSetFre = (Button) getView().findViewById(R.id.BtSetFre); + btnGetFre = (Button) getView().findViewById(R.id.BtGetFre); + + spMode = (Spinner) getView().findViewById(R.id.SpinnerMode); + SpSession = (Spinner) getView().findViewById(R.id.spsession); + SpInv = (Spinner) getView().findViewById(R.id.spinv); + + spMode.setOnItemSelectedListener(new MyOnTouchListener()); + + btnSetFre.setOnClickListener(new SetFreOnclickListener()); + btnGetFre.setOnClickListener(new GetFreOnclickListener()); + btnWorkWait.setOnClickListener(new SetPWMOnclickListener()); + btnGetWait.setOnClickListener(this); + + btnSetSession.setOnClickListener(this); + btnGetSession.setOnClickListener(this); + btnSetFreHop.setOnClickListener(this); + tv_normal_set.setOnClickListener(this); + btnSetAgreement.setOnClickListener(this); + btnSetQTParams.setOnClickListener(this); + btnGetQTParams.setOnClickListener(this); + btnSetLinkParams.setOnClickListener(this); + btnGetLinkParams.setOnClickListener(this); + + cbTagFocus.setOnCheckedChangeListener(new OnMyCheckedChangedListener()); + cbFastID.setOnCheckedChangeListener(new OnMyCheckedChangedListener()); + cbEPC_TID.setOnCheckedChangeListener(new OnMyCheckedChangedListener()); + + SpSession.setSelection(1); + SpInv.setSelection(0); + String ver = mContext.mReader.getVersion();//.getHardwareType(); + arrPow = R.array.arrayPower; + if (ver != null && ver.contains("RLM")) { + arrPow = R.array.arrayPower2; + } + ArrayAdapter adapter = ArrayAdapter.createFromResource(mContext, arrPow, android.R.layout.simple_spinner_item); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spPower.setAdapter(adapter); + } + + @Override + public void onResume() { + super.onResume(); + /* + 开启子线程获取参数,Handler更新UI,防止fragment打开卡顿 + */ + mHandler.post(new Runnable() { + @Override + public void run() { + getFre(); + getPwm(); + getLinkParams(); + OnClick_GetPower(null); + } + }); + } + + /** + * 工作模式下拉列表点击选中item监听 + */ + public class MyOnTouchListener implements AdapterView.OnItemSelectedListener { + + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + + if (position == 3) { + ll_freHop.setVisibility(View.VISIBLE); + rb_America.setChecked(true); //默认美国频点 + } else if (position != 3) { + ll_freHop.setVisibility(View.GONE); + } + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + } + + public class SetFreOnclickListener implements OnClickListener { + + @Override + public void onClick(View v) { + + // byte[] bBaseFre = new byte[2]; + // + // if (mContext.mReader.setFrequency( + // (byte) spMode.getSelectedItemPosition(), (byte) 0, + // bBaseFre, (byte) 0, (byte) 0, (byte) 0)) { + // UIHelper.ToastMessage(mContext, + // R.string.uhf_msg_set_frequency_succ); + // } else { + // UIHelper.ToastMessage(mContext, + // R.string.uhf_msg_set_frequency_fail); + // } + + if (mContext.mReader.setFrequencyMode((byte) spMode.getSelectedItemPosition())) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_frequency_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_frequency_fail); +// mContext.playSound(2); + } + } + } + + public void getFre() { + int idx = mContext.mReader.getFrequencyMode(); + + if (idx != -1) { + int count = spMode.getCount(); + spMode.setSelection(idx > count - 1 ? count - 1 : idx); + + // UIHelper.ToastMessage(mContext, + // R.string.uhf_msg_read_frequency_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_read_frequency_fail); + } + } + + public void getPwm() { + int[] pwm = mContext.mReader.getPwm(); + + if (pwm == null || pwm.length < 2) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_read_pwm_fail); + return; + } + + et_worktime.setText(pwm[0] + ""); + et_waittime.setText(pwm[1] + ""); + + et_worktime.setSelection(et_worktime.getText().toString().length()); + et_waittime.setSelection(et_waittime.getText().toString().length()); + } + + /** + * 获取链路参数 + */ + public void getLinkParams() { + int idx = mContext.mReader.getRFLink(); + if (idx != -1) { + splinkParams.setSelection(idx); + +// UIHelper.ToastMessage(mContext, +// R.string.uhf_msg_get_para_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_get_para_fail); + } + } + + public class SetPWMOnclickListener implements OnClickListener { + + @Override + public void onClick(View v) { + if (mContext.mReader.setPwm(StringUtility.string2Int(et_worktime.getText().toString(), 0), + StringUtility.string2Int(et_waittime.getText().toString(), 0))) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_pwm_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_pwm_fail); +// mContext.playSound(2); + } + } + } + + public class GetFreOnclickListener implements OnClickListener { + + @Override + public void onClick(View v) { + + // String strFrequency = mContext.mReader.getFrequency(); + // + // if (StringUtils.isNotEmpty(strFrequency)) { + // + // etFreRange.setText(strFrequency); + // + // UIHelper.ToastMessage(mContext, + // R.string.uhf_msg_read_frequency_succ); + // + // } else { + // UIHelper.ToastMessage(mContext, + // R.string.uhf_msg_read_frequency_fail); + // } + + getFre(); + } + } + + public class OnMyCheckedChangedListener implements CompoundButton.OnCheckedChangeListener { + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + switch (buttonView.getId()) { + case R.id.cbTagFocus: + if (mContext.mReader.setTagFocus(isChecked)) { + if (isChecked) { + cbTagFocus.setText(R.string.tagFocus_off); + } else { + cbTagFocus.setText(R.string.tagFocus); + } + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_fail); +// mContext.playSound(2); + } + break; + case R.id.cbFastID: + if (mContext.mReader.setFastID(isChecked)) { + if (isChecked) { + cbFastID.setText(R.string.fastID_off); + } else { + cbFastID.setText(R.string.fastID); + } + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_fail); +// mContext.playSound(2); + } + break; + case R.id.cbEPC_TID: + if (mContext.mReader.setEPCAndTIDMode()) { + if (isChecked) { + cbEPC_TID.setText(R.string.EPC_TID_off); + } else { + cbEPC_TID.setText(R.string.EPC_TID); + } + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_fail); +// mContext.playSound(2); + } + break; + } + } + } + + @OnClick(R.id.btnGetPower) + public void OnClick_GetPower(View view) { + int iPower = mContext.mReader.getPower(); + + Log.i(UHFMainActivity.TAG, "OnClick_GetPower() iPower=" + iPower); + if (iPower > -1) { + int position = iPower - 5; + int count = spPower.getCount(); + spPower.setSelection(position > count - 1 ? count - 1 : position); + + // UIHelper.ToastMessage(mContext, + // R.string.uhf_msg_read_power_succ); + + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_read_power_fail); + } + + } + + @OnClick(R.id.btnSetPower) + public void OnClick_SetPower(View view) { + int iPower = spPower.getSelectedItemPosition() + 5; + + Log.i(UHFMainActivity.TAG, "OnClick_SetPower() iPower=" + iPower); + if (mContext.mReader.setPower(iPower)) { + + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_power_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_power_fail); +// mContext.playSound(2); + } + + } + + /** + * 设置频点 + * + * @param value 频点数值 + * @return 是否设置成功 + */ + private boolean setFreHop(float value) { + boolean result = mContext.mReader.setFreHop(value); + if (result) { + + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_frehop_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_frehop_fail); +// mContext.playSound(2); + } + return result; + } + + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + switch (v.getId()) { + case R.id.btnSetFreHop: //设置频点 +// showFrequencyDialog(); + View view = spFreHop.getSelectedView(); + if (view instanceof TextView) { + String freHop = ((TextView) view).getText().toString().trim(); + setFreHop(Float.valueOf(freHop)); //设置频点 + } + break; + case R.id.btnGetWait: //获取空占比 + getPwm(); + break; + case R.id.btnSetAgreement: //设置协议 + if (mContext.mReader.setProtocol(SpinnerAgreement.getSelectedItemPosition())) { + UIHelper.ToastMessage(mContext, R.string.setAgreement_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.setAgreement_fail); +// mContext.playSound(2); + } + break; + case R.id.btnSetQTParams: //设置QT参数 + if (!cbQt.isChecked()) { + UIHelper.ToastMessage(mContext, R.string.please_on); +// mContext.playSound(2); + return; + } + if (mContext.mReader.setQTPara(cbQt.isChecked())) { + UIHelper.ToastMessage(mContext, R.string.setQTParams_succ); + + } else { + UIHelper.ToastMessage(mContext, R.string.setQTParams_fail); +// mContext.playSound(2); + } + break; + case R.id.btnGetQTParams: //获取QT参数 + int[] QTParams = mContext.mReader.getQTPara(); + if (QTParams[0] == 1) { + cbQt.setChecked(QTParams[1] == 1); + UIHelper.ToastMessage(mContext, R.string.getQTParams_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.getQTParams_fail); + } + break; + case R.id.btnSetLinkParams: //设置链路参数 + if (mContext.mReader.setRFLink(splinkParams.getSelectedItemPosition())) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_fail); +// mContext.playSound(2); + } + break; + case R.id.btnGetLinkParams: //获取链路参数 + getLinkParams(); + break; + + case R.id.btnSetSession: + + // //设置SESSION只针对盘点EPC有效,对返回EPC+TID,EPC+TID+USER无效 + int seesionid = SpSession.getSelectedItemPosition(); + int inventoried = SpInv.getSelectedItemPosition(); + if (seesionid < 0 || inventoried < 0) { + return; + } + char[] p = mContext.mReader.getGen2(); + if (p != null && p.length >= 14) { + int target = p[0]; + int action = p[1]; + int t = p[2]; + int q = p[3]; + int startQ = p[4]; + int minQ = p[5]; + int maxQ = p[6]; + int dr = p[7]; + int coding = p[8]; + int p1 = p[9]; + int Sel = p[10]; + int Session = p[11]; + int g = p[12]; + int linkFrequency = p[13]; + StringBuilder sb = new StringBuilder(); + sb.append("target="); + sb.append(target); + sb.append(" ,action="); + sb.append(action); + sb.append(" ,t="); + sb.append(t); + sb.append(" ,q="); + sb.append(q); + sb.append(" startQ="); + sb.append(startQ); + sb.append(" minQ="); + sb.append(minQ); + sb.append(" maxQ="); + sb.append(maxQ); + sb.append(" dr="); + sb.append(dr); + sb.append(" coding="); + sb.append(coding); + sb.append(" p="); + sb.append(p1); + sb.append(" Sel="); + sb.append(Sel); + sb.append(" Session="); + sb.append(Session); + sb.append(" g="); + sb.append(g); + sb.append(" linkFrequency="); + sb.append(linkFrequency); + sb.append("seesionid="); + sb.append(seesionid); + sb.append(" inventoried="); + sb.append(inventoried); + Log.i(UHFMainActivity.TAG, sb.toString()); + if (mContext.mReader.setGen2(target, action, t, q, startQ, minQ, maxQ, dr, coding, p1, Sel, seesionid, inventoried, linkFrequency)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_succ); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_fail); + } + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_fail); + } + break; + case R.id.btnGetSession: + char[] pp = mContext.mReader.getGen2(); + if (pp != null && pp.length >= 14) { + int target = pp[0]; + int action = pp[1]; + int t = pp[2]; + int q = pp[3]; + int startQ = pp[4]; + int minQ = pp[5]; + int maxQ = pp[6]; + int dr = pp[7]; + int coding = pp[8]; + int p1 = pp[9]; + int Sel = pp[10]; + int Session = pp[11]; + int g = pp[12]; + int linkFrequency = pp[13]; + StringBuilder sb = new StringBuilder(); + sb.append("target="); + sb.append(target); + sb.append(" ,action="); + sb.append(action); + sb.append(" ,t="); + sb.append(t); + sb.append(" ,q="); + sb.append(q); + sb.append(" startQ="); + sb.append(startQ); + sb.append(" minQ="); + sb.append(minQ); + sb.append(" maxQ="); + sb.append(maxQ); + sb.append(" dr="); + sb.append(dr); + sb.append(" coding="); + sb.append(coding); + sb.append(" p="); + sb.append(p1); + sb.append(" Sel="); + sb.append(Sel); + sb.append(" Session="); + sb.append(Session); + sb.append(" g="); + sb.append(g); + sb.append(" linkFrequency="); + sb.append(linkFrequency); + Log.i(UHFMainActivity.TAG, sb.toString()); + SpSession.setSelection(Session); + SpInv.setSelection(g); + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_succ); + } else + UIHelper.ToastMessage(mContext, R.string.uhf_msg_set_fail); + break; + default: + break; + } + } + + /** + * 显示频点设置 + */ + private void showFrequencyDialog() { + if (dialog == null) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); +// builder.setTitle(R.string.btSetFrequency); + View view = getActivity().getLayoutInflater().inflate(R.layout.uhf_dialog_frequency, null); + ListView listView = (ListView) view.findViewById(R.id.listView_frequency); + ImageView iv = (ImageView) view.findViewById(R.id.iv_dismissDialog); + iv.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + dialog.dismiss(); + } + }); + + String[] strArr = getResources().getStringArray(R.array.arrayFreHop); + listView.setAdapter(new ArrayAdapter(getActivity(), R.layout.item_text1, strArr)); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + // TODO Auto-generated method stub + if (view instanceof TextView) { + TextView tv = (TextView) view; + float value = Float.valueOf(tv.getText().toString().trim()); + setFreHop(value); //设置频点 + dialog.dismiss(); + } + } + + }); + + builder.setView(view); + dialog = builder.create(); + dialog.show(); + dialog.setCanceledOnTouchOutside(false); + + WindowManager.LayoutParams params = dialog.getWindow().getAttributes(); + params.width = getWindowWidth() - 100; + params.height = getWindowHeight() - 200; + dialog.getWindow().setAttributes(params); + } else { + dialog.show(); + } + } + + /** + * 判断是否为累计点击5次且时间少于1600毫秒(调用一次即点击一次) + * + * @return + */ + private boolean isFiveClick() { + if (timeArr == null) { + timeArr = new long[5]; + } + System.arraycopy(timeArr, 1, timeArr, 0, timeArr.length - 1); + timeArr[timeArr.length - 1] = System.currentTimeMillis(); + return System.currentTimeMillis() - timeArr[0] < 1600; + } + + + /** + * 获取屏幕宽度 + * + * @return + */ + public int getWindowWidth() { + if (metrics == null) { + metrics = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); + } + return metrics.widthPixels; + } + + /** + * 获取屏幕高度 + * + * @return + */ + public int getWindowHeight() { + if (metrics == null) { + metrics = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); + } + return metrics.heightPixels; + } + + @OnClick(R.id.rb_America) + public void onClick_rbAmerica(View view) { + + adapter = ArrayAdapter.createFromResource(mContext, R.array.arrayFreHop_us, android.R.layout.simple_spinner_item); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spFreHop.setAdapter(adapter); + } + + @OnClick(R.id.rb_Others) + public void onClick_rbOthers(View view) { + + adapter = ArrayAdapter.createFromResource(mContext, R.array.arrayFreHop, android.R.layout.simple_spinner_item); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spFreHop.setAdapter(adapter); + + } +} diff --git a/app/src/main/java/com/example/uhf/fragment/UHFWriteFragment.java b/app/src/main/java/com/example/uhf/fragment/UHFWriteFragment.java new file mode 100644 index 0000000..ef683cb --- /dev/null +++ b/app/src/main/java/com/example/uhf/fragment/UHFWriteFragment.java @@ -0,0 +1,273 @@ +package com.example.uhf.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.Spinner; + +import com.example.uhf.R; +import com.example.uhf.activity.UHFMainActivity; +import com.example.uhf.tools.StringUtils; +import com.example.uhf.tools.UIHelper; +import com.rscja.deviceapi.interfaces.IUHF; +import com.rscja.utility.StringUtility; + +public class UHFWriteFragment extends KeyDwonFragment implements OnClickListener { + + //private static final String TAG = "UHFWriteFragment"; + private UHFMainActivity mContext; + + private Spinner SpinnerBank_Write; + private EditText EtPtr_Write; + private EditText EtLen_Write; + private EditText EtData_Write; + private EditText EtAccessPwd_Write; + private EditText etLen_filter_wt; + private EditText etPtr_filter_wt; + private EditText etData_filter_wt; + + private Button BtWrite; + private CheckBox cb_filter_wt, cb_QT_W; + + private RadioButton rbEPC_filter_wt; + private RadioButton rbTID_filter_wt; + private RadioButton rbUser_filter_wt; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.uhf_write_fragment, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mContext = (UHFMainActivity) getActivity(); + SpinnerBank_Write = (Spinner) getView().findViewById(R.id.SpinnerBank_Write); + + EtPtr_Write = (EditText) getView().findViewById(R.id.EtPtr_Write); + EtLen_Write = (EditText) getView().findViewById(R.id.EtLen_Write); + EtData_Write = (EditText) getView().findViewById(R.id.EtData_Write); + EtAccessPwd_Write = (EditText) getView().findViewById(R.id.EtAccessPwd_Write); + etLen_filter_wt = (EditText) getView().findViewById(R.id.etLen_filter_wt); + etPtr_filter_wt = (EditText) getView().findViewById(R.id.etPtr_filter_wt); + etData_filter_wt = (EditText) getView().findViewById(R.id.etData_filter_wt); + + BtWrite = (Button) getView().findViewById(R.id.BtWrite); + cb_QT_W = (CheckBox) getView().findViewById(R.id.cb_QT_W); + cb_filter_wt = (CheckBox) getView().findViewById(R.id.cb_filter_wt); + + rbEPC_filter_wt = (RadioButton) getView().findViewById(R.id.rbEPC_filter_wt); + rbTID_filter_wt = (RadioButton) getView().findViewById(R.id.rbTID_filter_wt); + rbUser_filter_wt = (RadioButton) getView().findViewById(R.id.rbUser_filter_wt); + + rbEPC_filter_wt.setOnClickListener(this); + rbTID_filter_wt.setOnClickListener(this); + rbUser_filter_wt.setOnClickListener(this); + BtWrite.setOnClickListener(this); + + cb_filter_wt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + String data = etData_filter_wt.getText().toString().trim(); + String rex = "[\\da-fA-F]*"; //匹配正则表达式,数据为十六进制格式 + if (data == null || data.isEmpty() || !data.matches(rex)) { + UIHelper.ToastMessage(mContext, "过滤的数据必须是十六进制数据"); + cb_filter_wt.setChecked(false); + return; + } + } + } + }); + + SpinnerBank_Write.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + String element = adapterView.getItemAtPosition(i).toString();// 得到spanner的值 + if (element.equals("EPC")) { + EtPtr_Write.setText("2"); + } else { + EtPtr_Write.setText("0"); + } + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + + } + }); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.rbEPC_filter_wt: + etPtr_filter_wt.setText("32"); + break; + case R.id.rbTID_filter_wt: + etPtr_filter_wt.setText("0"); + break; + case R.id.rbUser_filter_wt: + etPtr_filter_wt.setText("0"); + break; + case R.id.BtWrite: + write(); + break; + } + } + + private void write() { + String strPtr = EtPtr_Write.getText().toString().trim(); + if (StringUtils.isEmpty(strPtr)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_addr_not_null); + return; + } else if (!StringUtility.isDecimal(strPtr)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_addr_must_decimal); + return; + } + + String strPWD = EtAccessPwd_Write.getText().toString().trim();// 访问密码 + if (StringUtils.isNotEmpty(strPWD)) { + if (strPWD.length() != 8) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_addr_must_len8); + return; + } else if (!mContext.vailHexInput(strPWD)) { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nohex); + return; + } + } else { + strPWD = "00000000"; + } + + String strData = EtData_Write.getText().toString().trim();// 要写入的内容 + if (StringUtils.isEmpty(strData)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_write_must_not_null); + return; + } else if (!mContext.vailHexInput(strData)) { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nohex); + return; + } + + // 多字单次 + String cntStr = EtLen_Write.getText().toString().trim(); + if (StringUtils.isEmpty(cntStr)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_len_not_null); + return; + } else if (!StringUtility.isDecimal(cntStr)) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_len_must_decimal); + return; + } + + if ((strData.length()) % 4 != 0) { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_write_must_len4x); + + return; + } else if (!mContext.vailHexInput(strData)) { + UIHelper.ToastMessage(mContext, R.string.rfid_mgs_error_nohex); + return; + } + + boolean result = false; + int Bank = 0; + + if (SpinnerBank_Write.getSelectedItemPosition() == 0) { + Bank = IUHF.Bank_RESERVED; + } else if (SpinnerBank_Write.getSelectedItemPosition() == 1) { + Bank = IUHF.Bank_EPC; + } else if (SpinnerBank_Write.getSelectedItemPosition() == 2) { + Bank = IUHF.Bank_TID; + } else if (SpinnerBank_Write.getSelectedItemPosition() == 3) { + Bank = IUHF.Bank_USER; + } else { + } + + if (cb_filter_wt.isChecked())// 指定标签 + { + if (etPtr_filter_wt.getText().toString() == null || etPtr_filter_wt.getText().toString().isEmpty()) { + etPtr_filter_wt.setText("0"); + } + if (etLen_filter_wt.getText().toString() == null || etLen_filter_wt.getText().toString().isEmpty()) { + UIHelper.ToastMessage(mContext, "过滤数据长度不能为空"); + return; + } + + int filterPtr = Integer.parseInt(etPtr_filter_wt.getText().toString()); + String filterData = etData_filter_wt.getText().toString(); + int filterCnt = Integer.parseInt(etLen_filter_wt.getText().toString()); + int filterBank = 0; + if (rbEPC_filter_wt.isChecked()) { + filterBank = IUHF.Bank_EPC; + } else if (rbTID_filter_wt.isChecked()) { + filterBank = IUHF.Bank_TID; + } else if (rbUser_filter_wt.isChecked()) { + filterBank = IUHF.Bank_USER; + } + boolean r = false; + if (cb_QT_W.isChecked()) { + r = mContext.mReader.writeData(strPWD, + filterBank, + filterPtr, + filterCnt, + filterData, + Bank, + Integer.parseInt(strPtr), + Integer.parseInt(cntStr), + strData + ); + } else { + r = mContext.mReader.writeData(strPWD, + filterBank, + filterPtr, + filterCnt, + filterData, + Bank, + Integer.parseInt(strPtr), + Integer.parseInt(cntStr), + strData + ); + } + + if (r) { + result = true; + } else { + result = false; + } + + } else { + boolean r = false; + if (cb_QT_W.isChecked()) { + r = mContext.mReader.writeData(strPWD, + Bank, + Integer.parseInt(strPtr), + Integer.valueOf(cntStr), strData); + } else { + r = mContext.mReader.writeData(strPWD, + Bank, + Integer.parseInt(strPtr), + Integer.valueOf(cntStr), strData);// 返回的UII + } + + if (r) { + result = true; + UIHelper.ToastMessage(mContext, getString(R.string.uhf_msg_write_succ)); + } else { + UIHelper.ToastMessage(mContext, R.string.uhf_msg_write_fail); + } + } + if (!result) { + mContext.playSound(2); + } else { + mContext.playSound(1); + } + } + +} diff --git a/app/src/main/java/com/example/uhf/tools/StringUtils.java b/app/src/main/java/com/example/uhf/tools/StringUtils.java new file mode 100644 index 0000000..4323408 --- /dev/null +++ b/app/src/main/java/com/example/uhf/tools/StringUtils.java @@ -0,0 +1,211 @@ +package com.example.uhf.tools; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class StringUtils { + + public static String replaceUrlWithPlus(String url) { + // 1. 处理特殊字符 + // 2. 去除后缀名带来的文件浏览器的视图凌乱(特别是图片更�?��如此类似处理,否则有的手机打�?��库,全是我们的缓存图�? + if (url != null) { + return url.replaceAll("http://(.)*?/", "") + .replaceAll("[.:/,%?&=]", "+").replaceAll("[+]+", "+"); + } + return null; + } + + /** + * 验证ip是否合法 + * + * @param text ip地址 + * @return 验证信息 + */ + public static Boolean isIP(String text) { + if (text != null && !text.isEmpty()) { + // 定义正则表达式 + String regex = "^((25[0-5])|(2[0-4]\\d)|(1\\d\\d)|([1-9]\\d)|\\d)(\\.((25[0-5])|(2[0-4]\\d)|(1\\d\\d)|([1-9]\\d)|\\d)){3}$"; + // 判断ip地址是否与正则表达式匹配 + if (text.matches(regex)) { + // 返回判断信息 + return true; + } else { + // 返回判断信息 + return false; + } + } + // 返回判断信息 + return false; + } + + /** + * 验证域名是否合法 + * + * @param text 域名 + * @return 验证信息 + */ + public static Boolean isDomain(String text) { + if (text != null && !text.isEmpty()) { + // 定义正则表达式 + String regex = "^([a-zA-Z0-9\\.\\-]+(\\:[a-zA-Z0-9\\.&%\\$\\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\\-]+\\.)*[a-zA-Z0-9\\-]+\\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))$"; + // 判断域名是否与正则表达式匹配 + if (text.matches(regex)) { + // 返回判断信息 + return true; + } else { + // 返回判断信息 + return false; + } + } + // 返回判断信息 + return false; + } + + public static boolean isEmpty(CharSequence cs) { + return cs == null || cs.length() == 0; + } + + public static boolean isNotEmpty(CharSequence cs) { + return !StringUtils.isEmpty(cs); + } + + public static String trim(String str) { + return str == null ? null : str.trim(); + } + + /** + * 字符串转整数 + * + * @param str + * @param defValue + * @return + */ + public static int toInt(String str, int defValue) { + try { + return Integer.parseInt(str); + } catch (Exception e) { + } + return defValue; + } + + /** + * 对象转整数 + * + * @param obj + * @return 转换异常返回 0 + */ + public static int toInt(Object obj) { + if (obj == null) + return 0; + return toInt(obj.toString(), 0); + } + + /** + * 对象转整数 + * + * @param obj + * @return 转换异常返回 0 + */ + public static long toLong(String obj) { + try { + return Long.parseLong(obj); + } catch (Exception e) { + } + return 0; + } + + /** + * 字符转double + * + * @param obj + * @return 转换异常返回 0 + */ + public static double toDouble(String obj) { + try { + return Double.parseDouble(obj); + } catch (Exception e) { + } + return 0; + } + + /** + * 字符串转布尔值 + * + * @param b + * @return 转换异常返回 false + */ + public static boolean toBool(String b) { + try { + return Boolean.parseBoolean(b); + } catch (Exception e) { + } + return false; + } + + /** + * 判断是否为整数 INT + * + * @param val + * @return + */ + public static Boolean isInt(String val) { + try { + Integer.parseInt(val); + return true; + } catch (Exception e) { + return false; + } + } + + public static String getTimeString() { + SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss"); + Date curDate = new Date(System.currentTimeMillis());// 获取当前时间 + return formatter.format(curDate); + } + + public static String getTimeFormat(long time) { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy MM dd HH:mm:ss"); + Date curDate = new Date(time);// 获取当前时间 + return formatter.format(curDate); + } + + /** + * 判断是否是十六进制 + * + * @param str + * @return + */ + public static boolean isHexNumber(String str) { + boolean flag = false; + for (int i = 0; i < str.length(); i++) { + char cc = str.charAt(i); + if (cc == '0' || cc == '1' || cc == '2' || cc == '3' || cc == '4' + || cc == '5' || cc == '6' || cc == '7' || cc == '8' + || cc == '9' || cc == 'A' || cc == 'B' || cc == 'C' + || cc == 'D' || cc == 'E' || cc == 'F' || cc == 'a' + || cc == 'b' || cc == 'c' || cc == 'c' || cc == 'd' + || cc == 'e' || cc == 'f') { + flag = true; + } + } + return flag; + } + + /** + * 十六进制字符串转换成char数组 + * + * @param s + * @return + */ + public static char[] HexStringToChars(String s) { + char[] bytes; + bytes = new char[s.length() / 2]; + + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (char) Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16); + } + + return bytes; + } + +} diff --git a/app/src/main/java/com/example/uhf/tools/UIHelper.java b/app/src/main/java/com/example/uhf/tools/UIHelper.java new file mode 100644 index 0000000..f4b00fb --- /dev/null +++ b/app/src/main/java/com/example/uhf/tools/UIHelper.java @@ -0,0 +1,87 @@ +package com.example.uhf.tools; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.widget.Toast; + +import com.example.uhf.R; + +public class UIHelper { + + /** + * 弹出Toast消息 + * + * @param msg + */ + public static void ToastMessage(Context cont, String msg) { + Toast.makeText(cont, msg, Toast.LENGTH_SHORT).show(); + } + + public static void ToastMessage(Context cont, int msg) { + Toast.makeText(cont, msg, Toast.LENGTH_SHORT).show(); + } + + public static void ToastMessage(Context cont, String msg, int time) { + Toast.makeText(cont, msg, time).show(); + } + + /** + * 显示弹出框消息 + * + * @param act + * @param titleInt + * @param messageInt + * @param iconInt + */ + public static void alert(Activity act, int titleInt, int messageInt, + int iconInt) { + try { + AlertDialog.Builder builder = new AlertDialog.Builder(act); + builder.setTitle(titleInt); + builder.setMessage(messageInt); + builder.setIcon(iconInt); + + builder.setNegativeButton(R.string.close, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + builder.create().show(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 显示弹出框消息 + * + * @param act + * @param titleInt + * @param message + * @param iconInt + */ + public static void alert(Activity act, int titleInt, String message, + int iconInt) { + try { + AlertDialog.Builder builder = new AlertDialog.Builder(act); + builder.setTitle(titleInt); + builder.setMessage(message); + builder.setIcon(iconInt); + + builder.setNegativeButton(R.string.close, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + builder.create().show(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/app/src/main/java/com/example/uhf/widget/LazyViewPager.java b/app/src/main/java/com/example/uhf/widget/LazyViewPager.java new file mode 100644 index 0000000..bccee5d --- /dev/null +++ b/app/src/main/java/com/example/uhf/widget/LazyViewPager.java @@ -0,0 +1,1737 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.uhf.widget; + +import android.content.Context; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +import com.example.uhf.activity.UHFMainActivity; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import androidx.core.os.ParcelableCompat; +import androidx.core.os.ParcelableCompatCreatorCallbacks; +import androidx.core.view.MotionEventCompat; +import androidx.core.view.VelocityTrackerCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.ViewConfigurationCompat; +import androidx.core.widget.EdgeEffectCompat; +import androidx.viewpager.widget.PagerAdapter; + +/** + * Layout manager that allows the user to flip left and right + * through pages of data. You supply an implementation of a + * + *

Note this class is currently under early design and + * development. The API will likely change in later updates of + * the compatibility library, requiring changes to the source code + * of apps when they are compiled against the newer version.

+ */ +public class LazyViewPager extends ViewGroup { + private static final String TAG = "LazyViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int DEFAULT_OFFSCREEN_PAGES = 0;//默认的加载页面,ViewPager是1个,所以会加载两个Fragment + private static final int MAX_SETTLE_DURATION = 600; // ms + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + } + + private static final Comparator COMPARATOR = new Comparator(){ + @Override + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + }}; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + // _o(t) = t * t * ((tension + 1) * t + tension) + // o(t) = _o(t - 1) + 1 + t -= 1.0f; + return t * t * t + 1.0f; + } + }; + + private final ArrayList mItems = new ArrayList(); + + private PagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private boolean mScrolling; + private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES; + + private boolean mIsBeingDragged; + private boolean mIsUnableToDrag; + private int mTouchSlop; + private float mInitialMotionX; + /** + * Position of the last motion event. + */ + private float mLastMotionX; + private float mLastMotionY; + /** + * ID of the active pointer. This is used to retain consistency during + * drags/flings if multiple pointers are used. + */ + private int mActivePointerId = INVALID_POINTER; + /** + * Sentinel value for no current active pointer. + * Used by {@link #mActivePointerId}. + */ + private static final int INVALID_POINTER = -1; + + /** + * Determines speed during touch scrolling + */ + private VelocityTracker mVelocityTracker; + private int mMinimumVelocity; + private int mMaximumVelocity; + private float mBaseLineFlingVelocity; + private float mFlingVelocityInfluence; + + private boolean mFakeDragging; + private long mFakeDragBeginTime; + + private EdgeEffectCompat mLeftEdge; + private EdgeEffectCompat mRightEdge; + + private boolean mFirstLayout = true; + + private OnPageChangeListener mOnPageChangeListener; + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + /** + * Called when the scroll state changes. Useful for discovering when the user + * begins dragging, when the pager is automatically settling to the current page, + * or when it is fully stopped/idle. + * + * @param state The new scroll state. + */ + public void onPageScrollStateChanged(int state); + } + + /** + * Simple implementation of the interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + @Override + public void onPageSelected(int position) { + // This space for rent + } + + @Override + public void onPageScrollStateChanged(int state) { + // This space for rent + } + } + + public LazyViewPager(Context context) { + super(context); + initViewPager(); + } + + public LazyViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + initViewPager(); + } + + void initViewPager() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + mLeftEdge = new EdgeEffectCompat(context); + mRightEdge = new EdgeEffectCompat(context); + + float density = context.getResources().getDisplayMetrics().density; + mBaseLineFlingVelocity = 2500.0f * density; + mFlingVelocityInfluence = 0.4f; + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + public void setAdapter(PagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + for (int i = 0; i < mItems.size(); i++) { + final ItemInfo ii = mItems.get(i); + mAdapter.destroyItem(this, ii.position, ii.object); + } + mAdapter.finishUpdate(this); + mItems.clear(); + removeAllViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + mAdapter = adapter; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else { + populate(); + } + } + } + + public PagerAdapter getAdapter() { + return mAdapter; + } + + /** + * Set the currently selected page. If the ViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mItems.size() != 0) { + setScrollingCacheEnabled(false); + return; + } + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + final int pageLimit = mOffscreenPageLimit; + if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + for (int i=0; iThis is offered as an optimization. If you know in advance the number + * of pages you will need to support or have lazy-loading mechanisms in place + * on your pages, tweaking this setting can have benefits in perceived smoothness + * of paging animations and interaction. If you have a small number of pages (3-4) + * that you can keep active all at once, less time will be spent in layout for + * newly created view subtrees as the user pages back and forth.

+ * + *

You should keep this limit low, especially if your pages have complex layouts. + * This setting defaults to 1.

+ * + * @param limit How many pages will be kept offscreen in an idle state. + */ + public void setOffscreenPageLimit(int limit) { + if (limit < DEFAULT_OFFSCREEN_PAGES) { + Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " + + DEFAULT_OFFSCREEN_PAGES); + limit = DEFAULT_OFFSCREEN_PAGES; + } + if (limit != mOffscreenPageLimit) { + mOffscreenPageLimit = limit; + populate(); + } + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(android.graphics.drawable.Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int width = getWidth(); + recomputeScrollPosition(width, width, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + /** + * Like {@link android.view.View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link android.view.View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + setScrollState(SCROLL_STATE_SETTLING); + + final float pageDelta = (float) Math.abs(dx) / (getWidth() + mPageMargin); + int duration = (int) (pageDelta * 100); + + velocity = Math.abs(velocity); + if (velocity > 0) { + duration += (duration / (velocity / mBaseLineFlingVelocity)) * mFlingVelocityInfluence; + } else { + duration += 100; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + void addNewItem(int position, int index) { + ItemInfo ii = new ItemInfo(); + ii.position = position; + ii.object = mAdapter.instantiateItem(this, position); + if (index < 0) { + mItems.add(ii); + } else { + mItems.add(index, ii); + } + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + + boolean needPopulate = mItems.size() < 3 && mItems.size() < mAdapter.getCount(); + int newCurrItem = -1; + + for (int i = 0; i < mItems.size(); i++) { + final ItemInfo ii = mItems.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == PagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == PagerAdapter.POSITION_NONE) { + mItems.remove(i); + i--; + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1)); + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + Collections.sort(mItems, COMPARATOR); + + if (newCurrItem >= 0) { + // TODO This currently causes a jump. + setCurrentItemInternal(newCurrItem, false, true); + needPopulate = true; + } + if (needPopulate) { + populate(); + requestLayout(); + } + } + + void populate() { + if (mAdapter == null) { + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(UHFMainActivity.TAG, "populate is pending, skipping for now..."); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + final int pageLimit = mOffscreenPageLimit; + final int startPos = Math.max(0, mCurItem - pageLimit); + final int N = mAdapter.getCount(); + final int endPos = Math.min(N-1, mCurItem + pageLimit); + + if (DEBUG) Log.v(TAG, "populating: startPos=" + startPos + " endPos=" + endPos); + + // Add and remove pages in the existing list. + int lastPos = -1; + for (int i=0; i endPos) && !ii.scrolling) { + if (DEBUG) Log.i(UHFMainActivity.TAG, "removing: " + ii.position + " @ " + i); + mItems.remove(i); + i--; + mAdapter.destroyItem(this, ii.position, ii.object); + } else if (lastPos < endPos && ii.position > startPos) { + // The next item is outside of our range, but we have a gap + // between it and the last item where we want to have a page + // shown. Fill in the gap. + lastPos++; + if (lastPos < startPos) { + lastPos = startPos; + } + while (lastPos <= endPos && lastPos < ii.position) { + if (DEBUG) Log.i(UHFMainActivity.TAG, "inserting: " + lastPos + " @ " + i); + addNewItem(lastPos, i); + lastPos++; + i++; + } + } + lastPos = ii.position; + } + + // Add any new pages we need at the end. + lastPos = mItems.size() > 0 ? mItems.get(mItems.size()-1).position : -1; + if (lastPos < endPos) { + lastPos++; + lastPos = lastPos > startPos ? lastPos : startPos; + while (lastPos <= endPos) { + if (DEBUG) Log.i(UHFMainActivity.TAG, "appending: " + lastPos); + addNewItem(lastPos, -1); + lastPos++; + } + } + + if (DEBUG) { + Log.i(UHFMainActivity.TAG, "Current page list:"); + for (int i=0; i CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + @Override + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + @Override + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + @Override + public void addView(View child, int index, LayoutParams params) { + if (mInLayout) { + addViewInLayout(child, index, params); + child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + ItemInfo infoForChild(View child) { + for (int i=0; i 0) { + final int oldScrollPos = getScrollX(); + final int oldwwm = oldWidth + oldMargin; + final int oldScrollItem = oldScrollPos / oldwwm; + final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm; + final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin); + scrollTo(scrollPos, getScrollY()); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + mScroller.startScroll(scrollPos, 0, mCurItem * widthWithMargin, 0, newDuration); + } + } else { + int scrollPos = mCurItem * widthWithMargin; + if (scrollPos != getScrollX()) { + completeScroll(); + scrollTo(scrollPos, getScrollY()); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mInLayout = true; + populate(); + mInLayout = false; + + final int count = getChildCount(); + final int width = r-l; + + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + ItemInfo ii; + if (child.getVisibility() != GONE && (ii=infoForChild(child)) != null) { + int loff = (width + mPageMargin) * ii.position; + int childLeft = getPaddingLeft() + loff; + int childTop = getPaddingTop(); + if (DEBUG) Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + + ":" + childLeft + "," + childTop + " " + child.getMeasuredWidth() + + "x" + child.getMeasuredHeight()); + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + } + } + mFirstLayout = false; + } + + @Override + public void computeScroll() { + if (DEBUG) Log.i(UHFMainActivity.TAG, "computeScroll: finished=" + mScroller.isFinished()); + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + if (DEBUG) Log.i(UHFMainActivity.TAG, "computeScroll: still scrolling"); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + + if (mOnPageChangeListener != null) { + final int widthWithMargin = getWidth() + mPageMargin; + final int position = x / widthWithMargin; + final int offsetPixels = x % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + setScrollState(SCROLL_STATE_IDLE); + } + mPopulatePending = false; + mScrolling = false; + for (int i=0; i 0 && scrollX == 0) || (dx < 0 && mAdapter != null && + scrollX >= (mAdapter.getCount() - 1) * getWidth() - 1); + if (DEBUG) Log.v(UHFMainActivity.TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + + if (canScroll(this, false, (int) dx, (int) x, (int) y)) { + // Nested view has scrollable area under this point. Let it be handled there. + mInitialMotionX = mLastMotionX = x; + mLastMotionY = y; + return false; + } + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(UHFMainActivity.TAG, "Starting drag!"); + mIsBeingDragged = true; + setScrollState(SCROLL_STATE_DRAGGING); + mLastMotionX = x; + setScrollingCacheEnabled(true); + } else { + if (yDiff > mTouchSlop) { + // The finger has moved enough in the vertical + // direction to be counted as a drag... abort + // any attempt to drag horizontally, to work correctly + // with children that have scrolling containers. + if (DEBUG) Log.v(UHFMainActivity.TAG, "Starting unable to drag!"); + mIsUnableToDrag = true; + } + } + break; + } + + case MotionEvent.ACTION_DOWN: { + /* + * Remember location of down touch. + * ACTION_DOWN always refers to pointer index 0. + */ + mLastMotionX = mInitialMotionX = ev.getX(); + mLastMotionY = ev.getY(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + + if (mScrollState == SCROLL_STATE_SETTLING) { + // Let the user 'catch' the pager as it animates. + mIsBeingDragged = true; + mIsUnableToDrag = false; + setScrollState(SCROLL_STATE_DRAGGING); + } else { + completeScroll(); + mIsBeingDragged = false; + mIsUnableToDrag = false; + } + + if (DEBUG) Log.v(UHFMainActivity.TAG, "Down at " + mLastMotionX + "," + mLastMotionY + + " mIsBeingDragged=" + mIsBeingDragged + + "mIsUnableToDrag=" + mIsUnableToDrag); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + } + + /* + * The only time we want to intercept motion events is if we are in the + * drag mode. + */ + return mIsBeingDragged; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (mFakeDragging) { + // A fake drag is in progress already, ignore this real one + // but still eat the touch events. + // (It is likely that the user is multi-touching the screen.) + return true; + } + + if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) { + // Don't handle edge touches immediately -- they may actually belong to one of our + // descendants. + return false; + } + + if (mAdapter == null || mAdapter.getCount() == 0) { + // Nothing to present or scroll; nothing to touch. + return false; + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + final int action = ev.getAction(); + boolean needsInvalidate = false; + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + /* + * If being flinged and user touches, stop the fling. isFinished + * will be false if being flinged. + */ + completeScroll(); + + // Remember where the motion event started + mLastMotionX = mInitialMotionX = ev.getX(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + break; + } + case MotionEvent.ACTION_MOVE: + if (!mIsBeingDragged) { + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float xDiff = Math.abs(x - mLastMotionX); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + if (DEBUG) Log.v(UHFMainActivity.TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + if (xDiff > mTouchSlop && xDiff > yDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + mLastMotionX = x; + setScrollState(SCROLL_STATE_DRAGGING); + setScrollingCacheEnabled(true); + } + } + if (mIsBeingDragged) { + // Scroll to follow the motion event + final int activePointerIndex = MotionEventCompat.findPointerIndex( + ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = mLastMotionX - x; + mLastMotionX = x; + float oldScrollX = getScrollX(); + float scrollX = oldScrollX + deltaX; + final int width = getWidth(); + final int widthWithMargin = width + mPageMargin; + + final int lastItemIndex = mAdapter.getCount() - 1; + final float leftBound = Math.max(0, (mCurItem - 1) * widthWithMargin); + final float rightBound = + Math.min(mCurItem + 1, lastItemIndex) * widthWithMargin; + if (scrollX < leftBound) { + if (leftBound == 0) { + float over = -scrollX; + needsInvalidate = mLeftEdge.onPull(over / width); + } + scrollX = leftBound; + } else if (scrollX > rightBound) { + if (rightBound == lastItemIndex * widthWithMargin) { + float over = scrollX - rightBound; + needsInvalidate = mRightEdge.onPull(over / width); + } + scrollX = rightBound; + } + // Don't lose the rounded component + mLastMotionX += scrollX - (int) scrollX; + scrollTo((int) scrollX, getScrollY()); + if (mOnPageChangeListener != null) { + final int position = (int) scrollX / widthWithMargin; + final int positionOffsetPixels = (int) scrollX % widthWithMargin; + final float positionOffset = (float) positionOffsetPixels / widthWithMargin; + mOnPageChangeListener.onPageScrolled(position, positionOffset, + positionOffsetPixels); + } + } + break; + case MotionEvent.ACTION_UP: + if (mIsBeingDragged) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( + velocityTracker, mActivePointerId); + mPopulatePending = true; + final int widthWithMargin = getWidth() + mPageMargin; + final int scrollX = getScrollX(); + final int currentPage = scrollX / widthWithMargin; + int nextPage = initialVelocity > 0 ? currentPage : currentPage + 1; + setCurrentItemInternal(nextPage, true, true, initialVelocity); + + mActivePointerId = INVALID_POINTER; + endDrag(); + needsInvalidate = mLeftEdge.onRelease() | mRightEdge.onRelease(); + } + break; + case MotionEvent.ACTION_CANCEL: + if (mIsBeingDragged) { + setCurrentItemInternal(mCurItem, true, true); + mActivePointerId = INVALID_POINTER; + endDrag(); + needsInvalidate = mLeftEdge.onRelease() | mRightEdge.onRelease(); + } + break; + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + final float x = MotionEventCompat.getX(ev, index); + mLastMotionX = x; + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + mLastMotionX = MotionEventCompat.getX(ev, + MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + if (needsInvalidate) { + invalidate(); + } + return true; + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + boolean needsInvalidate = false; + + final int overScrollMode = ViewCompat.getOverScrollMode(this); + if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS || + (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && + mAdapter != null && mAdapter.getCount() > 1)) { + if (!mLeftEdge.isFinished()) { + final int restoreCount = canvas.save(); + final int height = getHeight() - getPaddingTop() - getPaddingBottom(); + + canvas.rotate(270); + canvas.translate(-height + getPaddingTop(), 0); + mLeftEdge.setSize(height, getWidth()); + needsInvalidate |= mLeftEdge.draw(canvas); + canvas.restoreToCount(restoreCount); + } + if (!mRightEdge.isFinished()) { + final int restoreCount = canvas.save(); + final int width = getWidth(); + final int height = getHeight() - getPaddingTop() - getPaddingBottom(); + final int itemCount = mAdapter != null ? mAdapter.getCount() : 1; + + canvas.rotate(90); + canvas.translate(-getPaddingTop(), -itemCount * (width + mPageMargin) + mPageMargin); + mRightEdge.setSize(height, width); + needsInvalidate |= mRightEdge.draw(canvas); + canvas.restoreToCount(restoreCount); + } + } else { + mLeftEdge.finish(); + mRightEdge.finish(); + } + + if (needsInvalidate) { + // Keep animating + invalidate(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable if needed. + if (mPageMargin > 0 && mMarginDrawable != null) { + final int scrollX = getScrollX(); + final int width = getWidth(); + final int offset = scrollX % (width + mPageMargin); + if (offset != 0) { + // Pages fit completely when settled; we only need to draw when in between + final int left = scrollX - offset + width; + mMarginDrawable.setBounds(left, 0, left + mPageMargin, getHeight()); + mMarginDrawable.draw(canvas); + } + } + } + + /** + * Start a fake drag of the pager. + * + *

A fake drag can be useful if you want to synchronize the motion of the ViewPager + * with the touch scrolling of another view, while still letting the ViewPager + * control the snapping motion and fling behavior. (e.g. parallax-scrolling tabs.) + * Call {@link #fakeDragBy(float)} to simulate the actual drag motion. Call + * {@link #endFakeDrag()} to complete the fake drag and fling as necessary. + * + *

During a fake drag the ViewPager will ignore all touch events. If a real drag + * is already in progress, this method will return false. + * + * @return true if the fake drag began successfully, false if it could not be started. + * + * @see #fakeDragBy(float) + * @see #endFakeDrag() + */ + public boolean beginFakeDrag() { + if (mIsBeingDragged) { + return false; + } + mFakeDragging = true; + setScrollState(SCROLL_STATE_DRAGGING); + mInitialMotionX = mLastMotionX = 0; + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } else { + mVelocityTracker.clear(); + } + final long time = SystemClock.uptimeMillis(); + final MotionEvent ev = MotionEvent.obtain(time, time, MotionEvent.ACTION_DOWN, 0, 0, 0); + mVelocityTracker.addMovement(ev); + ev.recycle(); + mFakeDragBeginTime = time; + return true; + } + + /** + * End a fake drag of the pager. + * + * @see #beginFakeDrag() + * @see #fakeDragBy(float) + */ + public void endFakeDrag() { + if (!mFakeDragging) { + throw new IllegalStateException("No fake drag in progress. Call beginFakeDrag first."); + } + + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int)VelocityTrackerCompat.getYVelocity( velocityTracker, mActivePointerId); + mPopulatePending = true; + if ((Math.abs(initialVelocity) > mMinimumVelocity) + || Math.abs(mInitialMotionX-mLastMotionX) >= (getWidth()/3)) { + if (mLastMotionX > mInitialMotionX) { + setCurrentItemInternal(mCurItem-1, true, true); + } else { + setCurrentItemInternal(mCurItem+1, true, true); + } + } else { + setCurrentItemInternal(mCurItem, true, true); + } + endDrag(); + + mFakeDragging = false; + } + + /** + * Fake drag by an offset in pixels. You must have called {@link #beginFakeDrag()} first. + * + * @param xOffset Offset in pixels to drag by. + * @see #beginFakeDrag() + * @see #endFakeDrag() + */ + public void fakeDragBy(float xOffset) { + if (!mFakeDragging) { + throw new IllegalStateException("No fake drag in progress. Call beginFakeDrag first."); + } + + mLastMotionX += xOffset; + float scrollX = getScrollX() - xOffset; + final int width = getWidth(); + final int widthWithMargin = width + mPageMargin; + + final float leftBound = Math.max(0, (mCurItem - 1) * widthWithMargin); + final float rightBound = Math.min(mCurItem + 1, mAdapter.getCount() - 1) * widthWithMargin; + if (scrollX < leftBound) { + scrollX = leftBound; + } else if (scrollX > rightBound) { + scrollX = rightBound; + } + // Don't lose the rounded component + mLastMotionX += scrollX - (int) scrollX; + scrollTo((int) scrollX, getScrollY()); + if (mOnPageChangeListener != null) { + final int position = (int) scrollX / widthWithMargin; + final int positionOffsetPixels = (int) scrollX % widthWithMargin; + final float positionOffset = (float) positionOffsetPixels / widthWithMargin; + mOnPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + + // Synthesize an event for the VelocityTracker. + final long time = SystemClock.uptimeMillis(); + final MotionEvent ev = MotionEvent.obtain(mFakeDragBeginTime, time, MotionEvent.ACTION_MOVE, + mLastMotionX, 0, 0); + mVelocityTracker.addMovement(ev); + ev.recycle(); + } + + /** + * Returns true if a fake drag is in progress. + * + * @return true if currently in a fake drag, false otherwise. + * + * @see #beginFakeDrag() + * @see #fakeDragBy(float) + * @see #endFakeDrag() + */ + public boolean isFakeDragging() { + return mFakeDragging; + } + + private void onSecondaryPointerUp(MotionEvent ev) { + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); + if (mVelocityTracker != null) { + mVelocityTracker.clear(); + } + } + } + + private void endDrag() { + mIsBeingDragged = false; + mIsUnableToDrag = false; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (event.hasNoModifiers()) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + if (currentFocused != null && nextFocused.getLeft() >= currentFocused.getLeft()) { + handled = pageLeft(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + @Override + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + @Override + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a ViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + @Override + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // ViewPagers should only report accessibility info for the current page, + // otherwise things get very confusing. + + // TODO: Should this note something about the paging container? + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + private class PagerObserver extends DataSetObserver { + + @Override + public void onChanged() { + dataSetChanged(); + } + + @Override + public void onInvalidated() { + dataSetChanged(); + } + } +} diff --git a/app/src/main/java/com/example/uhf/widget/NoScrollViewPager.java b/app/src/main/java/com/example/uhf/widget/NoScrollViewPager.java new file mode 100644 index 0000000..42bfbc9 --- /dev/null +++ b/app/src/main/java/com/example/uhf/widget/NoScrollViewPager.java @@ -0,0 +1,58 @@ +package com.example.uhf.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * Created by Administrator on 2021/6/22. + */ +public class NoScrollViewPager extends LazyViewPager { + private boolean noScroll = true; + + public NoScrollViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + // TODO Auto-generated constructor stub + } + + public NoScrollViewPager(Context context) { + super(context); + } + + public void setNoScroll(boolean noScroll) { + this.noScroll = noScroll; + } + + @Override + public void scrollTo(int x, int y) { + super.scrollTo(x, y); + } + + @Override + public boolean onTouchEvent(MotionEvent arg0) { + /* return false;//super.onTouchEvent(arg0); */ + if (noScroll) + return false; + else + return super.onTouchEvent(arg0); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent arg0) { + if (noScroll) + return false; + else + return super.onInterceptTouchEvent(arg0); + } + + @Override + public void setCurrentItem(int item, boolean smoothScroll) { + super.setCurrentItem(item, smoothScroll); + } + + @Override + public void setCurrentItem(int item) { + super.setCurrentItem(item); + } + +} diff --git a/app/src/main/jniLibs/arm64-v8a/libIGLBarDecoder.so b/app/src/main/jniLibs/arm64-v8a/libIGLBarDecoder.so new file mode 100644 index 0000000..5a93842 Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libIGLBarDecoder.so differ diff --git a/app/src/main/jniLibs/arm64-v8a/libIGLImageAE.so b/app/src/main/jniLibs/arm64-v8a/libIGLImageAE.so new file mode 100644 index 0000000..b09a1dd Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libIGLImageAE.so differ diff --git a/app/src/main/jniLibs/armeabi-v7a/libIGLBarDecoder.so b/app/src/main/jniLibs/armeabi-v7a/libIGLBarDecoder.so new file mode 100644 index 0000000..6f829ad Binary files /dev/null and b/app/src/main/jniLibs/armeabi-v7a/libIGLBarDecoder.so differ diff --git a/app/src/main/jniLibs/armeabi-v7a/libIGLImageAE.so b/app/src/main/jniLibs/armeabi-v7a/libIGLImageAE.so new file mode 100644 index 0000000..a1a5003 Binary files /dev/null and b/app/src/main/jniLibs/armeabi-v7a/libIGLImageAE.so differ diff --git a/app/src/main/res/anim/grow_from_topleft_to_bottomright.xml b/app/src/main/res/anim/grow_from_topleft_to_bottomright.xml new file mode 100644 index 0000000..b172ebe --- /dev/null +++ b/app/src/main/res/anim/grow_from_topleft_to_bottomright.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/anim/slide_left_in.xml b/app/src/main/res/anim/slide_left_in.xml new file mode 100644 index 0000000..7c2a16e --- /dev/null +++ b/app/src/main/res/anim/slide_left_in.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/anim/slide_left_out.xml b/app/src/main/res/anim/slide_left_out.xml new file mode 100644 index 0000000..b82cf26 --- /dev/null +++ b/app/src/main/res/anim/slide_left_out.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/anim/slide_right_in.xml b/app/src/main/res/anim/slide_right_in.xml new file mode 100644 index 0000000..d0a781c --- /dev/null +++ b/app/src/main/res/anim/slide_right_in.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/anim/slide_right_out.xml b/app/src/main/res/anim/slide_right_out.xml new file mode 100644 index 0000000..f78757f --- /dev/null +++ b/app/src/main/res/anim/slide_right_out.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/drawable-hdpi/close.png b/app/src/main/res/drawable-hdpi/close.png new file mode 100644 index 0000000..70e9316 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/close.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..288b665 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable-hdpi/webtext.png b/app/src/main/res/drawable-hdpi/webtext.png new file mode 100644 index 0000000..3e95210 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/webtext.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..6ae570b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..d4fb7cd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..85a6081 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable/actionbar_back.xml b/app/src/main/res/drawable/actionbar_back.xml new file mode 100644 index 0000000..4993b82 --- /dev/null +++ b/app/src/main/res/drawable/actionbar_back.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_bg.xml b/app/src/main/res/drawable/button_bg.xml new file mode 100644 index 0000000..626413e --- /dev/null +++ b/app/src/main/res/drawable/button_bg.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/main/res/drawable/button_bg2.xml b/app/src/main/res/drawable/button_bg2.xml new file mode 100644 index 0000000..e8b2643 --- /dev/null +++ b/app/src/main/res/drawable/button_bg2.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/main/res/drawable/button_bg3.xml b/app/src/main/res/drawable/button_bg3.xml new file mode 100644 index 0000000..5725149 --- /dev/null +++ b/app/src/main/res/drawable/button_bg3.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/main/res/drawable/button_bg_down.xml b/app/src/main/res/drawable/button_bg_down.xml new file mode 100644 index 0000000..06bd38f --- /dev/null +++ b/app/src/main/res/drawable/button_bg_down.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_bg_down2.xml b/app/src/main/res/drawable/button_bg_down2.xml new file mode 100644 index 0000000..5c3e699 --- /dev/null +++ b/app/src/main/res/drawable/button_bg_down2.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_bg_down3.xml b/app/src/main/res/drawable/button_bg_down3.xml new file mode 100644 index 0000000..e318978 --- /dev/null +++ b/app/src/main/res/drawable/button_bg_down3.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_bg_gray.xml b/app/src/main/res/drawable/button_bg_gray.xml new file mode 100644 index 0000000..b099120 --- /dev/null +++ b/app/src/main/res/drawable/button_bg_gray.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_bg_up.xml b/app/src/main/res/drawable/button_bg_up.xml new file mode 100644 index 0000000..d0591a6 --- /dev/null +++ b/app/src/main/res/drawable/button_bg_up.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_bg_up2.xml b/app/src/main/res/drawable/button_bg_up2.xml new file mode 100644 index 0000000..da4250c --- /dev/null +++ b/app/src/main/res/drawable/button_bg_up2.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_bg_up3.xml b/app/src/main/res/drawable/button_bg_up3.xml new file mode 100644 index 0000000..246f66b --- /dev/null +++ b/app/src/main/res/drawable/button_bg_up3.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/card_normal.xml b/app/src/main/res/drawable/card_normal.xml new file mode 100644 index 0000000..b83aa79 --- /dev/null +++ b/app/src/main/res/drawable/card_normal.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/card_press.xml b/app/src/main/res/drawable/card_press.xml new file mode 100644 index 0000000..306804f --- /dev/null +++ b/app/src/main/res/drawable/card_press.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/check_text_color.xml b/app/src/main/res/drawable/check_text_color.xml new file mode 100644 index 0000000..ad3a302 --- /dev/null +++ b/app/src/main/res/drawable/check_text_color.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/check_text_color2.xml b/app/src/main/res/drawable/check_text_color2.xml new file mode 100644 index 0000000..210d6fe --- /dev/null +++ b/app/src/main/res/drawable/check_text_color2.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/rb_bg.xml b/app/src/main/res/drawable/rb_bg.xml new file mode 100644 index 0000000..3e381b5 --- /dev/null +++ b/app/src/main/res/drawable/rb_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rectangle_bg.xml b/app/src/main/res/drawable/rectangle_bg.xml new file mode 100644 index 0000000..f3e961c --- /dev/null +++ b/app/src/main/res/drawable/rectangle_bg.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rectangle_bg2.xml b/app/src/main/res/drawable/rectangle_bg2.xml new file mode 100644 index 0000000..55a23fe --- /dev/null +++ b/app/src/main/res/drawable/rectangle_bg2.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + \ No newline at end of file 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..34a3af7 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_uhfset.xml b/app/src/main/res/layout/activity_uhfset.xml new file mode 100644 index 0000000..b9da269 --- /dev/null +++ b/app/src/main/res/layout/activity_uhfset.xml @@ -0,0 +1,617 @@ + + + + + + + + + + + + + + + + + + + + +