【Android】PCからAndroid実機を操作

PCはjavaが動けばなんでもおk

JREまたはJDK1.5以上をインストールします。
パスを通します。
Android SDK1.5以上をインストールします。
パスを通します。


Android Screen Monitor - adakoda
こっから最新版をダウンロードしてきます。
zipを展開してjarをどっかに置きます。

端末を実機接続します。

http://devdevdev.hatenablog.com/entry/2014/12/03/145259
java -jar asm.jarをターミナルから実行。

エミュレーターもできるらしいが、、意味あるのか?



【Android】Android開発環境構築~Android Studio設定編

うん、Mac Book Pro Retinaだとちょっと非力になってきた。。
Xcodeで実機デバッグする分には問題ないんだけどね。。
iMac Retina 5K 27インチ買ってしまうか、21.5インチまで待つか。
23インチが欲しいんだけどな。

はい、本編。
とりあえず前回まででビルド環境はできまちた。
【Android】Android開発環境構築~Android Studio Mac編 - ふるすたっくえんじにあっぽい人の日記



今回はとりあえず快適に開発できるように。
File→Import Settings/Export Settingsで設定移行できるので、二度とやることはないかもだけどいちおメモ。


Preferences

Android Studio→Preferencesで設定画面を開きます。
▪︎IDESettings
・Appearance
Theme:Darcula
Show memory indicator:オン

・Editor→Appearance
Show line numbers:オン

・Editor→Colors & Fonts→Android Logcat
添付画像参照
f:id:devdevdev:20141207025302p:plain

・Editor→Code Folding
Imports オフ
One-line methods オフ


ADB

ターミナルを起動します。
以下のコマンドを入力
cd ~
vim .bash_profile

前回の手順通りに環境作った人は以下の通り入力
export PATH=$PATH:/Applications/Android\ Studio.app/sdk/platform-tools
違うひとはsdkあるとこ指定してにゃ。
んで、Android Studio再起動すればterminalからadbコマンド使えるようになりますぉ。


【Android】シングルトンパターン

うん、ごくごく普通にね、こんな感じで書けるんですが

package jp.hoge;

public class Hoge {
    
    private static final Hoge instance = new Hoge();
    
    private Hoge() {
    }
    
    public static Hoge getInstance() {
        return instance;
    }


Androidではあんま使えない模様。
まずActivity間でオブジェクトの共有ができないらしい。
んでもって、メモリ足んなくなると勝手にオブジェクトが解放されるらしい。
メンバ変数は通知があるけど、static変数はいつ解放されたかわかんないらしい。



まぁシングルトン自体賛否両論ですがね。
ちゃんと正しく使えば問題ないと思ってる派のぼく残念。
ってゆかSDKとか作るのにシングルトン便利なんよね。毎回インスタンス生成してもらわなくていいし。んー。
あ、ちなみにActivity間のオブジェクト共有問題についてはググったら書いてあっただけで、ほんとかは知らん。


【Android】Android開発環境構築~Android Studio Mac編

こんばんわ

環境構築編です。
えぇ、Windowsにすると言い張ってましたが、総合的に色々3時間考えた結果一旦Macに構築しますです。
ま、構築はWindowsでも大して変わらんなー


Android Studio

https://developer.android.com/sdk/installing/studio.html
↑ここにアクセスします。
Download Android Studio Beta v0.8.14
with the Android SDK for Macってやつをクリックしてダウンロードします。

zipを解凍します。
Android Studio.appをアプリケーションフォルダに移動します。


Android SDK Manager

なぜか0.8.14だとAndroid SDK Managerが入ってなかったので、追加でダウンロード。
http://developer.android.com/sdk/index.html
↑ここにアクセスします。
Download Eclpse ADT
with the Android SDK for Macってやつをクリックしてダウンロードします。

zipを解凍します。
さっき移動したAndroid Studio.appを右クリック
→パッケージの内容を表示して開いたフォルダに、解凍したzipの中にあるsdkフォルダをコピー


Android SDK Tools

Android Studioを起動して、Configure→SDK Manager
デフォルトでチェックがついてるからそのまんまInstall XX packages..をクリックして進むだけー


番外編

Android Studio起動したらjdkもっと古いのいれろやって怒られました。
詳しい情報を見るからサイトに移動して、インストールしてくだされ。

ぼくは日本語化はしないのでここで終了ー
にしても、なにこの簡単さ。ゆとりだな。

ついでに再掲

【Git】.gitignoreの書き方 - ふるすたっくえんじにあっぽい人の日記


【C#】確率抽選

はい、確率抽選。
必要にかられて作った。
ぼくが知ってるのはもっと長ったらしかった気がするけど、どうせ抽選だしこんなもんでいーべ。

    private static Random _rnd = new Random(); 
    public static T WeightedRandom<T>(this IEnumerable<T> source, Func<T, int> selector)
    {
        var totalWeight = source.Sum(x => selector(x));
        var baseWeight = _rnd.Next(0, totalWeight);
        var currentWeight = 0;
        return source.FirstOrDefault(x =>
            {
                currentWeight += selector(x);
                return currentWeight > baseWeight;
            });
    }



つかいかた!

    var dic = new Dictionary<string, int>() { { "a", 2 }, { "b", 3 }, { "c", 5 } };
    var aCount = 0;
    var bCount = 0;
    var cCount = 0;
    foreach (var i in Enumerable.Range(0, 1000000))
    {
        var item = dic.WeightedRandom(x => x.Value);
        if (item.Key == "a")
            aCount++;
        else if (item.Key == "b")
            bCount++;
        else if (item.Key == "c")
            cCount++;
    }
    Debug.WriteLine("a:" + aCount.ToString());
    Debug.WriteLine("b:" + bCount.ToString());
    Debug.WriteLine("c:" + cCount.ToString());



結果!
a:199955
b:299868
c:500177

うん、まぁだいたいあってるし?



【iOS/Objective-c】キーチェーンラッパー

まぁオープンソースとかでもいろいろあるんだけどさ。
ソース汚いし。
諸事情で使えないので作った。
俺が書いたらこんな短いのに。
同じ処理を3倍以上の行数で書いてるのがgithubとかにあって、あーぁってなる。



KeyChainWrapper.h

#import <Foundation/Foundation.h>

/*!
 @class KeyChainWrapper
 @brief キーチェーンラッパー
 */
@interface KeyChainClient : NSObject

/*!
 @brief インスタンス生成
 @param classValue Class Value Constants
 @param accessible Attribute Key Constants
 */
- (id)initWithClassValue:(CFTypeRef)classValue accessible:(CFTypeRef)accessible;

/*!
 @brief KeyChainに値を保存
 @param value 値
 @param key キー
 */
- (BOOL)saveValueToKeyChain:(id)value forKey:(NSString *)key;

/*!
 @brief KeyChainから値を削除
 @param key キー
 */
- (BOOL)removeValueFromKeyChainForKey:(NSString *)key;

/*!
 @brief KeyChainから値を取得
 @param key キー
 */
- (id)valueFromKeyChainForKey:(NSString *)key;

@end



KeyChainWrapper.m

#import "KeyChainWrapper.h"

@interface KeyChainWrapper()

@property (nonatomic) CFTypeRef classValue;
@property (nonatomic) CFTypeRef accessible;

@end

@implementation KeyChainWrapper

- (id)init {
    [self doesNotRecognizeSelector:_cmd];
    return nil;
}

- (id)initWithClassValue:(CFTypeRef)classValue accessible:(CFTypeRef)accessible {
    self = [super init];
    if (self) {
        self.classValue = classValue;
        self.accessible = accessible;
    }
    return self;
}

- (BOOL)saveValueToKeyChain:(id)value forKey:(NSString *)key {
    [self removeValueFromKeyChainForKey:key];
    NSDictionary *optional = @{ (__bridge id)kSecValueData : [NSKeyedArchiver archivedDataWithRootObject:value] };
    return SecItemAdd([self keyChainAttributesForKey:key optional:optional], NULL) == noErr;
}

- (BOOL)removeValueFromKeyChainForKey:(NSString *)key {
    return SecItemDelete([self keyChainAttributesForKey:key]) == noErr;
}

- (id)valueFromKeyChainForKey:(NSString *)key {
    NSDictionary *optional = @{
                               (__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue,
                               (__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitOne
                               };
    id value;
    CFDataRef keyData;
    if (SecItemCopyMatching([self keyChainAttributesForKey:key optional:optional], (CFTypeRef *)&keyData) == noErr) {
        @try {
            value = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
        }
        @catch (NSException *e) {
            value = nil;
        }
        @finally {}
    }
    
    if (keyData)
        CFRelease(keyData);
    
    return value;
}

- (CFDictionaryRef)keyChainAttributesForKey:(NSString *)key {
    return (__bridge CFDictionaryRef)
    [NSMutableDictionary dictionaryWithDictionary:
     @{
       (__bridge id)kSecClass : (__bridge id)self.classValue,
       (__bridge id)kSecAttrService : key,
       (__bridge id)kSecAttrAccount : key,
       (__bridge id)kSecAttrAccessible : (__bridge id)self.accessible,
       }];
}

- (CFDictionaryRef)keyChainAttributesForKey:(NSString *)key optional:(NSDictionary *)optional {
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:
                                (__bridge NSDictionary*)[self keyChainAttributesForKey:key]];
    for (NSString *optionalKey in optional.allKeys)
        [dic setObject:optional[optionalKey] forKey:optionalKey];
    
    return (__bridge CFDictionaryRef)dic;
}

@end



つかいかた!

        KeyChainWrapper *keyChainWrapper = [[KeyChainWrapper alloc] initWithClassValue:kSecClassGenericPassword accessible:kSecAttrAccessibleAfterFirstUnlock];
        [keyChainWrapper saveValueToKeyChain:@"sdjfhjsdfhksdfkds" forKey:@"key"];
        NSLog(@"%@", [keyChainWrapper valueFromKeyChainForKey:@"key"]);

        [keyChainWrapper removeValueFromKeyChainForKey:@"key"];


【iOS/Objective-c】Gzip圧縮/解凍

うん、そんだけ。
libz.dylibを追加してね。

#import <zlib.h>

+ (NSData *)compressByGzip:(NSData *)source
{
    if (source.length == 0)
        return nil;
    
    z_stream stream = [self initializedStreamBySource:source];
    if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) != Z_OK)
        return nil;
    
    NSMutableData *data = [NSMutableData dataWithCapacity:0];
    while (stream.avail_out == 0) {
        if (stream.total_out >= data.length)
            data.length += 16384;
        
        stream.next_out = data.mutableBytes + stream.total_out;
        stream.avail_out = data.length - stream.total_out;
        deflate(&stream, Z_FINISH);
    }
    deflateEnd(&stream);
    return data;
}

+ (NSData *)uncompressByGzip:(NSData *)source
{
    if (source.length == 0)
        return nil;
    
    z_stream stream = [self initializedStreamBySource:source];
    if (inflateInit2(&stream, 31) != Z_OK)
        return nil;
    
    NSMutableData *data = [NSMutableData dataWithCapacity:0];
    while (stream.avail_out == 0) {
        Bytef buffer[16384];
        stream.next_out = buffer;
        stream.avail_out = sizeof(buffer);
        inflate(&stream, Z_FINISH);
        size_t length = sizeof(buffer) - stream.avail_out;
        if (length > 0)
            [data appendBytes:buffer length:length];
    }
    inflateEnd(&stream);
    return data;
}

+ (z_stream)initializedStreamBySource:(NSData *)source {
    z_stream stream;
    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.opaque = Z_NULL;
    stream.avail_in = source.length;
    stream.next_in = (Bytef *)source.bytes;
    stream.total_out = 0;
    stream.avail_out = 0;
    return stream;
}