【xcode】AppIconにiPadのエリアがなかった時の対応

またたいした話じゃないけど、アプリの開発をひととおり行ってアプリのアイコンを設定しようとしたらiPad用のエリアがなかった。

iPhoneのみ
f:id:yoppy0066:20170207131426p:plain

iPhoneiPad両方あり
f:id:yoppy0066:20170207131455p:plain

理由はプロジェクトを作った時にDevicesをiPhoneを選択して作ったから。
あとからUniversalに変更したのでなかったので手動で追加した。

Assets.xcassetsをFinderで開くとAppIcon.appiconsetフォルダがあってこの中にContents.jsonがあるのでそれを編集。
iPhoneの設定の下にiPad用の設定を追加すればいけた

Contents.jsonに以下を追加

Contents.jsonに以下を追加

    {
        "idiom" : "ipad",
        "size" : "20x20",
        "scale" : "1x"
    },
{
    "idiom" : "ipad",
    "size" : "20x20",
    "scale" : "2x"
},
{
    "idiom" : "ipad",
    "size" : "29x29",
    "scale" : "1x"
},
{
    "idiom" : "ipad",
    "size" : "29x29",
    "scale" : "2x"
},
{
    "idiom" : "ipad",
    "size" : "40x40",
    "scale" : "1x"
},
{
    "idiom" : "ipad",
    "size" : "40x40",
    "scale" : "1x"
},
{
    "idiom" : "ipad",
    "size" : "40x40",
    "scale" : "2x"
},
{
    "idiom" : "ipad",
    "size" : "76x76",
    "scale" : "1x"
},
{
    "idiom" : "ipad",
    "size" : "76x76",
    "scale" : "2x"
},
{
    "idiom" : "ipad",
    "size" : "83.5x83.5",
    "scale" : "2x"
}

以上です

sftpをプロキシ(squid)または踏み台(ポートフォワーディング)経由で使用できるようにする

はじめに

やりたかったことはタイトル通りなのですが。

登場人物は以下
・作業用PC
・中継サーバー(踏み台 or プロキシ)
・開発サーバー

今回は中継サーバーと開発サーバーはcentos6.5で、作業PCはMacで確認。

アクセス制限は以下
・開発サーバーへのSSHでのアクセスは中継サーバーからしか接続できない。
・中継サーバーへは作業PCから接続できる。

作業するのがプログラマ以外なのでFTPクライアントソフトとかで接続できるようにしたい。というのがやりたかったことです。

調べてみて簡単に実装できそうな方法が2つ。
SSHポートフォワーディングを使う
・中継サーバーをプロキシサーバーにする
squidをいれてプロキシサーバーとする。作業者は中継サーバをプロキシに設定する形

これから先、サーバー名は以下とする
中継サーバー = relay
開発サーバー = dev

SSHポートフォワーディングを使う方法

ポートフォワーディング

$ ssh -N -L 2022:devのIP:devのポート relayのユーザ名@relayのIP
# Ctrl + cで終了
# 2022は適当なポート番号(作業用PCで空いてる番号)

SFTPで接続

$ sftp -oPort=2022 devのユーザ名@localhost

SFTP接続はターミナルから接続する例なのでコマンドだが、FileZilla等のFTPソフトを使ってる場合も上記の情報を設定すれば接続できる。

中継サーバーをプロキシサーバーにする

こっちの方がsquidを入れる必要があるので少し手間。
あと、SSHポートをプロキシとして解放するのでIP制限等をしない場合は、SSHのポート番号を変更した方がよさそう。今回は60022とかで話を進める。開発サーバー(接続先)のsshd_configでsshのポート番号を変更できるのでこちらは設定済であるとします。

squidのセットアップ

squidのインストール

$ yum install -y squid

/etc/squid/squid.confの編集

以下の項目をコメントアウト
#http_access deny all

http://qiita.com/pcnikki/items/404329f9ad9cb6e235d4
ここら辺とか参考にして最低限の設定はしておいた方がよさそう。
今回はsquidの公開ポートはデフォルトの3128で。

Basic認証設定

/etc/squid/squid.confの編集

# 以下を追加
auth_param basic program /usr/lib64/squid/ncsa_auth /etc/squid/passwd
acl password proxy_auth REQUIRED
http_access allow password

Basic認証用のユーザーを追加(更新、削除)

$ htpasswd -c /etc/squid/passwd user # 作成
$ htpasswd -b /etc/squid/passwd user pass # 追加
$ htpasswd -D /etc/squid/passwd user # 削除
SSHのポート番号をsquidで使えるようにする

/etc/squid/squid.confの編集

・・・
acl SSL_ports port 443
acl SSH_ports port 60022 # ★ココを追加
acl Safe_ports port 60022 # ★ココを追加
・・・

# ★ ココを書き換えてSSHもConnectメソッドを使えるように
# http_access deny CONNECT !SSL_ports
http_access deny CONNECT !SSL_ports !SSH_ports
・・・

squid起動

$ service squid start
SFTPでつなぐ
$ sftp -o "ProxyCommand connect -H basic認証のユーザ名@relayのIP:3128 %h %p" devのユーザー名@devのIP

とりあえず動いた。以上です

参考url
SquidでSSHをプロキシする設定。 - それマグで!
5分で作るPROXYサーバー - Qiita

sftpコマンドでプロキシ経由で接続する方法メモ

squidでたてたプロキシサーバー経由でsftp使うときのメモ

$ sftp -o "ProxyCommand connect -H プロキシのIP:プロキシのポート %h %p" sftpユーザー名@sftpサーバーのIP

以上です

【squid】プロキシにパスワード認証を設定する

次回のために作業メモ
squidのプロキシにパスワード認証(Basic認証)追加

ユーザー作成

# 新規作成
$ htpasswd -c /etc/squid/passwd user

# ユーザー追加
$ htpasswd -b /etc/squid/passwd user2 pass

# ユーザー削除
$ htpasswd -D /etc/squid/passwd user2

/etc/squid/squid.conf

# 追加
auth_param basic program /usr/lib64/squid/ncsa_auth /etc/squid/passwd
acl password proxy_auth REQUIRED
http_access allow password

再起動で設定反映

$ service squid restart

以上です

【android】Fragment上のListViewに置かれたボタンのonClickを処理する

はじめに

今回やりたかったのは、ListViewのセル上に削除ボタンとかをおいてクリックされたらListViewから削除するようなこと。
ListViewを作るのがActivityとFragmentとでやり方が違うみたい。

Activityの場合は以下みたいな形でボタンのイベントが取得できる。

xml

<Button ・・・
  android:id="@+id/myButton"
  android:onClick="myFunc"
 />

Adapter

public View getView(final int position, View convertView, ViewGroup parent) {
    ・・・
    Button myButton = (Button)convertView.findViewById(R.id.myButton);
    myButton.setTag(position);
    ・・・
}

Activity

public void myFunc(View view) {
    // ListView上のボタンがおされたら呼ばれる
    // view.getTag()でどの行が押されたかわかる
}

けど、Fragmentを使ってる場合はFragmentを呼び出してるActivityで実装されているmyFuncが呼ばれるためやりたいこととは違った。

Fragmentの場合

xmlのButtonにonClick属性はセットしない。
やり方わからなかったので、アダプターにインターフェースを定義して呼び出し元(Fragment)にメソッドを実装させる形で実装してみた。

xml

<Button ・・・
  android:id="@+id/myButton"
 />

Adapter

public class MyAdapter extends ArrayAdapter<MyData> {

    private MyAdapterListener listener;

    public interface MyAdapterListener {
        void myFunc(Object position);
    }

    public void setListener(MyAdapterListener listener) {
        this.listener = listener;
    }

    ・・・

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ・・・
        Button myButton = (Button)convertView.findViewById(R.id.myButton);
        myButton.setTag(position);
        myButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.myFunc(v.getTag());
            }
        });
        return convertView;
    }
}

Fragment

public class MyFragment extends Fragment implements MyAdapter.MyAdapterListener {
    ・・・
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ・・・

        // アダプターで用意したsetListnerメソッドで関連づける
        mAdapter = new MyAdapter(getContext(), 0, ・・・);
        mAdapter.setListener(this);
    }

    public void myFunc(Object position) {
        // 呼ばれた!!
    }
}

もっといいやり方ありそうだけど。。以上です

【android】ListViewひな型

試したりするときにとりあえずListView作ることが多いのでコピペ用にメモ

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private ArrayList<Item> mItems;
    private ItemAdapter mAdapter;
    private ListView mListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mItems = new ArrayList<>();
        mItems.clear();
        mAdapter = new ItemAdapter(this, 0, mItems);

        ListView listView = (ListView)findViewById(R.id.list_view);
        listView.setAdapter(mAdapter);

        setData();
    }

    private void setData() {
        for (int i = 0; i < 10; i++) {
            Item item = new Item();
            item.setTitle("タイトル " + String.valueOf(i+1));
            mItems.add(item);
        }
    }
}

class Item {
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

class ItemAdapter extends ArrayAdapter<Item> {
    private LayoutInflater layoutInflater;

    public ItemAdapter(Context c, int id, ArrayList<Item> data) {
        super(c, id, data);
        this.layoutInflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.list_item,parent,false);
        }
        Item data = getItem(position);

        TextView title = (TextView)convertView.findViewById(R.id.title);
        title.setText(data.getTitle());

        return convertView;
    }
}

main_activity.xml

<?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:id="@+id/activity_main"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingBottom="@dimen/activity_vertical_margin"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin">

  <ListView
      android:id="@+id/list_view"
      android:layout_width="match_parent"
      android:layout_height="match_parent"></ListView>
</RelativeLayout>

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical" android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="5sp"
        android:paddingTop="25sp"
        android:paddingBottom="15sp"
        android:textSize="24sp"/>
</LinearLayout>                                                                                                                                                                                                    
||<