Jelajahi Sumber

1.修改Android Apex Mobile,导入Result。

Pen Li 8 tahun lalu
induk
melakukan
441b843aae

+ 1180 - 0
Apex Mobile/app/src/main/java/com/usai/apex/Result/SearchResultActivity.java

@@ -0,0 +1,1180 @@
+package com.usai.apex.Result;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.DataSetObserver;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.text.Html;
+import android.text.Layout;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.BaseAdapter;
+import android.widget.HorizontalScrollView;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.TableRow;
+import android.widget.TextView;
+
+import com.usai.apex.BuildConfig;
+import com.usai.apex.R;
+//import com.usai.redant.Detail.KVDetailActivity;
+//import com.usai.redant.Detail.OrderDetailActivity;
+//import com.usai.apex.redantmobile.BuildConfig;
+import com.usai.util.Network;
+import com.usai.util.RAUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+//import static com.usai.redant.CommonEditor.CommonEditorActivity.URL_REMOTE;
+
+
+public class SearchResultActivity extends AppCompatActivity implements AbsListView.OnScrollListener {
+
+    private Bundle mParams;
+    private JSONObject resultData;
+
+    private Context mContext;
+    private ListView resultListView;
+    private ResultAdapter adapter;
+
+    private View clickedView;
+    private View.OnTouchListener resultRowClickListener;
+    private GestureDetector detector;
+
+    private TextView footer;
+    private int footer_height = 60;
+
+    ProgressDialog progressDialog;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_search_result);
+
+        mContext = this;
+        resultListView = (ListView)findViewById(R.id.result_table_list);
+
+        progressDialog = new ProgressDialog(mContext);
+        progressDialog.setCancelable(false);
+
+        initClickListener();
+
+
+        footer = new TextView(mContext);
+        footer.setBackgroundColor(Color.WHITE);
+        footer.setGravity(Gravity.CENTER);
+        footer.setText("Load More");
+        footer.setTextSize(sp2px(mContext,8));
+        footer.setVisibility(View.INVISIBLE);
+
+        AbsListView.LayoutParams footerLayoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,footer_height);
+        footer.setLayoutParams(footerLayoutParams);
+
+        resultListView.addFooterView(footer);
+
+
+        adapter = new ResultAdapter(mContext);
+        resultListView.setAdapter(adapter);
+        resultListView.setDividerHeight(0);
+
+        resultListView.setOnScrollListener(this);
+
+        if (savedInstanceState != null) {
+            mParams = savedInstanceState.getBundle("query_params");
+        } else {
+            mParams = getIntent().getBundleExtra("query_params");
+        }
+
+        if (mParams == null) {
+            mParams = new Bundle();
+        }
+
+        String title = mParams.getString("title");
+        setTitle(title);
+
+        loadData();
+
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putBundle("query_params",mParams);
+    }
+
+    // 动态修改Menu
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        menu.clear();
+
+
+        if (resultData != null) {
+            try {
+                JSONArray menu_json = resultData.getJSONArray("menu");
+
+                if (menu_json != null && menu_json.length() > 0) {
+
+                    for (int i = 0; i < menu_json.length(); i++) {
+                        JSONObject json = menu_json.getJSONObject(i);
+                        String title = json.getString("title");
+                        menu.add(0, i, 0, title);
+                    }
+                }
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return true;
+    }
+
+//    @Override
+//    public boolean onCreateOptionsMenu(Menu menu) {
+//        getMenuInflater().inflate(R.menu.result_menu,menu);
+//        return true;
+//    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+
+//        if (item.getItemId() == R.id.result_menu) {
+//
+//            try {
+//
+//                JSONArray menu = resultData.getJSONArray("menu");
+//
+//                if (menu.length() > 0) {
+//                    ArrayList<String> titleList = new ArrayList<>();
+//
+//                    for (int i = 0; i < menu.length(); i++) {
+//                        JSONObject json = menu.getJSONObject(i);
+//                        String title = json.getString("title");
+//                        titleList.add(title);
+//                    }
+//
+//                    new AlertDialog.Builder(mContext)
+//                            .setSingleChoiceItems((String[])titleList.toArray(new String[titleList.size()]), -1, new DialogInterface.OnClickListener() {
+//                                @Override
+//                                public void onClick(DialogInterface dialog, int which) {
+//
+//                                    try {
+//                                        JSONArray menu = resultData.getJSONArray("menu");
+//                                        JSONObject json = menu.getJSONObject(which);
+//
+//                                        String actionType = json.getString("action");
+//                                        String url = json.optString("url");
+//
+//                                        if (actionType.equals("download")) {
+//                                            export(url);
+//                                        } else if (actionType.equals("save")) {
+//                                            if(BuildConfig.DEBUG && true){
+//                                                //do something for assert aim
+//                                                Log.e("Result", "onOptionsItemSelected DialogClick: not implement");
+//                                            }
+//                                        }
+//
+//                                    } catch (JSONException exception) {
+//                                        Log.d("Result", "onClick: ",exception);
+//                                    }
+//                                    dialog.dismiss();
+//                                }
+//                            })
+//                            .show();
+//                }
+//
+//            } catch (JSONException e) {
+//                Log.e("Result", "onOptionsItemSelected: ", e);
+//            }
+//
+//        }
+
+        int which = item.getItemId();
+        try {
+            JSONArray menu = resultData.getJSONArray("menu");
+            JSONObject json = menu.getJSONObject(which);
+
+            String actionType = json.getString("action");
+            String url = json.optString("url");
+
+            if (actionType.equals("download")) {
+                export(url);
+            } else if (actionType.equals("save")) {
+                if(BuildConfig.DEBUG && true){
+                    //do something for assert aim
+                    Log.e("Result", "onOptionsItemSelected DialogClick: not implement");
+                }
+            }
+
+        } catch (JSONException exception) {
+            Log.d("Result", "onClick: ",exception);
+        }
+
+        return true;
+    }
+
+    public int last_index;
+    public int total_index;
+    public boolean isLoading = false;//表示是否正处于加载状态
+
+    @Override
+    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+        last_index = firstVisibleItem+visibleItemCount;
+        total_index = totalItemCount;
+    }
+
+    @Override
+    public void onScrollStateChanged(AbsListView view, int scrollState) {
+        if(last_index == total_index && (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE))
+        {
+            // 表示此时需要显示刷新视图界面进行新数据的加载(要等滑动停止)
+            if(!isLoading)
+            {
+                // 设置刷新界面可见
+                footer.setVisibility(View.VISIBLE);
+                loadMore();
+            }
+        }
+    }
+
+    private void setupUI() {
+        try {
+            if (resultData == null) {
+                return;
+            } else {
+                int result = resultData.getInt("result");
+                if (result != 2) {
+                    return;
+                }
+            }
+            JSONObject layout = resultData.getJSONObject("layout");
+
+            JSONObject header = layout.getJSONObject("header");
+            int width = header.getInt("width");
+            width = convertDp2Px(width);
+
+            AbsListView.LayoutParams footerLayoutParams = (AbsListView.LayoutParams)footer.getLayoutParams();
+            if (footerLayoutParams == null) {
+                footerLayoutParams = new AbsListView.LayoutParams(width,footer_height);
+            }
+            footerLayoutParams.height = footer_height;
+            footerLayoutParams.width = width;
+
+            footer.setLayoutParams(footerLayoutParams);
+
+
+        } catch (JSONException e) {
+            Log.e("Result", "setupUI: ", e);
+        }
+
+    }
+
+    public void loadComplete() {
+        footer.setVisibility(View.GONE);//设置刷新界面不可见
+        resultListView.forceLayout();
+
+        isLoading = false;//设置正在刷新标志位false
+        invalidateOptionsMenu();
+
+        String title = resultData.optString("table_title");
+        setTitle(title);
+
+        progressDialog.dismiss();
+    }
+
+
+    private void showProgressDialog(String title, String msg) {
+        progressDialog.setTitle(title);
+        progressDialog.setMessage(msg);
+        progressDialog.show();
+    }
+
+    JSONObject readRawFile(int id)
+    {
+        String content;
+        Resources resources=this.getResources();
+        InputStream is=null;
+        try{
+            is=resources.openRawResource(id);
+            byte buffer[]=new byte[is.available()];
+            is.read(buffer);
+            content=new String(buffer);
+            JSONObject json = new JSONObject(content);
+            return json;
+        }
+        catch(IOException e)
+        {
+            e.printStackTrace();
+        }
+        catch (JSONException e) {
+            e.printStackTrace();
+        }
+        finally
+        {
+            if(is!=null)
+            {
+                try{
+                    is.close();
+                }catch(IOException e)
+                {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return null;
+    }
+
+    private void loadData() {
+
+//        resultData = readRawFile(R.raw.predef_query);
+//        if (1 == 1) {
+//            return;
+//        }
+
+        isLoading = true;
+
+        showProgressDialog(null,"Loading");
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+                try {
+
+                    mParams.putInt("offset",adapter.getCount());
+                    mParams.putInt("limit",25);
+                    resultData = Network.query(mParams);
+                    if (resultData == null) {
+                        resultData = new JSONObject();
+                    }
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            setupUI();
+                            loadComplete();
+                            int result = resultData.optInt("result",0);
+                            if (result == 2) {
+
+                            } else {
+
+                                String msg = resultData.optString("msg");
+                                if (msg == null || msg.isEmpty()) {
+                                    msg = "Sorry,some error occurred";
+                                }
+
+                                new AlertDialog.Builder(mContext)
+                                        .setTitle("Warning")
+                                        .setMessage(msg)
+                                        .show();
+                            }
+
+                            adapter.notifyDataSetChanged();
+                        }
+                    });
+
+                } catch (Exception e) {
+                    Log.e("Result", "onCreate: ",e);
+                }
+
+
+
+
+            }
+        }).start();
+
+    }
+
+    private void loadMore() {
+
+        isLoading = true;
+        showProgressDialog(null,"Loading");
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+                try {
+
+//                    Thread.sleep(2000);
+//
+//                    InputStream in = getResources().openRawResource( R.raw.result);
+//                    int length = in.available();
+//                    byte[] buffer = new byte[length];
+//                    in.read(buffer);
+//                    String res = new String(buffer,"utf8");
+//                    in.close();
+//
+//                    JSONObject newJson = new JSONObject(res);
+
+                    mParams.putInt("offset",adapter.getCount());
+                    mParams.putInt("limit",25);
+                    JSONObject newJson = Network.query(mParams);
+
+                    if (newJson != null) {
+
+                        int result = newJson.getInt("result");
+                        if (result == 2) {
+                            JSONObject newData = newJson.getJSONObject("data");
+                            int add_count = newData.getInt("count");
+
+                            JSONObject data = resultData.getJSONObject("data");
+                            int count = data.getInt("count");
+
+                            for (int i = 0; i < add_count; i++) {
+                                JSONArray new_data_item = newData.getJSONArray("item_" + i);
+                                if (new_data_item != null) {
+                                    data.put("item_" + count++,new_data_item);
+                                }
+                            }
+                            data.put("count",count);
+                            resultData.put("data",data);
+
+                            runOnUiThread(new Runnable() {
+                                @Override
+                                public void run() {
+                                    setupUI();
+                                    loadComplete();
+                                    adapter.notifyDataSetChanged();
+                                }
+                            });
+                        } else {
+                            String msg = newJson.getString("msg");
+                            if (msg == null || msg.isEmpty()) {
+                                msg = "Some error occurred";
+                            }
+                            showAlert(msg);
+                        }
+
+
+                    }
+
+
+                } catch (Exception e) {
+                    Log.e("Result", "onCreate: ",e);
+                    showAlert("Some error occurred");
+                }
+
+
+
+
+            }
+        }).start();
+    }
+
+    private JSONObject contentData() {
+        try {
+            return resultData.getJSONObject("data");
+        } catch (JSONException e) {
+            Log.e("Result", "contentData: ", e);
+        }
+        return null;
+    }
+
+    private class GestureListener extends GestureDetector.SimpleOnGestureListener {
+
+        @Override
+        public boolean onDoubleTapEvent(MotionEvent e) {
+
+
+            if (e.getAction() == MotionEvent.ACTION_UP) {
+
+                TableRow cellRow = (TableRow)clickedView.getParent();
+                RelativeLayout cell = (RelativeLayout)cellRow.getParent();
+
+                int position = resultListView.getPositionForView(cell);
+//                Log.d("Result", "onDoubleTapEvent: " + position);
+
+                if (position == 0) {
+                    return false;
+                }
+
+                try {
+
+                    JSONArray row_action = resultData.optJSONArray("row_action");
+                    if (row_action != null) {
+
+                        if (row_action.length() == 1) {
+
+                            JSONObject action = row_action.getJSONObject(0);
+                            String module = action.getString("module");
+
+                            if (module.equals("quick_look")) {
+                                JSONObject param = action.getJSONObject("params");
+                                String url = action.getString("url");
+                                showQuickLook(param,url);
+                            } else if (module.equals("kv_detail")) {
+                                JSONObject params = new JSONObject();
+                                params.put("query_id",mParams.get("query_id"));
+
+                                JSONObject criteria = new JSONObject();
+                                JSONObject action_params = action.getJSONObject("params");
+                                Iterator<String> iterator = action_params.keys();
+                                while (iterator.hasNext()) {
+                                    String key = iterator.next();
+                                    JSONArray item = contentData().getJSONArray("item_" + position);
+                                    int idx = action_params.getInt(key);
+                                    criteria.put(key,item.get(idx));
+                                }
+
+                                params.put("criteria",criteria.toString());
+                                showKVDetail(params);
+
+                            } else if (module.equals("order_detail")) {
+
+                                showOrderDetail();
+
+                            }
+
+
+                        } else if (row_action.length() > 1) {
+
+                            ArrayList<String> titleList = new ArrayList<>();
+
+                            for (int i = 0; i < row_action.length(); i++) {
+                                JSONObject json = row_action.getJSONObject(i);
+                                String title = json.getString("title");
+                                titleList.add(title);
+                            }
+
+                            new AlertDialog.Builder(mContext)
+                                    .setSingleChoiceItems((String[])titleList.toArray(new String[titleList.size()]), -1, new DialogInterface.OnClickListener() {
+                                        @Override
+                                        public void onClick(DialogInterface dialog, int which) {
+
+                                            try {
+                                                JSONArray content_action = resultData.getJSONArray("row_action");
+                                                JSONObject json = content_action.getJSONObject(which);
+                                                String module = json.getString("module");
+                                                JSONObject add_params = json.getJSONObject("params");
+
+                                                if (module.equals("quick_look")) {
+                                                    JSONObject param = json.getJSONObject("params");
+                                                    String url = json.getString("url");
+                                                    showQuickLook(param,url);
+                                                } else if (module.equals("kv_detail")) {
+
+                                                    JSONObject params = json.getJSONObject("params");
+                                                    showKVDetail(params);
+
+                                                } else if (module.equals("order_detail")) {
+
+                                                    showOrderDetail();
+
+                                                }
+
+
+                                            } catch (JSONException exception) {
+                                                Log.d("Result", "onClick: ",exception);
+                                            }
+                                            dialog.dismiss();
+
+                                        }
+                                    })
+                                    .show();
+
+                        }
+
+                    }
+
+                } catch (JSONException exception) {
+                    Log.e("Result", "onDoubleTapEvent: ",exception);
+                }
+
+            }
+
+            return false;
+        }
+
+        @Override
+        public boolean onSingleTapConfirmed(MotionEvent e) {
+            if (clickedView instanceof TextView) {
+                TextView tv = (TextView)clickedView;
+                if (ellipsisTextView(tv)) {
+                    showAlert(tv.getText().toString());
+                }
+            }
+            return false;
+        }
+    }
+
+    private void initClickListener() {
+
+        // 需要作为成员变量
+        detector = new GestureDetector(mContext, new GestureListener());
+
+        resultRowClickListener = new View.OnTouchListener() {
+
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+
+                clickedView = v;
+
+                detector.onTouchEvent(event);
+
+                return true;
+            }
+        };
+
+    }
+
+
+
+    private class ResultAdapter extends BaseAdapter {
+
+        @Override
+        public boolean areAllItemsEnabled() {
+            return true;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            return true;
+        }
+
+        private class ResultHoder {
+            public ResultHoder(View view) {
+                row = (TableRow)view.findViewById(R.id.result_row);
+                view.setTag(this);
+            }
+            TableRow row;
+        }
+
+        public ResultAdapter(Context ctx) {
+
+        }
+
+        @Override
+        public void registerDataSetObserver(DataSetObserver observer) {
+
+        }
+
+        @Override
+        public void unregisterDataSetObserver(DataSetObserver observer) {
+
+        }
+
+        @Override
+        public int getCount() {
+            if (resultData == null) {
+                return 0;
+            } else {
+                int result = resultData.optInt("result");
+                if (result != 2) {
+                    return 0;
+                }
+            }
+            try {
+                JSONObject data = resultData.getJSONObject("data");
+                int result_count = data.getInt("count");
+                return result_count + 1; // header + data
+
+            } catch (JSONException e) {
+                Log.e("Result", "getCount: ", e);
+                return 0;
+            }
+        }
+
+        @Override
+        public Object getItem(int position) {
+            try {
+                if (position == 0) {
+                    // header
+
+                    JSONObject layout = resultData.getJSONObject("layout");
+                    JSONObject header = layout.getJSONObject("header");
+                    JSONArray col = header.getJSONArray("col");
+
+                    return col;
+
+                } else {
+                    // result row
+
+                    JSONObject data = resultData.getJSONObject("data");
+                    JSONArray item = data.getJSONArray("item_" + (position - 1));
+
+                    return item;
+                }
+
+
+            } catch (JSONException e) {
+                Log.e("Result", "getItem: ", e);
+            }
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public boolean hasStableIds() {
+            return false;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+
+            View cell;
+            ResultHoder holder;
+            if (convertView == null) {
+
+                cell = LayoutInflater.from(mContext).inflate(R.layout.result_cell,null);
+                holder = new ResultHoder(cell);
+
+
+            } else {
+
+                cell = convertView;
+                holder = (ResultHoder)cell.getTag();
+
+            }
+//            holder.row.removeAllViews();
+
+//            cell.setOnTouchListener(resultRowClickListener);
+
+            // setup
+           try {
+
+               JSONObject layout = resultData.getJSONObject("layout");
+
+               JSONObject header = layout.getJSONObject("header");
+               int width = header.getInt("width");
+               int height = header.getInt("height");
+               int margin_t = header.getInt("margin_t");
+               int margin_l = header.getInt("margin_l");
+               int margin_b = header.getInt("margin_b");
+               int margin_r = header.getInt("margin_r");
+
+               width = convertDp2Px(width);
+               height = convertDp2Px(height);
+               margin_t = convertDp2Px(margin_t);
+               margin_l = convertDp2Px(margin_l);
+               margin_b = convertDp2Px(margin_b);
+               margin_r = convertDp2Px(margin_r);
+
+               HorizontalScrollView.LayoutParams listViewLayoutParams = (HorizontalScrollView.LayoutParams)resultListView.getLayoutParams();
+               listViewLayoutParams.width = width;
+               resultListView.setLayoutParams(listViewLayoutParams);
+
+               JSONArray obj = (JSONArray)getItem(position);
+               if (position == 0) {
+
+                   // header
+                   String bg_color = header.getString("bg_color");
+                   String f_color = header.getString("f_color");
+
+                   bg_color = bg_color.replace("0x","#");
+                   f_color = f_color.replace("0x","#");
+
+                   RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)holder.row.getLayoutParams();
+                   layoutParams.height = height;
+                   holder.row.setLayoutParams(layoutParams);
+
+                   // col
+                   for (int i = 0; i < obj.length(); i++) {
+
+                       JSONObject value = obj.getJSONObject(i);
+                       int col_w = value.getInt("width");
+                       col_w = convertDp2Px(col_w);
+
+                       String h_align = value.getString("h_align");
+                       String v_center = value.getString("v_center");
+                       String col_bg_color = value.getString("bg_color");
+                       String col_f_color = value.getString("f_color");
+                       String name = value.getString("name");
+
+                       bg_color = bg_color.replace("0x","#");
+                       f_color = f_color.replace("0x","#");
+
+                       TextView tv = (TextView)holder.row.findViewById(i);
+                       if (tv == null) {
+                           tv = new TextView(mContext);
+                           tv.setWidth(col_w);
+                           tv.setHeight(height);
+                           tv.setGravity(convertGravity("h_align",h_align) | convertGravity("v_center",v_center));
+
+                           tv.setTextColor(Color.parseColor(f_color));
+
+                           tv.setSingleLine();
+                           tv.setEllipsize(TextUtils.TruncateAt.END);
+
+                           tv.setPadding(margin_l,margin_t,margin_r,margin_b);
+
+                           TableRow.LayoutParams tvLayoutParams = new  TableRow.LayoutParams(col_w, height);
+//                       tv.setLayoutParams(tvLayoutParams);
+
+                           tv.setId(i);
+                           holder.row.addView(tv,i,tvLayoutParams);
+                           tv.setBackgroundDrawable(getResources().getDrawable(R.drawable.result_black_border));
+
+                           tv.setOnTouchListener(resultRowClickListener);
+                       }
+
+
+                       if (name.contains("</")) {
+                           tv.setText(Html.fromHtml(name));
+                       } else {
+                           tv.setText(name);
+                       }
+
+                   }
+                   holder.row.setBackgroundColor(Color.parseColor(bg_color));
+
+               } else {
+
+                   // row
+                   JSONObject row = layout.getJSONObject("row");
+                   String f_color = row.getString("f_color");
+                   String color_0 = row.getString("color_0");
+                   String color_1 = row.getString("color_1");
+                   f_color = f_color.replace("0x","#");
+                   color_0 = color_0.replace("0x","#");
+                   color_1 = color_1.replace("0x","#");
+
+                   int row_h = row.getInt("height");
+                   row_h = convertDp2Px(row_h);
+
+                   RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)holder.row.getLayoutParams();
+                   layoutParams.height = row_h;
+                   holder.row.setLayoutParams(layoutParams);
+
+                   // col
+                   for (int i = 0; i < obj.length(); i++) {
+
+                       JSONArray col_layout = row.getJSONArray("val");
+                       JSONObject layout_val = col_layout.getJSONObject(i);
+
+                       String type = layout_val.getString("type");
+                       String h_align = layout_val.getString("h_align");
+                       String v_center = layout_val.getString("v_center");
+                       String col_bg_color = layout_val.getString("bg_color");
+                       String col_f_color = layout_val.getString("f_color");
+
+                       col_bg_color = col_bg_color.replace("0x","#");
+                       col_f_color = col_f_color.replace("0x","#");
+
+                       String value = obj.getString(i);
+
+
+                       JSONObject size = ((JSONArray)getItem(0)).getJSONObject(i);
+                       int col_w = size.getInt("width");
+                       int col_h = row.getInt("height");
+
+                       col_w = convertDp2Px(col_w);
+                       col_h = convertDp2Px(col_h);
+
+                       TextView tv = (TextView) holder.row.findViewById(i);
+                       if (tv == null) {
+                           tv = new TextView(mContext);
+                           tv.setWidth(col_w);
+                           tv.setHeight(col_h);
+                           tv.setGravity(convertGravity("h_align",h_align) | convertGravity("v_center",v_center));
+                           tv.setTextColor(Color.parseColor(col_f_color));
+
+                           tv.setSingleLine();
+                           tv.setEllipsize(TextUtils.TruncateAt.END);
+
+                           tv.setPadding(margin_l,margin_t,margin_r,margin_b);
+
+                           TableRow.LayoutParams tvLayoutParams = new  TableRow.LayoutParams(col_w, col_h);
+
+                           tv.setId(i);
+                           holder.row.addView(tv,i,tvLayoutParams);
+
+                           tv.setOnTouchListener(resultRowClickListener);
+                           tv.setBackgroundDrawable(getResources().getDrawable(R.drawable.result_black_border));
+                       }
+
+
+                       if (value.contains("</")) {
+                           tv.setText(Html.fromHtml(value));
+                       } else {
+                           tv.setText(value);
+                       }
+
+
+                   }
+
+                   if ((position - 1) % 2 == 0) {
+                       holder.row.setBackgroundColor(Color.parseColor(color_0));
+                   } else {
+                       holder.row.setBackgroundColor(Color.parseColor(color_1));
+
+                   }
+
+               }
+
+           } catch (JSONException e) {
+               Log.e("Result", "getView: ", e);
+           }
+
+            return cell;
+        }
+
+        private int convertGravity(String key, String align) {
+
+            if (key.equals("h_align")) {
+                if (align.equals("center")) {
+                    return Gravity.CENTER_HORIZONTAL;
+                } else if (align.equals("left")) {
+                    return Gravity.LEFT;
+                } else if (align.equals("right")) {
+                    return Gravity.RIGHT;
+                }
+
+            }
+
+            if (key.equals("v_center")) {
+
+                if (align.equals("center")) {
+                    return Gravity.CENTER_VERTICAL;
+                } else if (align.equals("top")) {
+                    return Gravity.TOP;
+                } else if (align.equals("bottom")) {
+                    return Gravity.BOTTOM;
+                }
+            }
+            return Gravity.CENTER;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            return 0;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 1;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return false;
+        }
+    }
+
+
+    public boolean ellipsisTextView(TextView tv) {
+        Layout l = tv.getLayout();
+        if ( l != null){
+            int lines = l.getLineCount();
+            if ( lines > 0) {
+                if (l.getEllipsisCount(lines - 1) > 0) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public int convertDp2Px(int dp) {
+        return dp2px(mContext,dp);
+    }
+
+    public int px2dp(Context context, float pxValue) {
+        float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (pxValue / scale + 0.5f);
+    }
+
+    public int dp2px(Context context, float dpValue) {
+        float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+
+    public int px2sp(Context context, float pxValue) {
+        float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+        return (int) (pxValue / fontScale + 0.5f);
+    }
+
+    public int sp2px(Context context, float spValue) {
+        float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+        return (int) (spValue * fontScale + 0.5f);
+    }
+
+
+    private String documentPath;
+    private String download_query;
+    private void export(final String download_url) {
+
+        if (download_query != null) {
+            documentPath = download_query;
+            Uri uri= Uri.parse(download_query);
+            openFileAtPath(uri,"*/*");
+            return;
+        }
+
+        showProgressDialog(null,"Please wait");
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+                // download & get path
+                final String path = Network.download_query(download_url);
+
+
+                documentPath = path;
+                download_query = path;
+
+
+                if (path != null) {
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            progressDialog.dismiss();
+                            Uri uri= Uri.parse(documentPath);
+                            openFileAtPath(uri,RAUtil.getMimeType(documentPath));
+                        }
+                    });
+                }
+
+            }
+        }).start();
+
+    }
+
+    public void showAlert(String msg) {
+        if (msg == null || msg.isEmpty()) {
+            return;
+        }
+
+        new AlertDialog.Builder(mContext)
+                .setMessage(msg)
+                .show();
+    }
+
+    public void showOrderDetail() {
+//        Intent intent = OrderDetailActivity.build(mContext,OrderDetailActivity.class,null,URL_REMOTE,null,new Bundle());
+//
+//        startActivity(intent);
+    }
+
+    public void showKVDetail(final JSONObject param) {
+        showProgressDialog("Please wait","Loading...");
+
+//        new Thread(new Runnable() {
+//            @Override
+//            public void run() {
+//
+//                final JSONObject json = Network.kv_detail(RAUtil.Json2Bundle(param));
+////                final JSONObject json = readRawFile(R.raw.kv);
+//
+//                runOnUiThread(new Runnable() {
+//                    @Override
+//                    public void run() {
+//                        progressDialog.dismiss();
+//
+//                        int result = 0;
+//                        if (json != null) {
+//                            result = json.optInt("result",0);
+//                        }
+//                        if (result == 2) {
+//
+//                            Intent intent = KVDetailActivity.build(mContext,json.toString());
+//
+//                            startActivity(intent);
+//
+//                        } else {
+//                            String msg = json.optString("msg");
+//                            if (msg == null) {
+//                                msg = "Sorry,some error occurred";
+//                            }
+//                            showAlert(msg);
+//                        }
+//
+//                    }
+//                });
+//
+//            }
+//        }).start();
+
+    }
+
+    public void showQuickLook(final JSONObject param, final String url) {
+
+        showProgressDialog("Please wait","Downloading...");
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+                // 下载文件
+                final String path = Network.downloadFile(RAUtil.Json2Bundle(param),url);
+                final String type = RAUtil.getMimeType(path);
+
+                runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        progressDialog.dismiss();
+                        if (path != null && !path.isEmpty()) {
+                            Uri uri= Uri.parse(path);
+                            openFileAtPath(uri,type);
+                        }
+                    }
+                });
+
+            }
+        }).start();
+
+
+    }
+
+    private void openFileAtPath(Uri uri, String type) {
+        // type "application/pdf"
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        intent.setDataAndType(uri, type);
+        if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
+            // someone knows how to handle this mime type with this scheme, don't download.
+            try {
+                startActivity(intent);
+                return;
+            } catch (Exception ex) {
+                Log.d("Open File", "activity not found for " + type + " over " + uri, ex);
+            }
+
+        } else {
+            Log.d("Open File", "openFileAtPath: " + "No App " + uri);
+            try {
+                shareFile(uri,type);
+            } catch (Exception e) {
+                Log.e("Show Dialog Error", "openFileAtPath: ", e);
+            }
+        }
+
+    }
+
+    private void shareFile(Uri uri, String type) {
+
+        Intent shareIntent = new Intent();
+        shareIntent.setAction(Intent.ACTION_SEND);
+        shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
+        shareIntent.setType(type);
+        startActivity(Intent.createChooser(shareIntent, "Share"));
+    }
+
+
+}

+ 143 - 0
Apex Mobile/app/src/main/java/com/usai/util/Network.java

@@ -1,10 +1,18 @@
 package com.usai.util;
 
 import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
 import java.net.Socket;
+import java.net.URL;
+import java.net.URLEncoder;
 import java.net.UnknownHostException;
 import java.security.KeyManagementException;
 import java.security.KeyStore;
@@ -12,7 +20,10 @@ import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.UnrecoverableKeyException;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
@@ -1408,4 +1419,136 @@ public class Network
 			return sslContext.getSocketFactory().createSocket();
 		}
 	}
+
+	private static String createPostParameters(Bundle parms) throws UnsupportedEncodingException {
+		StringBuilder result = new StringBuilder();
+		boolean first = true;
+		for(String key : parms.keySet()){
+			if (first)
+				first = false;
+			else
+				result.append("&");
+
+			result.append(URLEncoder.encode(key, "UTF-8"));
+			result.append("=");
+			result.append(URLEncoder.encode(parms.get(key).toString(), "UTF-8"));
+		}
+
+		return result.toString();
+	}
+
+	//读取响应头
+	public static JSONObject getResponseHeader(HttpURLConnection conn) {
+		Map<String, List<String>> responseHeaderMap = conn.getHeaderFields();
+		int size = responseHeaderMap.size();
+		try {
+			JSONObject responseHeader = new JSONObject();
+			for(int i = 0; i < size; i++){
+				String responseHeaderKey = conn.getHeaderFieldKey(i);
+				String responseHeaderValue = conn.getHeaderField(i);
+				if (responseHeaderKey != null && !responseHeaderKey.isEmpty() && responseHeaderValue != null) {
+					responseHeader.put(responseHeaderKey,responseHeaderValue);
+				}
+			}
+			return responseHeader;
+		} catch (JSONException e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	public static String getResponsesuggestedFilename(JSONObject response) {
+
+		if (response == null) {
+			return null;
+		}
+
+		try {
+			String key = "Content-Disposition";
+			String content_disposition = response.getString(key);
+			if (content_disposition != null) {
+				String[] components = content_disposition.split(";");
+				if (components[1] != null) {
+					String fileName = components[1].split("=")[1];
+					fileName = fileName.replace("\"","");
+					return fileName;
+				}
+			}
+
+		} catch (JSONException e) {
+			e.printStackTrace();
+		}
+
+
+		return null;
+	}
+
+	public static String downloadFile(Bundle params, String download_url) {
+
+		HttpURLConnection connection = null;
+		try {
+
+			String fileName = UUID.randomUUID().toString();
+			String dir = "download";
+			if (RAUtil.isFileExist(fileName,dir)) {
+				return dir + File.separator + fileName;
+			} else {
+				// 创建一个URL对象
+				URL url=new URL(download_url);
+				// 创建一个HTTP链接
+				connection=(HttpURLConnection)url.openConnection();
+
+				// 拼参数
+				if (params != null && params.keySet().size() > 0) {
+					OutputStream os = connection.getOutputStream();
+					BufferedWriter writer = new BufferedWriter(
+							new OutputStreamWriter(os, "UTF-8"));
+					writer.write(createPostParameters(params));
+
+					writer.flush();
+					writer.close();
+					os.close();
+				}
+
+				// 获取响应
+				JSONObject responseHeader = getResponseHeader(connection);
+				String suggestedFileName = getResponsesuggestedFilename(responseHeader);
+				Log.d("Download", "download_query: " + suggestedFileName);
+				if (suggestedFileName != null && !suggestedFileName.isEmpty()) {
+					fileName = suggestedFileName;
+				}
+
+				// 使用IO流获取数据
+				InputStream inputStream=connection.getInputStream();
+				// 写文件
+				File downloadFile = RAUtil.write2SDFromInput(fileName,dir,inputStream);
+
+				if (downloadFile == null) {
+					return null;
+				} else {
+					return downloadFile.getAbsolutePath();
+				}
+			}
+
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			if (connection != null) {
+				connection.disconnect();
+			}
+		}
+
+
+
+		return null;
+	}
+
+	public static String download_query(String download_url) {
+
+		return downloadFile(null,download_url);
+	}
+
+	public  static JSONObject query(Bundle params) {
+		return null;
+	}
 }

+ 694 - 0
Apex Mobile/app/src/main/java/com/usai/util/RAUtil.java

@@ -0,0 +1,694 @@
+package com.usai.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.media.ExifInterface;
+import android.media.MediaScannerConnection;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.PermissionChecker;
+import android.util.Log;
+import android.webkit.MimeTypeMap;
+
+import com.usai.apex.ApexTrackingApplication;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Created by ray on 27/06/2017.
+ */
+
+
+public class RAUtil {
+    public static final int MY_PERMISSIONS_REQUEST= 1;
+//    public static void checkPermissions1(Activity activity, String[] permissions)
+//    {
+//        Log.d("_RAIMAGE", "checkPermissions1:==================================== ");
+//        for(String permission : permissions) {
+//            boolean bshow=ActivityCompat.shouldShowRequestPermissionRationale(activity,permission);
+//            boolean granted= ContextCompat.checkSelfPermission(activity,
+//                    Manifest.permission.ACCESS_FINE_LOCATION)
+//                    == PackageManager.PERMISSION_GRANTED;
+//            boolean pc = PermissionChecker.checkSelfPermission(activity,permission)==PermissionChecker.PERMISSION_GRANTED;
+//            Log.d("_RAIMAGE", "checkPermissions1: "+permission+"  SHOW  "+bshow+"  granted  "+granted +","+pc);
+//        }
+//        Log.d("_RAIMAGE", "checkPermissions1:==================================== ");
+//    }
+    public static boolean isNumeric(String str){
+        for (int i = 0; i < str.length(); i++){
+            System.out.println(str.charAt(i));
+            if (!Character.isDigit(str.charAt(i))){
+                return false;
+            }
+        }
+        return true;
+    }
+    public static Boolean checkPermissions(Activity activity, String[] permissions)
+    {
+        if (Build.VERSION.SDK_INT >= 23)
+        {
+            return checkPermissions_23(activity,permissions);
+        }
+        else
+        {
+            return false;
+//            return checkPermissions_23(activity,permissions);
+        }
+    }
+
+    public static Boolean checkPermissions_23(String[] permissions)
+    {
+        Log.d("_RAIMAGE", "checkPermissions23:==================================== ");
+        ArrayList<String> request_list = new ArrayList<String>();
+        Context context = ApexTrackingApplication.getInstance().getApplicationContext();
+        for(String permission : permissions) {
+
+            boolean pc = PermissionChecker.checkSelfPermission(context,permission)== PermissionChecker.PERMISSION_GRANTED;
+            if(!pc)
+                return false;
+        }
+        Log.d("_RAIMAGE", "checkPermissions23:==================================== ");
+
+
+
+        return true;
+
+    }
+
+    public static void updateGallery(String filename)//filename是我们的文件全名,包括后缀哦
+    {
+
+        Context context = ApexTrackingApplication.getInstance().getApplicationContext();
+        MediaScannerConnection.scanFile(context,
+                new String[] { filename }, null,
+                new MediaScannerConnection.OnScanCompletedListener() {
+                    public void onScanCompleted(String path, Uri uri) {
+                        Log.i("ExternalStorage", "Scanned " + path + ":");
+                        Log.i("ExternalStorage", "-> uri=" + uri);
+                    }
+                });
+    }
+
+    public static Boolean checkPermissions_23(Activity activity, String[] permissions)
+    {
+        Log.d("_RAIMAGE", "checkPermissions23:==================================== ");
+        ArrayList<String> request_list = new ArrayList<String>();
+        for(String permission : permissions) {
+            boolean bshow= ActivityCompat.shouldShowRequestPermissionRationale(activity,permission);
+//            boolean granted= ContextCompat.checkSelfPermission(activity,
+//                    Manifest.permission.ACCESS_FINE_LOCATION)
+//                    == PackageManager.PERMISSION_GRANTED;
+            boolean pc = PermissionChecker.checkSelfPermission(activity,permission)== PermissionChecker.PERMISSION_GRANTED;
+//            Log.d("_RAIMAGE", "checkPermissions23: "+permission+"  SHOW  "+bshow+"  granted  "+granted +","+pc);
+
+            if(!pc)
+                request_list.add(permission);
+        }
+        Log.d("_RAIMAGE", "checkPermissions23:==================================== ");
+
+
+        if(request_list.isEmpty())
+            return false;
+        ActivityCompat.requestPermissions(activity,
+                request_list.toArray(new String[0]),
+                MY_PERMISSIONS_REQUEST);
+
+
+        return true;
+
+    }
+    public static Boolean checkPermissions_24(Activity activity, String[] permissions)
+    {
+
+
+
+
+//        ArrayList<String> request_list = new ArrayList<String>();
+//        for(String permission : permissions) {
+//
+//
+////            boolean bshow=ActivityCompat.shouldShowRequestPermissionRationale(activity,permission);
+////
+////
+////            AppOpsManager appOpsManager = (AppOpsManager) activity.getSystemService(Context.APP_OPS_SERVICE);
+////            String opsName = AppOpsManager.permissionToOp(permission);
+////            if (opsName == null) {
+////                return true;
+////            }
+////            int opsMode = appOpsManager.checkOpNoThrow(opsName, Process.myUid(), activity.getPackageName());
+//////            return opsMode == AppOpsManager.MODE_ALLOWED;
+//
+//
+////            if (ContextCompat.checkSelfPermission(activity,
+////                    Manifest.permission.ACCESS_FINE_LOCATION)
+////                    != PackageManager.PERMISSION_GRANTED||opsMode != AppOpsManager.MODE_ALLOWED)
+//
+//                request_list.add(permission);
+//
+//        }
+
+//        File logfile = new File(Environment.getExternalStorageDirectory()
+//                .getPath() + "/redant/pop/" + "debug" + ".log");
+//
+//        // int mode = Application.MODE_APPEND;
+//        if (!logfile.exists())
+//        {
+//            // mode = Application.MODE_PRIVATE;
+//            try
+//            {
+//                logfile.createNewFile();
+//            }
+//            catch (IOException e)
+//            {
+//                // TODO Auto-generated catch block
+//                e.printStackTrace();
+//
+//            }
+//        }
+        if(permissions.length==0)
+            return true;
+        ActivityCompat.requestPermissions(activity,
+                permissions,
+                MY_PERMISSIONS_REQUEST);
+
+
+        return true;
+
+//
+//        if (ContextCompat.checkSelfPermission(activity,
+//                Manifest.permission.ACCESS_FINE_LOCATION)
+//                != PackageManager.PERMISSION_GRANTED)
+//        {
+//
+//
+////            if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
+////                    permission))
+////            {
+////                return false;
+////            }
+////            else
+//            {
+//                ActivityCompat.requestPermissions(activity,
+//                        new String[]{permission},
+//                        MY_PERMISSIONS_REQUEST);
+//                return true;
+//            }
+//        } else
+//        {
+//           return true;
+//        }
+//        if(true)
+//        return true;
+        // 调用Context的checkCallingOrSelfPermission来检查权限
+
+//        Activity activity1 = (Activity) activity;
+//        if(activity==null)
+//            return false;
+//        if (PackageManager.PERMISSION_GRANTED!= context.checkCallingOrSelfPermission(permission)) {
+//
+////            String[] tmp = permission.split("\\.");
+////            String permission_name = tmp[tmp.length - 1];
+////            permission_name = permission_name.replace("_"," ");
+////
+////
+////            new AlertDialog.Builder(context)
+////                    .setTitle("Warning")
+////                    .setMessage("RA Image need " + permission_name.toLowerCase() + " permission")
+////                    .setPositiveButton("OK", null)
+////                    .show();
+////
+////            return false;
+//
+//
+//             if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
+//                    permission)) {
+//
+//                Log.d("_RAIMAGE", "checkPermission: shouldShowRequestPermissionRationale TRUE   " + permission);
+//                // Show an expanation to the user *asynchronously* -- don't block
+//                // this thread waiting for the user's response! After the user
+//                // sees the explanation, try again to request the permission.
+//
+//            } else {
+//
+//                // No explanation needed, we can request the permission.
+//
+//
+//                Log.d("_RAIMAGE", "checkPermission: shouldShowRequestPermissionRationale false   "+ permission);
+//                ActivityCompat.requestPermissions(activity,
+//                        new String[]{permission},
+//                        123);
+//
+//                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
+//                // app-defined int constant. The callback method gets the
+//                // result of the request.
+//            }
+//
+//        }
+//        return true;
+    }
+
+    public static String lastPathComponent(String path){
+
+        int start=path.lastIndexOf("/");
+        int end=path.lastIndexOf(".");
+        if(start!=-1 && end!=-1){
+            return path.substring(start+1,end);
+        }else{
+            return null;
+        }
+
+    }
+
+    public static File routeBitmap(File sourceFile, String file_name)
+    {
+        /**
+         * 获取图片的旋转角度,有些系统把拍照的图片旋转了,有的没有旋转
+         */
+        int degree = RAUtil.readPictureDegree(sourceFile.getAbsolutePath());
+
+        BitmapFactory.Options opts=new BitmapFactory.Options();//获取缩略图显示到屏幕上
+        opts.inSampleSize=1;
+        Bitmap cbitmap= BitmapFactory.decodeFile(sourceFile.getAbsolutePath(),opts);
+
+        /**
+         * 把图片旋转为正的方向
+         */
+        Bitmap newbitmap = RAUtil.rotaingImageView(degree, cbitmap);
+
+        //sourceFile.get
+        String routedPath = "";
+        if(file_name==null) {
+            String path = sourceFile.getPath();
+
+            routedPath=path.replace(".jpg", "_routed.jpg");
+        }
+        else
+        {
+            String path = sourceFile.getParent();
+            routedPath = path+"/"+file_name;
+        }
+        File routedFile = new File(routedPath);
+        try {
+
+            FileOutputStream outputStream = new FileOutputStream(routedFile);
+            newbitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
+
+            outputStream.flush();
+            outputStream.close();
+
+            String filepath = sourceFile.getAbsolutePath();
+            sourceFile.delete();
+            RAUtil.updateGallery(filepath);
+//				scaleFile.renameTo(new File(path));
+            return routedFile;
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
+
+    }
+    /**
+     * 读取图片属性:旋转的角度
+     * @param path 图片绝对路径
+     * @return degree旋转的角度
+     */
+    public static int readPictureDegree(String path) {
+        int degree  = 0;
+        try {
+            ExifInterface exifInterface = new ExifInterface(path);
+            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
+            switch (orientation) {
+                case ExifInterface.ORIENTATION_ROTATE_90:
+                    degree = 90;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_180:
+                    degree = 180;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_270:
+                    degree = 270;
+                    break;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return degree;
+    }
+    /*
+     * 旋转图片
+     * @param angle
+     * @param bitmap
+     * @return Bitmap
+     */
+    public static Bitmap rotaingImageView(int angle , Bitmap bitmap) {
+        //旋转图片 动作
+        Matrix matrix = new Matrix();;
+        matrix.postRotate(angle);
+        System.out.println("angle2=" + angle);
+        // 创建新的图片
+        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
+                bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+        return resizedBitmap;
+    }
+    public static JSONObject Bundle2Json(Bundle bundle)
+    {
+        JSONObject json = new JSONObject();
+        Set<String> keys = bundle.keySet();
+        for (String key : keys) {
+            try {
+                Log.d("", "Bundle2Json: key:"+key+"  val: "+wrap(bundle.get(key)));
+                 json.put(key, wrap(bundle.get(key))); //see edit below
+//                json.put(key, JSONObject.wrap(bundle.get(key)));
+            } catch(JSONException e) {
+                //Handle exception here
+            }
+        }
+        return json;
+    }
+
+    private static Object wrap(Object o) {
+        if (o == null) {
+            return JSONObject.NULL;
+        }
+        if (o instanceof JSONArray || o instanceof JSONObject) {
+            return o;
+        }
+        if (o.equals(JSONObject.NULL)) {
+            return o;
+        }
+        try {
+            if (o instanceof Bundle)
+            {
+                return Bundle2Json((Bundle) o);
+
+            }
+            if (o instanceof Collection) {
+                return new JSONArray((Collection) o);
+            } else if (o.getClass().isArray()) {
+                return toJSONArray(o);
+            }
+            if (o instanceof Map) {
+                return new JSONObject((Map) o);
+            }
+            if (o instanceof Boolean ||
+                    o instanceof Byte ||
+                    o instanceof Character ||
+                    o instanceof Double ||
+                    o instanceof Float ||
+                    o instanceof Integer ||
+                    o instanceof Long ||
+                    o instanceof Short ||
+                    o instanceof String) {
+                return o;
+            }
+            if (o.getClass().getPackage().getName().startsWith("java.")) {
+                return o.toString();
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    private static JSONArray toJSONArray(Object array) throws JSONException {
+        JSONArray result = new JSONArray();
+        if (!array.getClass().isArray()) {
+            throw new JSONException("Not a primitive array: " + array.getClass());
+        }
+        final int length = Array.getLength(array);
+        for (int i = 0; i < length; ++i) {
+            result.put(wrap(Array.get(array, i)));
+        }
+        return result;
+    }
+    public static Bundle Json2Bundle(JSONObject s) {
+        Bundle bundle = new Bundle();
+
+        for (Iterator<String> it = s.keys(); it.hasNext(); ) {
+            String key = it.next();
+            try {
+                Object o = s.get(key);
+
+
+
+                if (o == null) {
+                    continue;
+                }
+                else if ( o instanceof JSONObject) {
+                    bundle.putBundle(key,Json2Bundle((JSONObject) o));
+                }
+                else if(o instanceof JSONArray)
+                {
+                    throw new JSONException("Json2Bundle does not support Json array: " + o.getClass());// bundle.putarr
+                }
+                else if (o.equals(JSONObject.NULL)) {
+                    continue;
+                }
+                else if (o instanceof Boolean)
+                {
+                    bundle.putBoolean(key,((Boolean) o).booleanValue());
+                }
+                else if(o instanceof Byte)
+                {
+                    bundle.putByte(key, ((Byte) o).byteValue());
+                }
+                else if(o instanceof Character)
+                {
+                    bundle.putChar(key, ((Character) o).charValue());
+                }
+                else if(o instanceof Double)
+                {
+                    bundle.putDouble(key, ((Double) o).doubleValue());
+                }
+                else if(o instanceof Float)
+                {
+                    bundle.putFloat(key, ((Float) o).floatValue());
+                }
+                else if(o instanceof Integer)
+                {
+                    bundle.putInt(key, ((Integer) o).intValue());
+                }
+                else if(o instanceof Long)
+                {
+                    bundle.putLong(key, ((Long) o).longValue());
+                }
+                else if(o instanceof Short)
+                {
+                    bundle.putShort(key, ((Short) o).shortValue());
+                }
+                else if(o instanceof String)
+                {
+                    bundle.putString(key, o.toString());
+                }
+
+//                ArrayList<Parcelable> a = new ArrayList<>();
+//                a.add("");
+//                a.add(1);
+//                bundle.putParcelableArrayList("arr", a);
+
+
+
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+        }
+        return bundle;
+    }
+    public static Bundle Json2Bundle1(JSONObject s) {
+        Bundle bundle = new Bundle();
+
+        for (Iterator<String> it = s.keys(); it.hasNext(); ) {
+            String key = it.next();
+            JSONArray arr = s.optJSONArray(key);
+            Double num = s.optDouble(key);
+//            Integer i = s.optInt(key);
+            String str = s.optString(key);
+            JSONObject obj = s.optJSONObject(key);
+            if (arr != null && arr.length() <= 0)
+            {
+                bundle.putStringArray(key, new String[]{});
+            }
+
+            else if (arr != null && !Double.isNaN(arr.optDouble(0))) {
+                double[] newarr = new double[arr.length()];
+                for (int i=0; i<arr.length(); i++)
+                    newarr[i] = arr.optDouble(i);
+                bundle.putDoubleArray(key, newarr);
+            }
+
+            else if (arr != null && arr.optString(0) != null) {
+                String[] newarr = new String[arr.length()];
+                for (int i=0; i<arr.length(); i++)
+                    newarr[i] = arr.optString(i);
+                bundle.putStringArray(key, newarr);
+            }
+
+
+            else if (obj != null)
+            {
+                Bundle b=Json2Bundle(obj);
+                bundle.putBundle(key, b);
+            }
+
+            else if (!num.isNaN())
+                bundle.putDouble(key, num);
+
+            else if (str != null)
+                bundle.putString(key, str);
+
+            else
+                System.err.println("unable to transform json to bundle " + key);
+        }
+        return bundle;
+    }
+//    public static Bundle Json2Bundle(JSONObject jsonObject) throws JSONException {
+//        Bundle bundle = new Bundle();
+//        Iterator iter = jsonObject.keys();
+//        while(iter.hasNext()){
+//            String key = (String)iter.next();
+//            String value = jsonObject.getString(key);
+//            bundle.putString(key,value);
+//        }
+//        return bundle;
+//    }
+
+    public static JSONArray jsonObject2KVArray(JSONObject object, boolean trim) {
+
+        if (object == null) {
+            return null;
+        }
+
+        try {
+            JSONArray ret = new JSONArray();
+            Iterator<String> iterator = object.keys();
+
+            while (iterator.hasNext()) {
+
+                JSONObject kv = new JSONObject();
+
+                String key = iterator.next();
+                Object value = object.get(key);
+
+                kv.put("key",key);
+                if (trim) {
+                    if (value == null) {
+                        continue;
+                    }
+                    String val = value.toString();
+                    if (val.length() == 0) {
+                        continue;
+                    }
+                }
+
+                kv.put("value",value);
+                ret.put(kv);
+
+            }
+
+            return ret;
+
+        } catch (JSONException e) {
+            e.printStackTrace();
+            return null;
+        }
+
+    }
+
+    public static String getApplicationName(Context context) {
+
+        PackageManager packageManager = null;
+        ApplicationInfo applicationInfo = null;
+        try {
+            packageManager = context.getPackageManager();
+            applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            applicationInfo = null;
+        }
+        String applicationName = (String) packageManager.getApplicationLabel(applicationInfo);
+        return applicationName;
+    }
+
+    public static String SDCardRoot() {
+        return Environment.getExternalStorageDirectory()+File.separator;
+    }
+
+    public static File createSDDir(String dir)throws IOException{
+        File dirFile=new File(SDCardRoot()+dir);
+        dirFile.mkdir();//mkdir()只能创建一层文件目录,mkdirs()可以创建多层文件目录
+        return dirFile;
+    }
+
+    //在SD卡上创建文件
+    public static File createFileInSDCard(String fileName,String dir) throws IOException {
+        File file=new File(SDCardRoot()+dir+File.separator+fileName);
+        file.createNewFile();
+        return file;
+    }
+
+    public static boolean isFileExist(String fileName,String dir){
+        File file=new File(SDCardRoot()+dir+File.separator+fileName);
+        return file.exists();
+    }
+
+    //将一个InoutStream里面的数据写入到SD卡中
+    public static File write2SDFromInput(String fileName,String dir,InputStream input){
+        File file=null;
+        OutputStream output=null;
+        try {
+            //创建目录
+            createSDDir(dir);
+            //创建文件
+            file=createFileInSDCard(fileName,dir);
+            //写数据流
+            output=new FileOutputStream(file);
+            byte buffer[]=new byte[4*1024];//每次存4K
+            int temp;
+            //写入数据
+            while((temp=input.read(buffer))!=-1){
+                output.write(buffer,0,temp);
+            }
+            output.flush();
+        } catch (Exception e) {
+            System.out.println("写数据异常:"+e);
+        }
+        finally{
+            try {
+                output.close();
+            } catch (Exception e2) {
+                System.out.println(e2);
+            }
+        }
+        return file;
+    }
+
+    public static String getMimeType(String filePath) {
+        String ext = MimeTypeMap.getFileExtensionFromUrl(filePath);
+        String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
+        if (mime == null || mime.isEmpty()) {
+            mime = "text/plain";
+        }
+        return mime;
+    }
+
+}

+ 18 - 0
Apex Mobile/app/src/main/res/drawable/black_border.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!--背景色-->
+    <solid android:color="#FFFFFF" />
+
+    <!--边框颜色-->
+    <stroke
+        android:width="0.01dp"
+        android:color="#000000" />
+
+    <padding
+        android:bottom="1dp"
+        android:left="1dp"
+        android:right="1dp"
+        android:top="1dp" />
+
+</shape>

+ 45 - 0
Apex Mobile/app/src/main/res/drawable/result_black_border.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--<selector xmlns:android="http://schemas.android.com/apk/res/android">-->
+
+    <!--<shape xmlns:android="http://schemas.android.com/apk/res/android" >-->
+        <!--&lt;!&ndash;&lt;!&ndash; 实心 &ndash;&gt;&ndash;&gt;-->
+        <!--&lt;!&ndash;背景色&ndash;&gt;-->
+        <!--<solid android:color="#FFFFFF" />-->
+
+        <!--&lt;!&ndash;边框颜色&ndash;&gt;-->
+        <!--<stroke-->
+            <!--android:width="1dp"-->
+            <!--android:color="#000000" />-->
+
+        <!--<padding-->
+            <!--android:bottom="1dp"-->
+            <!--android:left="1dp"-->
+            <!--android:right="1dp"-->
+            <!--android:top="1dp" />-->
+    <!--</shape>-->
+
+<!--</selector>-->
+
+<!--<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >-->
+    <!--&lt;!&ndash; This is the main color &ndash;&gt;-->
+    <!--<item>-->
+        <!--<shape>-->
+            <!--&lt;!&ndash;    边框颜色 &ndash;&gt;-->
+            <!--<solid android:color="#000000"/>-->
+        <!--</shape>-->
+    <!--</item>-->
+    <!--&lt;!&ndash; 给View设置1dp的边框 &ndash;&gt;-->
+    <!--<item android:top="1dp" android:left="1dp" android:right="1dp" android:bottom="1dp">-->
+        <!--<shape>-->
+            <!--&lt;!&ndash;     View填充颜色 &ndash;&gt;-->
+            <!--<solid android:color="#ffffff" />-->
+        <!--</shape>-->
+    <!--</item>-->
+
+<!--</layer-list>-->
+
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
+    <solid android:color="#00000000" />
+    <stroke android:width="1dip" android:color="#000000"/>
+</shape>

+ 31 - 0
Apex Mobile/app/src/main/res/layout/activity_search_result.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#ffffff"
+    tools:context="com.usai.apex.Result.SearchResultActivity">
+
+
+
+    <HorizontalScrollView
+        android:id="@+id/horizontal_scroll"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:background="#ffffff"
+        >
+
+        <ListView
+            android:id="@+id/result_table_list"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:background="#ffffff"
+            >
+
+
+        </ListView>
+    </HorizontalScrollView>
+
+
+</RelativeLayout>

+ 18 - 0
Apex Mobile/app/src/main/res/layout/result_cell.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content">
+
+
+    <TableRow
+        android:id="@+id/result_row"
+        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+        android:background="#00000000"
+        >
+
+
+    </TableRow>
+
+</RelativeLayout>