■コード
以下の記述でステータスバーを消すことができる。
[UIApplication sharedApplication].statusBarHidden = YES;
■Info.plist
もしくはInfo.plistにUIStatusBarHiddenというキーを追加し、値にYESをセットする。
以下の記述でステータスバーを消すことができる。
[UIApplication sharedApplication].statusBarHidden = YES;
もしくはInfo.plistにUIStatusBarHiddenというキーを追加し、値にYESをセットする。
以下のようにしてActivityを定義する。
package info.justoneplanet.android.sample.preference; import android.os.Bundle; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.PreferenceActivity; import android.util.Log; public class SettingActivity extends PreferenceActivity implements OnPreferenceChangeListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.setting); } /** * 設定が変更された時 */ @Override public boolean onPreferenceChange(Preference preference, Object newValue) { Log.e("preference changed - " + preference.toString(), newValue.toString()); return false; } }
驚くことに保存するロジックは書かなくて良い。以下のXMLを定義すればkeyを元にして自動的に保存される。
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="@string/group1"> <CheckBoxPreference android:key="@string/item1_key" android:title="@string/item1" android:summary="@string/item1_summary" android:summaryOn="@string/item1_summary_on" android:summaryOff="@string/item1_summary_off" android:defaultValue="true" /> </PreferenceCategory> <PreferenceCategory android:title="@string/group1"> <ListPreference android:key="@string/item2_key" android:title="@string/item2" android:summary="@string/item2_summary" android:dialogTitle="@string/item2" android:entries="@array/list_entries" android:entryValues="@array/list_entryvalues" android:selectable="true" android:enabled="true" android:positiveButtonText="OK" android:negativeButtonText="Cancel" android:defaultValue="2nd"> </ListPreference> <RingtonePreference android:key="@string/melody_key" android:title="@string/melody" android:summary="@string/melody_summary" android:showDefault="true" /> </PreferenceCategory> </PreferenceScreen>
以下のようにして通常のSharedPreferenceから読み出しできる。PreferenceManager.getDefaultSharedPreferences(this);だけが設定画面用の呼び出しである。
package info.justoneplanet.android.sample.preference; import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.TextView; public class MainActivity extends Activity { private static final int REQUEST_CODE = 200; private SharedPreferences sharedPreferences; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // sharedpreferenceの呼び出し sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); } @Override public void onResume() { super.onResume(); // 設定から戻ってきたときに反映されているように // 設定1 TextView textView1 = (TextView) findViewById(R.id.item1); textView1.setText(String.valueOf(sharedPreferences.getBoolean(getString(R.string.item1_key), true))); // 設定2 TextView textView2 = (TextView) findViewById(R.id.item2); textView2.setText(String.valueOf(sharedPreferences.getString(getString(R.string.item2_key), getString(R.string.not_set)))); // 設定3 TextView textView3 = (TextView) findViewById(R.id.item3); textView3.setText(String.valueOf(sharedPreferences.getString(getString(R.string.melody_key), getString(R.string.not_set)))); } /** * メニューボタンが押された時 */ @Override public boolean onCreateOptionsMenu(Menu menu) { boolean result = super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return result; } /** * メニューが選択された時 */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case R.id.menu_setting: Intent intent = new Intent(this, SettingActivity.class); startActivityForResult(intent, REQUEST_CODE); return true; } return false; } }
ロジックには関係しないが後でコピーする為にリソースも残しておく。
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Preference</string> <string name="menu_setting">Setting</string> <string name="not_set">Not set, yet.</string> <string name="group1">group 1</string> <string name="item1">item 1</string> <string name="item1_key">item1</string> <string name="item1_summary_on">it is on</string> <string name="item1_summary_off">it is off</string> <string name="item1_summary">summary1</string> <string name="group2">group 2</string> <string name="item2">item 2</string> <string name="item2_key">item2</string> <string name="item2_summary">summary1</string> <string name="melody">melody</string> <string name="melody_key">melody</string> <string name="melody_summary">melody</string> </resources>
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="list_entries"> <item>Item 1</item> <item>Item 2</item> <item>Item 3</item> </string-array> <string-array name="list_entryvalues"> <item>1</item> <item>2</item> <item>3</item> </string-array> </resources>
ちなみに属性値を誤って入力しなかったりするとR.javaが崩れる。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/app_name" /> <TextView android:id="@+id/item1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/app_name" /> <TextView android:id="@+id/item2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/app_name" /> <TextView android:id="@+id/item3" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/app_name" /> </LinearLayout>
めも。サンプルコードなのでアレ。
テキストを表示する場合は以下のようにする。
<TextView android:id="@+id/list_face" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="17sp" android:textColor="#333333" />
以下のようにして編集可能なテキスト領域を設置する。
<EditText android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="top" android:id="@+id/edit_text"/>
デフォルトでは水平方向でセンタリングされるのでgravityを指定し変更する。
以下のように入力補助付きのテキストエリアを生成できる。
<AutoCompleteTextView android:id="@+id/autocomp" android:layout_width="fill_parent" android:layout_height="wrap_content" android:completionThreshold="2" />
但し、これだけでは完結しない。
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > </TextView>
以下のようにして入力候補をセットする。
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.text, new String[]{"hoge", "fuga", "piyo"}); ((AutoCompleteTextView) findViewById(R.id.autocomp)).setAdapter(adapter);
画像表示用View。
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" android:id="@+id/icon" />
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:id="@+id/movie" />
以下のようにして動画ソースをセットする。
((VideoView) findViewById(R.id.movie)).setVideoPath("/data/adult.mp4");
以下のようにしてボタンを設置することができる。
<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/app_name" />
以下のようにしてクリックした時のイベントを定義する。
((Button) findViewById(R.id.button)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } });
メモ。
デフォルトのブラウザで共有を押した時の挙動と同じものが以下のコードで実現できる。
Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, "text"); startActivity(Intent.createChooser(intent, "title"));
ちなみに画像などを送ることもできる。
忘れてしまうのでメモしておく。
CREATE TABLE new_table LIKE old_table; INSERT INTO new_table SELECT * FROM old_table;
これは以下のように異なったDB間でも行うことができる。
CREATE TABLE new_table LIKE `old_database`.`old_table`; INSERT INTO new_table SELECT * FROM `old_database`.`old_table`;
StoreKitを追加する。
#import <StoreKit/StoreKit.h>
以下のようにしてSKProductsRequestDelegateとSKPaymentTransactionObserverを実装する。/p>
@interface HogeViewController : UIViewController<SKProductsRequestDelegate, SKPaymentTransactionObserver> { bool isLoading; SKProductsRequest *skProductsRequest; UIActivityIndicatorView *spinner; UIView *loaderBg; UILabel *loaderTitle; } @property bool isLoading; - (IBAction)purchaseButtonPushed:(id)sender; - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response; - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransaction:(NSArray *)transactions; - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (IBAction)purchaseButtonPushed:(id)sender { if([[UIDevice currentDevice] networkAvailable] == NO){ return; } if(self.isLoading){ return; } if([SKPaymentQueue canMakePayments]){ self.isLoading = true; // loader loaderBg = [[UIView alloc] init]; [loaderBg setFrame:CGRectMake(100, 150, 120, 85)]; [loaderBg setBackgroundColor:[UIColor blackColor]]; [loaderBg.layer setCornerRadius:13.0f]; [loaderBg setAlpha:0.7]; [self.view addSubview:loaderBg]; loaderTitle = [[UILabel alloc] init]; [loaderTitle setTextColor:[UIColor whiteColor]]; [loaderTitle setFrame:CGRectMake(0, 57, 120, 18)]; [loaderTitle setText:@"Loading..."]; [loaderTitle setTextAlignment:UITextAlignmentCenter]; [loaderTitle setBackgroundColor:[UIColor clearColor]]; [loaderTitle setAlpha:1.0]; [loaderBg addSubview:loaderTitle]; // spinner spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; [spinner setCenter:CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0)]; [self.view addSubview:spinner]; [spinner startAnimating]; [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; // 課金部分 // identiferを元にappleサーバに問い合わせます [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; skProductsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"identifer"]]; [skProductsRequest setDelegate:self]; [skProductsRequest start]; } else{// 本体の設定でアプリ内課金をOFFにしている人向けの表示 [self showAlert:@"cannot purchase" text:@"設定 > 一般 > 機能制限で[App内での購入]をONにしてください"]; } }
上述のようにアプリ内課金は本体の設定で無効にできる事を考慮する。
identiferをセットしてリクエストしたレスポンスに商品データがあれば、その商品の購入手続きに入る。
#pragma mark - #pragma mark SKProductsRequestDelegate - (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { if (response == nil) { return; } for(SKProduct *product in response.products){// productを元にした購入オブジェクトをキューに入れて購入手続きに SKPayment *payment = [SKPayment paymentWithProduct:product]; [[SKPaymentQueue defaultQueue] addPayment:payment]; } }
後述のオブザーバーの管理を忘れないようにすること。
以下のように状態はswitch文で分岐する。
#pragma mark - #pragma mark SKPaymentTransactionObserver - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransaction:(NSArray *)transactions { BOOL isFinished = YES; for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchasing:// 何らかのOKを押す前の処理 break; case SKPaymentTransactionStatePurchased:// success : 決済手続き完了処理 [queue finishTransaction:transaction]; // もし自社サーバでユーザが購入を完了したかどうかappleサーバに確認する場合は、 // transaction.transactionReceiptの値をbase64に変換して自社サーバに送信 // [transaction.transactionReceipt base64EncodedString]; isFinished = NO; break; case SKPaymentTransactionStateFailed:// 途中でキャンセルした時 isFinished = NO; [queue finishTransaction:transaction]; break; case SKPaymentTransactionStateRestored:// 通常はコールされない isFinished = NO; [queue finishTransaction:transaction]; break; default: break; } } if (isFinished == NO) {// トランザクションが何らかの完了をした時=>ローディングを消す self.isLoading = false; [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; [loaderTitle removeFromSuperview]; [loaderBg removeFromSuperview]; [spinner stopAnimating]; } } - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0){ [self paymentQueue:queue updatedTransaction:transactions]; }
dealloc部分で課金処理キューからオブザーバーをしっかり削除するようにする。
- (void)dealloc{ [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];// これ!!! [loaderBg release]; [loaderTitle release]; [skProductsRequest release]; [spinner release]; [super dealloc]; }
以下のようにしてユーザから送信されてきたレシート情報を自社サーバ側でappleに確認する。
$ch = curl_init(); $url = "https://sandbox.itunes.apple.com/verifyReceipt";// サンドボックス(テスト用) curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, '{"receipt-data" : "' . $receipt . '"}'); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_HEADER, FALSE); $result = curl_exec($ch);
xcodeからインストールしたアプリではサンドボックス経由という事が購入ダイアログで表示されます。storeからインストールしたアプリでは本番と同じダイアログになります。特にコードを変更する必要はなく自動で判定してくれるようです。
ruby -e "$(curl -fsSLk https://gist.github.com/raw/323731/install_homebrew.rb)"
基本は以下のように型つきの入れ物を用意する。
int main(int argc, char *argv[]) { int ary[5]; }
以下のように初期化も同時に行える。
int main(int argc, char *argv[]) { int ary[5] = {1, 2, 3, 4, 5}; }
上述の場合、要素数は以下のように省略して良い。
int main(int argc, char *argv[]) { int ary[] = {1, 2, 3, 4, 5}; }
配列の要素数は以下のようにして求めることができる。
int main(int argc, char *argv[]) { int ary[5] = {1, 2, 3, 4, 5}; printf("%lu", sizeof(ary) / sizeof(ary[0]));// 5 = 全体のサイズ / 1要素のサイズ }
煩雑ですな。ループは普通にfor文とか使う。
たぶん10分くらいで可能。
yum install openssl-devel wget http://nodejs.org/dist/node-v0.4.3.tar.gz tar xvzf node-v0.4.3.tar.gz cd node-v0.4.3 ./configure make make install curl http://npmjs.org/install.sh | sh npm install websocket-server npm install base64
make中は一休みできる(●´ω`●)
websocket-serverは新しいWebSocketの仕様に対応してないのでwebsocketを使用する。
yum install openssl-devel gcc-c++ make wget http://nodejs.org/dist/v0.6.8/node-v0.6.8.tar.gz tar xvzf node-v0.6.8.tar.gz cd node-v0.6.8 ./configure make make install curl http://npmjs.org/install.sh | sh npm install websocket
以下のコマンドで軽く設定してiptablesの設定ファイルを生成しておく。
system-config-firewall-tui
実際の設定は以下のコマンドを実行して行う。
vim /etc/sysconfig/iptables /etc/init.d/iptables restart vim /etc/sysconfig/ip6tables /etc/init.d/ip6tables restart
naveを使ってnodeをインストールする。
sudo yum -y install openssl-devel gcc-c++ git make git clone https://github.com/isaacs/nave.git ~/.nave ~/.nave/nave.sh install stable ~/.nave/nave.sh use stable echo "~/.nave/nave.sh use stable" >> ~/.bash_profile sudo curl https://npmjs.org/install.sh --insecure | sh npm -g install forever
どうやら環境によっては以下のエラーが出る。
../base64.cc:138: error: 'malloc' was not declared in this scope ../base64.cc:141: error: 'free' was not declared in this scope
ソースをダウンロードしbase64.ccに以下のラインを追加する。
#import <stdlib.h>
その後、以下のコマンドでインストールする。
npm install dir/
最後のスラッシュは必要なかったかもしれない。