Flaskでpostされたjsonを受け取る
Flaskのrequestでデータを受け取るには
- request.data
- request.form
- request.json
等がある。
それぞれ、Content-Typeで受け取り方が切り替わるらしい。
request.jsonはContent-Typeをapplication/jsonに設定していれば
自動的にオブジェクトへパースしてデータを返してくれる。
POSTするデータはJSON.stringifyしてないと400エラーが出て怒られる。
なので、Javascript側ではajaxの設定を下記のようにする。
- Content-Typeをapplication/jsonに
- データはJSON.stringifyで文字列に
例)
$.ajax( { url:'/api/test', type:'POST', data:JSON.stringify(data), dataType: 'json', contentType: 'application/json' }) .done(function(data, textStatus, jqXHR ){ console.log("done"); console.log(data); }) .fail(function(jqXHR, textStatus, errorThrown){ console.log("failed"); });;
Python側では念の為にヘッダーのチェックを行う。
@app.route('/api/test', methods=['POST']) def face_info(): if request.headers['Content-Type'] != 'application/json': print(request.headers['Content-Type']) return flask.jsonify(res='error'), 400 print request.json return flask.jsonify(res='ok')
Android string.xmlの分割と多言語化
多言語化はフォルダ名をvalues-XX(XXは国コード"ja"とか"cn"とか)にして、同じようなリソースを置くことでAndroidが勝手に入れ替えてくれる。
また、言語ファイルをよく記述しているres/values/string.xmlは、他の名前で定義しても利用可能。
なので、string.xmlが大きくなりそうになったらファイルを分割するとスッキリする。
例えば、string_test.xml内で"hello"という文字列を定義すると、R.string.helloでアクセスできるようになる。
下記はサンプル。
res/values/string_test.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">hello!</string> </resources>
res/values-ja/string_test.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">こんにちわ!</string> </resources>
利用例)
Log.d("debug", getString(R.string.hello));
これで言語が日本語の際は"こんにちは!"、それ以外は"hello"と出力される。
AndroidのLogCat出力用テンプレート(メソッド名とか行番号とか表示したいよ!)
メソッド名とか行番号とかLogCatに出力したいなーと、ぐぐってみたらここを読んで、おぉー(・・)と思い作ってみました。
Eclipseのテンプレ設定にすると非常に便利かも!
下記コード。
private static final boolean ENABLE_LOG = true; private static void logd(String msg) { if(ENABLE_LOG) { Log.d(getTag(), msg); } } private static final String getTag() { StackTraceElement ste = Thread.currentThread().getStackTrace()[4]; String className = ste.getClassName(); className = className.substring(className.lastIndexOf(".") + 1); String methodName = ste.getMethodName(); int lineNum = ste.getLineNumber(); return className + "." + methodName + ":" + lineNum; }
logd()を使うと、
HogeActivity.foobar:11
のようなタグが出力されます。
これをEclipseの設定で下記のようにコピペすると、Classを作成した時にテンプレ付きで作成されます。
テンプレにすることの難点は、すべてのクラスにコレがくっついてくることです(´・ω・`)
まぁ消せばOKなんですけどね。
やっぱりコピペツールに登録しようかなー
なにかいい方法があれば教えて下さい
iOSで通信する際のUser-Agentを組み立てる
こういうフォーマットのUAがつくりたい!
<アプリ名>/
例)
MyApp/1.0 (iPhone5,2; 6.0; iOS; ja)
//format: MyApp/1.0 (iPhone5,2; 6.0; iOS; ja) - (NSString*)buildUserAgent { // モデル名取得 NSString *modelname = [self platformName]; // osのバージョン取得 float iOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; // 言語設定取得 NSArray *langs = [NSLocale preferredLanguages]; //取得した配列から先頭の文字列を取得(先頭が現在の設定言語) NSString *currentLanguage = [langs objectAtIndex:0]; NSString* userAgent = [NSString stringWithFormat:@"MyApp/1.0 (%@; %0.2f; iOS; %@)", modelname, iOSVersion, currentLanguage]; return userAgent; } // デバイスの情報を返す - (NSString *)platformName { size_t size; sysctlbyname("hw.machine", NULL, &size, NULL, 0); char *machine = malloc(size); sysctlbyname("hw.machine", machine, &size, NULL, 0); NSString *platformName = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding]; free(machine); return platformName; }
ちょっと決め打ち多いね^^;
あとはこの文字列をNSURLConnectionなりAFHTTPClientなりにセットしよう!
Macで"dyld: Library not loaded:"が出たら。。。
dyld: Library not loaded: lib/..... Referenced from: /Users/......./hoge Reason: image not found
これを.zshrcに書いとこう。
export DYLD_LIBRARY_PATH=/path/to/lib:$DYLD_LIBRARY_PATH
これで動くはず。
Xcodeでビルドした時の”duplicate symbols”エラーを回避する
FacebookSDKやAWSiOSSDKなど、いろんなライブラリをブチ込みまくると
ld: - duplicate symbols for architecture ---
と言うエラーがよく出る。
重複して使われているライブラリ(SBJsonとか)が出るとこのようなエラーがでてしまう。
くっそ!
そしてググりまくって回避方法を見つけました(`・ω・´)
今回はFacebookとAWSの.frameworkの衝突を回避する例を紹介します。
まず普通にビルドすると、
duplicate symbol _OBJC_CLASS_$_SBJsonParser in: .../Build/Products/Debug-iphoneos/libFacebook SDK.a(SBJsonParser.o) . . . . . XcodeWorkspace/aws-ios-sdk-1.4.3/AWSiOSSDK.framework/AWSiOSSDK(SBJsonWriter.o) ld: 6 duplicate symbols for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)
お、おぅ、となります。
○SBJsonParser.o
○SBJsonWriter.o
これらがFacebookSDKとAWSのSDKで使われてるから怒られる。たぶん。
なので、AWSiOSSDKの方からこれらを消してあげます。
まず下記コマンドで、どのアーキテクチャ用になってるかチェック。
$lipo -info AWSiOSSDK Architectures in the fat file: AWSiOSSDK are: armv7 (cputype (12) cpusubtype (11)) i386
armv7とi386のアーキテクチャ用にビルドされてるそうです。
下記コマンドで分解。
$lipo -thin armv7 AWSiOSSDK -output AWSiOSSDK_armv7 $lipo -thin i386 AWSiOSSDK -output AWSiOSSDK_i386
.oファイル検索
$ar -t AWSiOSSDK_armv7|grep SBJson SBJsonParser.o SBJsonStreamParser.o SBJsonStreamParserAccumulator.o SBJsonStreamParserAdapter.o SBJsonStreamParserState.o SBJsonStreamWriter.o SBJsonStreamWriterAccumulator.o SBJsonStreamWriterState.o SBJsonTokeniser.o SBJsonUTF8Stream.o SBJsonWriter.o
あったあった。
目的のファイル削除。
ar -dv AWSiOSSDK_armv7 SBJsonParser.o SBJsonWriter.o ar -dv AWSiOSSDK_i386 SBJsonParser.o SBJsonWriter.o
合体!
lipo -create AWSiOSSDK_armv7 AWSiOSSDK_i386 -output AWSiOSSDK
これでビルドすると。。。。
Building...... (´・ω・`)
Succeed!いぇーす!おめでとう!
*追記
armv7sのライブラリ抽出は下記で可能。
xcrun -sdk iphoneos lipo -thin armv7s AWSiOSSDK -output AWSiOSSDK_armv7s
AndroidでBitmap画像を保存
よく忘れるのでメモ書き。
ギャラリーに"/MyPhoto/"フォルダができてその中に保存されます。
最後のContentResolverの部分で保存したファイルパスを登録しておかないと、
デバイスを再起動するまでギャラリーが更新されない罠が準備されてます。
public void saveBitmap(Bitmap saveImage) throws IOException { final String SAVE_DIR = "/MyPhoto/"; File file = new File(Environment.getExternalStorageDirectory().getPath() + SAVE_DIR); try{ if(!file.exists()){ file.mkdir(); } }catch(SecurityException e){ e.printStackTrace(); throw e; } Date mDate = new Date(); SimpleDateFormat fileNameDate = new SimpleDateFormat("yyyyMMdd_HHmmss"); String fileName = fileNameDate.format(mDate) + ".jpg"; String AttachName = file.getAbsolutePath() + "/" + fileName; try { FileOutputStream out = new FileOutputStream(AttachName); saveImage.compress(CompressFormat.JPEG, 100, out); out.flush(); out.close(); } catch(IOException e) { e.printStackTrace(); throw e; } // save index ContentValues values = new ContentValues(); ContentResolver contentResolver = getContentResolver(); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put(Images.Media.TITLE, fileName); values.put("_data", AttachName); contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); }