DialogでViewpager

DialogでViewpagerを使おうとした時のお話。

どうもAlertDialog.Builderを今まで使ってたのだが、とうとう不具合?が出てしまった。

今回DialogでViewpagerを使うために他のやつのように

// カスタムビューを設定
      LayoutInflater inflater = LayoutInflater.from(this);
      final View layout = inflater.inflate(R.layout.dialog_kusuri, (ViewGroup) findViewById(R.id.layout_root));

のDialogのlayoutからlayout.findViewById(R.id.pager)をViewPagerにしたのだが、何故かViewが見つからなくて落ちてしまう。(java.lang.IllegalStateException: Fragment does not have a view)

頑張ってpagerを見つけようとしたけどダメだった。

これは何でだろーってしらべた結果どうもAlertDialog.Builderを使ってるのが悪かったらしい

これからはDialogFragmentを使えとのこと。

ためしにDialogFragmentを使うとすんなり動いた。

PageDialog.java

package com.medicalmonitor;

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;

public class PageDialog extends DialogFragment {
    private final static String KEY_URL = "diaog_key_urls";

    public static PageDialog newInstance(String[] urls) {
        PageDialog fragment = new PageDialog();
        Bundle args = new Bundle();
        args.putStringArray(KEY_URL, urls);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.dialog_kusuri, container, false);
        String[] urls = getArguments().getStringArray(KEY_URL);

        final ViewPager viewPager = (ViewPager) view.findViewById(R.id.pager2);
        final Dialog_Fragment_pager adapter = new Dialog_Fragment_pager(getChildFragmentManager());
        viewPager.setAdapter(adapter);

        getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        getDialog().setCanceledOnTouchOutside(true);

        return view;
    }
}

Dialog_Fragment_pager.java

package com.medicalmonitor;


import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.ViewGroup;

import java.util.HashMap;
import java.util.Map;


public class Dialog_Fragment_pager
  extends FragmentPagerAdapter {//FragmentStatePagerAdapterはメモリ破棄する、保存するならこっち
   private Map<Integer, String> mFragmentTags;
    private FragmentManager mFragmentManager;
  public Dialog_Fragment_pager(FragmentManager fm) {
    super(fm);
    mFragmentManager = fm;
    mFragmentTags = new HashMap<Integer, String>();
  }
  private static final String ARG_SECTION_NUMBER = "section_number";

  @Override
  public Fragment getItem(int position) {
     return frag_dialog_pager_main.newInstance(position);
  }

  @Override
  public int getCount() {
    return 3;
  }

  @Override
  public CharSequence getPageTitle(int position) {
     
    return "Page " + position;
  }
  @Override
  public Object instantiateItem(ViewGroup container, int position) {
      Object obj = super.instantiateItem(container, position);
      if (obj instanceof Fragment) {
          // record the fragment tag here.
          Fragment f = (Fragment) obj;
          String tag = f.getTag();
          mFragmentTags.put(position, tag);
      }
      return obj;
  }

  public Fragment getFragment(int position) {
      String tag = mFragmentTags.get(position);
      if (tag == null)
          return null;
      return mFragmentManager.findFragmentByTag(tag);
  }

}

frag_dialog_pager_main.java

package com.medicalmonitor;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONObject;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class frag_dialog_pager_main extends Fragment {
   private static final String KEY_URL_STR = "urlStr";
   private static final int KANJANUM = 0;
   private static final int UNFINISHEDNUM = 1;
   private static final int FINISHEDNUM = 2;
   float juuryou=0;
   int mNum;//画面の番号1はunfinished2はfinishedとか
    final List<CustomData> localobjects = new ArrayList<CustomData>();//ローカルオブジェクト
   static frag_dialog_pager_main newInstance(int num) {
      frag_dialog_pager_main f = new frag_dialog_pager_main();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putInt("num", num);
        f.setArguments(args);

        return f;
    }

    /**
     * When creating, retrieve this instance's number from its arguments.
     */
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      mNum = getArguments() != null ? getArguments().getInt("num") : 1;
   }

   
    AlertDialog.Builder alertDlg2;
     private AlertDialog m_dlg;
      View rootView;
       ListView listView;
         //グローバル変数
          Globals globals;
         ArrayAdapter adapter;

            Fragment_pick pick = new Fragment_pick();
           // MainActivity activity = (MainActivity) getActivity();  
            MainActivity main = new MainActivity();
   @Override
   public View onCreateView(
      LayoutInflater inflater, 
      ViewGroup container, 
      Bundle savedInstanceState) {
      globals = (Globals) getActivity().getApplication();
      getActivity().getApplicationContext();

      return inflater.inflate(R.layout.frag_picking_finished, container, false);
   }
   @Override
    public void onStop() {
       //ImageCache.deleteAll(getCacheDir());
       super.onStop();
   
    }
   @Override
    public void onStart() {
       super.onStart();
       
   }
}

↑無駄な処理多いなー

ダイアログ使うときは

PageDialog newFragment = PageDialog.newInstance(null);
newFragment.show(getSupportFragmentManager(), TAG);

だけ!

まぁ動いてよかったー

MySQLで重複コードを除外するクエリ

医薬品データベースでYJコードは同じでもJANコードが違うのはほとんどである。

だからYJコードを主レコードというか重複しないレコードで他のデータベースとLEFT JOINさせたい場合にYJコードが重複してると困っちゃう。

いろいろ考えた結果↓の感じで動いた。

SELECT *
FROM `iyaku_code` AS m
WHERE `JANコード` = (
  SELECT MAX(`JANコード`)
  FROM `iyaku_code` AS s
  WHERE m.`個別医薬品コード` = s.`個別医薬品コード`
);

Showing rows 0 – 24 (20379 total, Query took 0.0542 seconds.)

パフォーマンスもまぁまぁ良かったのでこれを使うことにしよう

MySQLの効率化

いま在庫量のデータベースをいじってる。

固定の医薬品コードとは違いこっちはひたすらデータが積み上がっていくデータベースになる。

だからこれは最初の段階でしっかり設計をしないといけない。

とりあえず現在の在庫のSQLクエリを作ってみた。

 

2つのデータベースを結合して、合計をさせてやった。

 Showing rows 0 – 24 (32 total, Query took 0.0697 seconds.)

SELECT `YJコード`,SUM( `合計` ) FROM (
(SELECT `YJコード`,-SUM( `使用数` ) as 合計 FROM `picking_finished` GROUP BY `YJコード`)
UNION
(SELECT `YJコード`,SUM( `入出数` ) as 合計 FROM `inventory_control` GROUP BY `YJコード`)
)as tmp
GROUP BY YJコード

うんまぁまぁ早い。

しかしここからYJコードからデータをとってきて引っ付けてあーだーこーだしなとイケない。

Accessさんならクエリをクエリ出来て簡単だったけどMySQLはなんかスパゲッティコードになりそうで怖い。

まぁ一つづつ作っていこう。

医薬品のコード

医薬品のコードは別名たくさんある。

困ったものである。

例えば→ 個別医薬品コード=YJコード=販売名コード

ちなみにこの度医薬品コードのデータベースの大幅な改善を行った。

薬価や、薬効、ジェネリックの有無とかに対応さした。

しかし基礎のデータベースを作ったのはもう6ヶ月前。すっかりコードの変換処理とかの仕方は忘れてる。かすかな記憶でなんか今回みたいにデータベースが変更になっても動くようなシステムにしようとは思ってた気がするが全然覚えてない。

試しにCSVでUFT8にしてMySQLに新データを突っ込んだ(大量データでmy.iniのmax_allowed_packet を64Mぐらいにしないと動かなかった)

するとそのまま動いてくれた。

やっぱり最初の設計って大事だと思った瞬間だった。

Activityのローカル変数の保存について

自分のActivityをintentでほかのActivityに渡して再び戻った時にそのActivityが生きてる保証は全くない。

今開発のアプリではglobal関数に結構大事なもの(JSONとか)を保存さしてるのでActivityに戻った時に返り値がnullになってることがしばしばある(Acrobatとかメモリを食うものだとほぼ死ぬ)

なので戻った時にどうしても必要なのはonSaveInstanceStateで保存させるのだけどJSONはどうやって保存させようとなったらStackOverFlowにあったからメモ代わりにおいとく

//保存
if(globals.StockJSON!=null) outState.putString("StockJSON", globals.StockJSON.toString());
try {//JSON READ
    String jsonString = mSavedInstanceState.getString("StockJSON");
    globals.StockJSON = new JSONObject(jsonString);
} catch (JSONException e) {
    e.printStackTrace();
}catch (Exception e) {
    e.printStackTrace();
}

まぁいつもながら効率は考えてない。

しかしまぁAndroid Studioも慣れてきたといえまだまだ知らない事ばかりだ。

Gradleとか全然わからない。

郵便の問題

普段会社というか事務所というか登記されている場所にいないため郵便物が届いたときに困ってしまう。

考えた結果スマートフォンを使ってピンポンの音声に反応して来客モニターの写真を撮ってメールを送信するようなシステムを構築することにした。

auroraってアプリがソースを公開してたからそれをちょこちょこいじって2,3時間ぐらいで完成した。ちゃんと動作することを祈ろう。

これならヤマトさんが来た事が分かるから次の日に事務所に行けば郵送物を受け取れる。

これで1週間おきに事務所に行く手間が省けそうだ。

fragmentの回転時の処理

fragmentで回転させると当然activityが初期化されるけど、fragmentでインスタンスを保存してonCreateで復元させるときなぜかnullpointさんがでた。

onCreateでgetActivityはできないようだ。

仕方ないのでonCreateでBundleに保存さしてonStartで復元させるというやり方にした。

たぶんスマートではないけど動いたのでいいとする。

Bundle mSavedInstanceState;
@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Log.d("Lifecycle", "onSaveInstanceState()");

    //インスタンスの保存

    outState.putString("kusuriInfo", kusuriInfo.getText().toString());
}

@Override
 public void onStart() {
 super.onStart();
if(mSavedInstanceState!=null){//回転時の復元処理
    String value = mSavedInstanceState.getString("kusuriInfo");
    kusuriInfo.setText(value);

}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //ここだけだとnullpointなるからonstartで復元させる
    mSavedInstanceState=savedInstanceState;

}

GalaxyJのバグ

現在在庫管理システムを絶賛製作中だけど、機種によってUSBバーコードリーダの挙動がことなるから困ってしまう。GalaxyJのUsbManagerがnullを返す問題はSamsungにバグレポートを送るか悩み中。

バーコードリーダが接続されてるかのclassだけどこれでいいものだろうか

boolean USBexist=false;
boolean exist=false;
      boolean returnExist=false;
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
   HashMap<String, UsbDevice> map=manager.getDeviceList();
   Iterator<UsbDevice> it = map.values().iterator();
   while(it.hasNext()) {
       UsbDevice device = it.next();
          USBexist=true;
          returnExist=true;
       Log.d("USB", "NAME =" + device.getDeviceName());
       // use device info
      //if(showMessage)Toast.makeText(getApplicationContext(), "USBが接続されました。", Toast.LENGTH_SHORT).show();
     }

      if(newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
          exist=true;
          returnExist=true;
          //if(showMessage)Toast.makeText(getApplicationContext(), "バーコードスキャナーが接続されました。", Toast.LENGTH_SHORT).show();
          //((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).showInputMethodPicker();
          //Toast.makeText(this, "Barcode Scanner detected. Please turn OFF Hardware/Physical keyboard to enable softkeyboard to function.", Toast.LENGTH_LONG).show();
      }