Archive for the ‘Dev’ Category

Foregroundにする(Android)

2012年6月23日

一度BackgroundになってしまったアプリをForegroundにするには

1.Activity の launchMode を “singleTask” に設定する

AndroidManufest.xml の <activity> に以下を追加
            android:launchMode="singleTask" 

2.startActivityで、そのActivityを呼び出す
       Intent intent = new Intent(getApplicationContext(), XXXXActivity.class);
       startActivity(intent);

Ringtone Picker を使う(Android)

2012年6月23日

Ringtoneを選択する画面(Ringtone Picker)を表示する

    	Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
    	startActivityForResult(intent, 0);

選択されたRingtoneのUriを取得する

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 0) {
            if (resultCode == RESULT_OK) {
            	//If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap object in the extra field. 
            	Bundle b = data.getExtras();
                Set keys = b.keySet();
                Iterator k = keys.iterator();
                while(k.hasNext()) {
                    String key = k.next();
                    if(key.equals(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)) {
                        Object o = b.get(key);                		
                        mRtUri = (Uri)o;
                        if(mRtUri != null) {

                        }
                        break;
                     }
                }
            }
        }
    }

Beep音を出す(Android)

2012年6月23日

Beep音を鳴らす。

Ringtone を使うには、RingtoneのURIを指定して、RingtoneManager.getRingtone() を呼び出し、Ringtone を取得。

取得したRingtone の start() と stop() を呼び出す。

※このコードはエミュレータではエラーになる。(Settings.System.DEFAULT_RINGTONE_URI=null になってしまう)

    private void beep(int ms) {
        Uri rturi = Settings.System.DEFAULT_RINGTONE_URI;
        if(rturi != null) {
            Ringtone rt = RingtoneManager.getRingtone(this.getContext(), rturi);
            if(rt != null) {
                rt.play();                
                try {
                    Thread.sleep(ms);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                rt.stop();                
            }
        }        
    }

他にも以下のようなものを使って音を出せる。

Custom Dialog を作成 (Android)

2012年6月22日

別にMainのViewをもつActivityの中で使用するCustom Dialog を作成してみる。

Dev Guideにある以下のページを参照。丁寧に書いてあるので、ほぼこのページとそこのリンクだけの情報で作成できる。
http://developer.android.com/guide/topics/ui/dialogs.html#CustomDialog
今回は、タイマーの時間をセットするだけの簡単なものなので、AlertDialogを使用する。
引っかかってしまった点が1つだけあった。Dev GuideにあるAlertDialogを作成するコード例では
OnCreatedDialog() でDialogをcreateするコードの中で、LayoutInflater を取得するところが

 
    	Context mContext = getApplicationContext();
    	LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);

となっていたが、Activityクラスで作成するときは、Context は getApplicationContext() で取得するものでは例外が発生してしまった。API Demo のソースなどを参照し、下のように this つまりActivity クラス自身を指定すると例外はなくなった。

 
    	LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);

このあとは、DevGuideのサンプル通りに、以下のようなコードで実装できた。
なお、setView() でカスタムのレイアウトを指定しても、setNegativeButton()、setPositiveButton() を指定すると、ボタンはそのレイアウトの下に表示された。つまり、カスタムのレイアウトのなかにはOKやCancelのボタンは不要ということになる。

 
    	AlertDialog.Builder builder;
    	AlertDialog dialog;
    	LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
    	final View layout = inflater.inflate(R.layout.timer_setting_dialog, null)
        //Custom Dialog 内のコントロールの初期化処理
        Spinner spn1 = (Spinner)layout.findViewById(R.id.spinner1);
        ArrayAdapter adapter1 = new ArrayAdapter(this, android.R.layout.simple_spinner_item);
        adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        for(int i = 0; i<100; i++) {
        	adapter1.add(String.format("%02d", i));
        }
        spn1.setAdapter(adapter1);
        //(省略)

        //AlertDialog.Builderを使う
    	builder = new AlertDialog.Builder(this);
    	builder.setView(layout);
    	builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            }
        });
    	builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                //(省略)
            }
        });
    	dialog = builder.create();
Custom Dialog

Custom Dialog

iPhone/iPadでPicasaを使う(画像のプレビューまで)

2012年5月13日

Picasaを使う(iPhone)でPicasaWebAlbumのAPIでアルバム一覧を取得するところまでやったので、今回は画像のプレビューまで実装してみた。(ソース)

iPhone版の画面

Login画面(iPhone)

Login画面(iPhone)

Album一覧(iPhone)

Album一覧(iPhone)

写真一覧(iPhone)

写真一覧(iPhone)

(more…)

Custum View をXMLのレイアウトに加える(Android)

2012年3月3日

タイマーの残り時間を表示する簡単なCustom View を作成し、既存のGUIコンポーネントと一緒にXMLのレイアウトに組み込む。

参照ページ

Custom View を実装

android.view.Viewを継承したクラスを作成し、onDraw(Canvas canvas) をオーバーライドして描画ロジックを実装するだけ。但し、XMLのレイアウトに組み込むには、さらに以下の2つの形式のコンストラクタも実装する必要がある。

public View (Context context)

public View (Context context, AttributeSet attrs)

Layoutに組み込む

このCustomViewをXMLのレイアウトに組み込むには、ただ、CustomViewのクラス名をフルパスで指定するだけでよい。

    <TextView
        android:id="@+id/textView1"
        android:layout_alignParentTop="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <stndstn.intervaltimer.TimerView
        android:id="@+id/timerview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true"
    />

これはLayout.xmlの一部で、上は通常のTextView、下が今回作成したCustomView。

クラス名をフルパスで設定する以外は、手でXMLのレイアウトを編集するときと同じ要領。

Re-installation failed due to different application signatures. が出たとき

2012年2月18日

Emulatorでアプリをデバッグしようとしたとき、以下のようなエラーが発生した

[2012-02-18 16:54:35 - IntervalTimer] Installing IntervalTimer.apk...
[2012-02-18 16:54:46 - IntervalTimer] Re-installation failed due to different application signatures.
[2012-02-18 16:54:46 - IntervalTimer] You must perform a full uninstall of the application. WARNING: This will remove the application data!
[2012-02-18 16:54:46 - IntervalTimer] Please execute 'adb uninstall stndstn.intervaltimer' in a shell.
[2012-02-18 16:54:46 - IntervalTimer] Launch canceled!

adb は SDKの /platform-tools フォルダ にあった。Emulatorが起動した状態で、SDKの /platform-tools フォルダで以下のコマンドを実行し、解消できた。

$ ./adb uninstall stndstn.intervaltimer

NSManagedObjectModelでTableViewのデータを管理する

2011年12月23日

xcdatamodel でデータモデルを定義

xcdatamodelにデータモデルを定義

TableViewControllerもこれにあわせて変更

まずは、Viewに関連付けるEntityを指定

- (NSFetchedResultsController *)fetchedResultsController
{
    if (__fetchedResultsController != nil)
    {
        return __fetchedResultsController;
    }

    /*
     Set up the fetched results controller.
    */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.(*defined in xcdatamodel)
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Album" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.(*defined in xcdatamodel)
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error])
        {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return __fetchedResultsController;
}

次にセルデータの表示のためのコードを編集

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell.
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [[managedObject valueForKey:@"name"] description];
}

TableView の ManagedObjectContextにデータを設定する

このコードはTableViewの外でもよい。ここで、mFetchedResultsController は、TableViewの fetchedResultsController で取得した NSFetchedResultsController 。

既存データをクリア

Entity毎にクリアできるメソッドが見つからなかったので、1つずつ削除してみた。

    //clear existing data
    NSArray *fetchedObjects = [mFetchedResultsController fetchedObjects];
    NSEnumerator *enumerator = [fetchedObjects objectEnumerator];
    NSManagedObject *object;
    while ((object = [enumerator nextObject])) {
        [[mFetchedResultsController managedObjectContext] deleteObject:object];        
    }    

データをInsertする。

            //
            // insert into managedObjectContext
            //
            // Create a new instance of the entity managed by the fetched results controller.
            NSManagedObjectContext *context = [mFetchedResultsController managedObjectContext];
            NSEntityDescription *entity = [[mFetchedResultsController fetchRequest] entity];
            NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

            [newManagedObject setValue:title forKey:@"name"];

            // Save the context.
            NSError *error = nil;
            if (![context save:&error])
            {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
                 */
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
            //

persistentStoreCoordinatorでエラーになるとき

データモデルを変更した後、AppDelegate の persistentStoreCoordinatorでエラーになるときは、自動生成されるコメントに書いてあるように、一度既存のデータファイルを削除してみる。

//deleting the existing store
 [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];

画像をViewerで開く

2011年11月3日
 File f = new File(ファイル名);
 Uri data = Uri.fromFile(f);
 Intent intent = new Intent(Intent.ACTION_VIEW);
 intent.setDataAndType(data, "image/jpeg");
 startActivity(intent);

Navigation-basedだけど最初の画面はTableViewにしたくないとき

2011年10月27日

Navigation-based applicationでプロジェクトを作成したが、最初の画面はTableViewにしたくないとき

  1. 新たにUIViewControllerクラスを追加(XIBファイル付きで)
  2. MainWindow.xib の Objects 内にある Navigation Controller の下の Root View Controller について
    1. 名前を変える
    2. Attributes Inspector にある NIB Name を、上で作成したXIB Name に変える

      Change NIB name of RootViewController

      RootViewController の NIB name を変更

    3. Identiy Inspector にある Class を、上で作成したクラスに変える

      Change class name of RootViewController

      Class name も変える

  3. MainWindow.xib の Objects 内にある Navigation Controller の下の Root View Controller について
    1. AppDelegate.m の – (void)awakeFromNib に RootViewControllerに関するコードが有るので、これは削除する。ここで行われている TableViewController に managedObjectContext を渡す処理は、TableViewController をinitialize するところで行う。
    2. Root View Controller は、不要なら削除