iPhoneで3GP動画を再生する方法

iOS 4.3になってからiPhoneSafariやダウンロード系アプリの中で3GP形式の動画が再生できなくなってしまいました。日本の携帯電話(フィーチャーフォン)で撮影した動画では3GP形式が事実上の標準となっているため、それらの携帯電話で撮影された動画が見られなくなり、悲しい思いをしている人も多いと思います。

実は、3GP動画はカメラロール(カメラアプリで撮影された写真が保存される場所)に入れることで、いまだに再生できます。

この記事では、アップローダーに掲載されている3GP動画をiPhone単体でダウンロードし、再生する方法を説明します。

なお、下記の手順はiPhone3GSiOS 4.3.5、Downloads 3.0.4の環境で確認したものです。今後のバージョンアップなどにより同様の手順で再生できなくなる可能性があります。ご了承ください。

事前準備

1. Downloads/Liteをインストールします。

Downloads(有料版)またはDownloads Lite(無料版)をインストールします。無料版のLiteで大丈夫です。
※Liteではファイルを7個までしかダウンロードできません。8個目をダウンロードするには、どれかのファイルを削除する必要があります。

2. インストールしたDownloads/Liteを起動し、右下にある [Settings] アイコンをタップします。

3. 設定画面が表示されます。[Identify Browser As] をタップします。

4. 「Firefox 3.6」をタップして選択します。

以上の作業は最初の1回だけやれば大丈夫です。

ダウンロードする

1. 画面左下の [Browser] アイコンをタップし、見たい動画のURLをアドレスバーに入力し、動画ページを表示します。

2. 表示された動画のサムネイルや「動画を閲覧」のリンクなどをタップします。

3. メニューが表示されますので [Download] をタップします。

4. [Add Download] 画面が表示されます。上段は動画のURL、下段はフォルダ選択になっています。通常はそのままでOKです。[Done] をタップします。

5. 画面下部の [Downloads] アイコンをタップすると、ファイルのダウンロード状況が表示されます。新たにダウンロードしたものが上に来ます。ファイル名をタップします。

6. メニューが表示されます。[Reveal in File Manager] をタップします。

7. 実際にダウンロードされたファイルが表示されます。


カメラロールに保存し、再生する

1. 保存された動画の右にある右矢印アイコンをタップします。

2. 表示された画面の [Add to Photos] をタップします。

これでカメラロールに保存されました。

写真アプリのカメラロールを開き、保存した動画をタップすれば再生できます。

EclipseとMavenでGWTアプリケーションを作成する:05 サーバーと通信する

環境など

私は日本語化されたEclipseを使用しているので、英語版とはメニューや項目名が異なります。お使いの環境と異なる場合には、適宜読み替えてください。

この説明で使用しているソフトウェアのバージョンは次の通りです。

サーバーとの通信と2つのインターフェイス

Webアプリケーションではブラウザ側で処理が完結するといったことはあまりなく、多くの場合にはサーバーと接続し、何らかの情報のやり取りをします。

GWTではサーバーと通信する方法が複数用意されています。ここではリモート・プロシジャ・コール(RPC)を使ってサーバーと通信するサンプルを作成します。

前回までに作成したアプリケーションで挨拶メッセージを作成する部分をサーバー側のサービスとして独立させ、それをクライアント側から呼び出すことにします。

サービスを作成するためには2つのインターフェースが必要です。ひとつはサービス用インターフェース、もうひとつは呼び出し用インターフェースです。

サービス用インターフェースは次のような特徴を持っています。

  • サーバー上のサービスが実装するインターフェースです。
  • GWTのRemoteServiceインターフェースをextendsします。

呼び出し用インターフェースは次のような特徴を持っています。

  • クライアント側のコードがサーバー上のサービスを呼び出すときに使うインターフェースです。
  • サービス用インターフェースと同じ名前のメソッドを持ちますが、最後の引数としてAsyncCallback型を持ちます。ここでTは元のメソッドの戻り値の型です。メソッド自体の戻り値はvoidになります。
  • 慣例として、サービス用インターフェースの後ろに「Async」を付けた名前にします。

呼び出し用インターフェースが自動生成されないようにする

gwt-mavenプラグインで作成されたpom.xmlには、呼び出し用インターフェースを自動生成するための記述があります。ここではインターフェースは自分で作成しますので、以下の手順で自動生成されないようにします。

1. プロジェクト・エクスプローラーからpom.xmlをダブルクリックし、エディタで開きます。「pom.xml」タブに切り替えます。

2. gwt-maven-pluginの設定のの下にあるgenerateAsyncを削除します。

変更前

<goals>
  <goal>compile</goal>
  <goal>generateAsync</goal>
  <goal>test</goal>
</goals>

変更後

<goals>
  <goal>compile</goal>
  <goal>test</goal>
</goals>

サービス用インターフェースを作成する

次のようなインターフェースを作成します。

  • 名前はGreetingMessageService
  • clientパッケージに含める
  • RemoteServiceインターフェースをextendsする

GreetingMessageSerivce:

package jp.ne.hatena.paz3.GwtSample.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("GreetingMessageService")
public interface GreetingMessageService extends RemoteService {

	public String getGreetingMessage(String name);

}

getGreetingMessageは、引数として指定された名前を受け取り、挨拶メッセージを返すメソッドです。

@RemoteServiceRelativePathでサービスを呼び出すときのURL相対パスを指定します。

呼び出し用インターフェースを作成する

次のようなインターフェースを作成します。

  • 名前はGreetingMessageServiceAsync
  • clientパッケージに含める

GreetingMessageSerivceAsync:

package jp.ne.hatena.paz3.GwtSample.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface GreetingMessageServiceAsync {
	
	void getGreetingMessage(String name, AsyncCallback<String> callback);
	
}

サービスの実装を作成する

サービスを実装します。サービスを実装するクラスは次のようにします。

  • RemoteServiceServletをextendsする
  • サービス用インターフェースを実装する
  • serverパッケージに含める

そこで、次のようなクラスを作成します。

  • 名前はGreetingMessageServiceImpl
  • RemoteServiceServletをextendsする
  • GreetingMessageServiceインターフェースをimplementsする
  • serverパッケージに含める

GreetingMessageSerivceImpl:

package jp.ne.hatena.paz3.GwtSample.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import jp.ne.hatena.paz3.GwtSample.client.GreetingMessageService;

public class GreetingMessageServiceImpl extends RemoteServiceServlet
		implements GreetingMessageService {

	public String getGreetingMessage(String name) {
		String message = "Hello " + name + " !";
		return message;
	}

}

サービスを登録する

作成したサービスをweb.xmlに登録します。

src/main/webapp/WEB-INF/web.xmlの間に次の行を追加します。

web.xml(抜粋):

<servlet>
	<servlet-name>GreetingMessageService</servlet-name>
	<servlet-class>jp.ne.hatena.paz3.GwtSample.server.GreetingMessageServiceImpl</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>GreetingMessageService</servlet-name>
	<url-pattern>/jp.ne.hatena.paz3.GwtSample.Application/GreetingMessageService</url-pattern>
</servlet-mapping>

呼び出し側コードを作成する

前回までで作成したApplication.javaを、サービスを呼び出すように変更します。

importに次の行を追加します。

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

showGreetingMessageメソッドを変更します。

変更前:

private void showGreetingMessage() {
	String name = nameTextBox.getText();
	String message = "Hello " + name + " !";
	messageLabel.setText(message);
}

変更後:

private void showGreetingMessage() {
	String name = nameTextBox.getText();
	
	GreetingMessageServiceAsync greetingMessageService =
		GWT.create(GreetingMessageService.class);
	
	greetingMessageService.getGreetingMessage(name, new AsyncCallback<String>() {
		
		public void onSuccess(String result) {
			messageLabel.setText(result);
		}
		
		public void onFailure(Throwable caught) {
			String message = "Error: " + caught.toString();
			messageLabel.setText(message);
		}
		
	});
}

ホストモードで実行できるようにする

ここまでの設定をして、warファイルを作成しアプリケーションサーバーに配置すれば、リモートサービスを呼び出すアプリケーションは動作します。しかし、Mavengwt:runターゲットで動作するホストモードでは実行できません。

ホストモードで実行させるには、以下の2つの設定をします。

サービスを.gwt.xmlに登録する

Application.gwt.xmlの間に次の行を追加します。

Application.gwt.xml(抜粋):

<servlet path="/GreetingMessageService" class="jp.ne.hatena.paz3.GwtSample.server.GreetingMessageServiceImpl" />
war/WEB-INF/web.xmlを作成する

war/WEB-INF/web.xmlを作成します。上記で修正したweb.xmlをwar/WEB-INFの下にコピーしても良いでしょう。

src/java/main/WEB-INF/web.xmlを読み込んでくれれば便利だと思うのですが、そうなっておらず、別々のファイルを読み込むようになっています。ファイルを分けている理由について http://mojo.codehaus.org/gwt-maven-plugin/user-guide/hosted.html には「ホストモードはテスト用であり、配備用の設定とは別にすべきである」と書かれています。

実行する

前々回の方法で実行してください。動作は前回とまったく同じになりますが、内部ではRPCを使ってサーバー側のサービスを呼び出しています。

EclipseとMavenでGWTアプリケーションを作成する:04 簡単なアプリケーションを作成する

環境など

私は日本語化されたEclipseを使用しているので、英語版とはメニューや項目名が異なります。お使いの環境と異なる場合には、適宜読み替えてください。

この説明で使用しているソフトウェアのバージョンは次の通りです。

アプリケーションの作成

前回のコードを土台として、簡単なアプリケーションを作成して動かしてみます。

1. Eclipseのプロジェクト・エクスプローラーからApplication.java (src/main/java/jp/ne/hatena/paz3/GwtSample/client/Application.java) をダブルクリックし、エディタで開きます。

2. コードを次のように変更します。

Application.java

package jp.ne.hatena.paz3.GwtSample.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Application
    implements EntryPoint
{

	private Label nameLabel;
	private TextBox nameTextBox;
	private Button greetButton;
	private HorizontalPanel horizontalPanel;
	private Label messageLabel;
	private VerticalPanel verticalPanel;

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad()
	{
		// Make input area.
		nameLabel = new Label("Name");
		nameTextBox = new TextBox();
		greetButton = new Button("Hi !");
		horizontalPanel = new HorizontalPanel();
		horizontalPanel.add(nameLabel);
		horizontalPanel.add(nameTextBox);
		horizontalPanel.add(greetButton);
		
		// Make output area.
		messageLabel = new Label();
		
		// Combine two areas vertically.
		verticalPanel = new VerticalPanel();
		verticalPanel.add(horizontalPanel);
		verticalPanel.add(messageLabel);
		
		// Add panel to web page.
		RootPanel.get().add(verticalPanel);
		
		// Listen for click event on greetButton.
		greetButton.addClickHandler(new ClickHandler() {
			
			public void onClick(ClickEvent event) {
				showGreetingMessage();
			}
			
		});
	}
	
	private void showGreetingMessage() {
		String name = nameTextBox.getText();
		String message = "Hello " + name + " !";
		messageLabel.setText(message);
	}
	
}

3. 保存します。

アプリケーションの実行

前回の手順 で実行してください。実行すると、「Name」と書かれたテキストボックスが表示されます。

テキストボックスに名前を入れて「Hi !」をクリックすると、その下にメッセージが表示されます。

日本語も使用できます。

コードの解説

画面レイアウト

今回作成した画面は次のようになっています。

horizontalPanelはコンポーネントを横方向に並べるパネルです。horizontalPanelの上にnameLabel(「Name」と書かれたラベル)、nameTextBox(名前を入れるテキストボックス)、greetButton(「Hi !」と書かれたボタン)が横方向に並んで乗っています。

verticalPanelはコンポーネントを縦方向に並べるパネルです。verticalPanelの上にhorizontalPanelとmessageTextBox(メッセージを表示するテキストボックス)が縦方向に並んで乗っています。

コンポーネントを配置する

GWTのアプリケーションでは、ページを表示したときにonMouseLoadが実行されます。

onMouseLoadの中では、次のコードでnameLabel、nameTextBox、greetButtonを作成し、horizontalPanelのaddメソッドで配置しています。

// Make input area.
nameLabel = new Label("Name");
nameTextBox = new TextBox();
greetButton = new Button("Hi !");
horizontalPanel = new HorizontalPanel();
horizontalPanel.add(nameLabel);
horizontalPanel.add(nameTextBox);
horizontalPanel.add(greetButton);

次のコードでmessageLabelを作成し、horizontalPanelと共にverticalPanelのaddメソッドで配置しています。

// Make output area.
messageLabel = new Label();

// Combine two areas vertically.
verticalPanel = new VerticalPanel();
verticalPanel.add(horizontalPanel);
verticalPanel.add(messageLabel);

次のコードでverticalPanelをWebページに追加しています。RootPanelはWebページ内でコンポーネントを配置できる場所を表すクラスで、getメソッドで実際の場所を取得します。画面に表示するコンポーネントは必ずRootPanelのaddメソッドで画面に配置する必要があります。

// Add panel to web page.
RootPanel.get().add(verticalPanel);
ボタンクリック時の処理

次はgreetButtonをクリックしたときの処理です。

// Listen for click event on greetButton.
greetButton.addClickHandler(new ClickHandler() {
	
	public void onClick(ClickEvent event) {
		showGreetingMessage();
	}
	
});

ボタンをクリックしたときの処理は、ButtonクラスのaddClickHandlerで登録します。addClickHandlerメソッドの引数として、ClickHandlerインターフェイスを実装した無名クラスのインスタンスを作成(new ClickHandler() {…})して渡しています。

ClickHandlerインターフェイスにはonClickメソッドがあります。ここにクリック時の処理を記述します。ここではshowGreetingMessageメソッドを呼び出しています。

showGreetingMessageメソッドは、messageLabelに「Hello 名前 !」という文字列を設定するメソッドです。

private void showGreetingMessage() {
	String name = nameTextBox.getText();
	String message = "Hello " + name + " !";
	messageLabel.setText(message);
}