分享
 
 
 

[转]J2ME MIDP Device Fragmentation Tutorial with Marv The Miner

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

j2me MIDP Device Fragmentation Tutorial with Marv The Miner

http://www.netbeans.org/kb/articles/tutorial-j2mefragmentation-40.html

Feedback

Feedback

This tutorial shows how to configure the IDE to work with existing JavaTM 2, Micro Edition Platform (J2METM Platform) MIDP projects and, specifically, how to use the NetBeansTM IDE's built-in solution to the device fragmentation problem. Following this tutorial from start to finish will illustrate the following:

How to port an existing fragmented MIDP project to NetBeans

How to use the IDE's built-in device fragmentation solution

The example program this tutorial uses is the popular j2me game "Marv The Miner," which was released under GPL and written to run on several different mobile platforms.

This tutorial should take approximately two hours to complete and covers the following topics:

Import sources from an existing MIDP project.

Create and customize project configurations for each distribution Jar.

Mark pieces of source code as being specific to each configuration.

Build several distribution Jars for the project.

Use external emulators from within the IDE.

To follow this tutorial you need the MarvTheMiner_120_all.zip file, which contains the original source files of the program. Click here and download "Marv the Miner v1.2.0 (including level editor)" to obtain the source files.

Setting Up Your Environment

Obtaining and Installing the Required Software

Starting the IDE

Obtaining the Required Source Files

Developing the Marv The Miner Application in NetBeans

Import Existing Sources

Creating Project Configurations

Customize Project Settings for Configurations

Create Custom Code Blocks for each Configuration

Building and Executing the Marv the Miner Application

Exploring Configurations Further

Using Non-UEI compliant Emulator Platforms

Setting Up Your Environment

This section describes how to set up your system before starting the tutorial.

Obtaining and Installing the Required Software

The following software is required for the example:

The NetBeansTM Integrated Development Environment (IDE) with the NetBeans Mobility Pack 4.0 Beta 2 or FCS.

You can obtain this software from the NetBeans download site: http://www.netbeans.org/downloads/index.html

JavaTM 2 Software Development Kit, Standard Edition (J2SETM SDK), v. 1.4.2 or higher

You can obtain the J2SE SDK from http://java.sun.com/j2se/downloads.html

j2meTM Wireless Toolkit 2.0 or higher

The j2me Wireless Toolkit is installed with the NetBeans Mobility Pack. You also can obtain the Wireless Toolkit from http://java.sun.com/products/j2mewtooklit/index.html.

Nokia Series 60 SDKs for Symbian OS

The SDK can be obtained at http://www.forum.nokia.com/main/0,6566,034-483,00.html

SDK for one or more of the following: Nokia Series 40, Nokia Series 80, Nokia Series 90, Motorola SDK4.1 for j2me GA, Vodafone

You can obtain Motorola SDK4.1 for j2me GA from http://www.motocoder.com/motorola/pcsHome.jsp?node_name=SDK (registration required)

You can obtain Nokia SDKs from http://www.forum.nokia.com/main/1,6566,030,00.html. Select Java in the "View tools by technology area" drop down box.

The Vodafone SDK is available only to Global Partners, and can not be obtained via simple online registration.

Use the instructions provided at the download sites to install the software.

Starting the IDE

To start the NetBeans IDE:

On Microsoft Windows

Choose Start > Programs > NetBeans version > NetBeans IDE.

On UNIX, or Linux environments

In a terminal window, type sh IDE-install-path/bin/runide.sh

The IDE-install-path variable stands for the path to the IDE's home directory.

Obtaining the Required Source Files

The MarvTheMiner_120_all.zip file contains the source files of the original Marv The Miner application. The zip includes a MarvTheMiner directory, which contains the src and res subdirectories that you will use in this tutorial.

To unzip the MarvTheMiner_120_all.zip file:

In your file system, create a temporary location for the contents of MarvTheMiner_120_all.zip.

For example, this tutorial refers to this directory as the C:\temp directory.

Use an application that unzips files to unzip the MarvTheMiner_120_all.zip file to the temp directory.

The temp directory now has a MarvTheMiner directory, which contains the following files and subdirectories:

File or Subdirectory

Description

src

The source files which make up the Marv The Miner program.

res

Contains the resource files used by the program. This includes graphics as well as .map files which are used to define the game level's layouts.

MarvEditor

A level editor (outside the scope of this tutorial).

Nokia.full

A Nokia build of the game.

MIDP.full

A generic MIDP build of the game.

Move the res directory to C:/temp/MarvTheMiner_120_all/src/. This is a small work-around to make sure the resource files maintain the correct relative path once we create a new NetBeans project.

Developing the Marv The Miner Application in NetBeans IDE

In this section, you set up and work with the existing project sources within the NetBeans IDE.

Import existing sources

Creating the Project

The first step is to create a new project in the NetBeans IDE.

Choose File > New Project from the main menu.

The New Project wizard is displayed.

In the Categories list select Mobile. Then select Mobile Project from Existing MIDP Sources and click Next.

If you did not install NetBeans using the installer, you are shown a panel here instructing you to install a mobile platform. Follow the instructions and install some version of the Wireless Toolkit. Then click next.

For the Imported Sources Location, click the Browse button and navigate to C:/temp/MarvTheMiner_120_all/src directory that you created when you unzipped the MarvTheMiner_120_all.zip file. Select the src directory, and click Open. Click Next.

Enter a name for your New Project. For example, name it MarvTheMiner.

Now select a directory where the new project directory should reside. Make sure the Set as Main Project check box is enabled, and click Finish.

A new project, MarvTheMiner, is created and displayed in the IDE's Projects tab.

Expand the MarvTheMiner root project node to see the project's sources and resources. Expand the <default package> node and then double click on Main.java to open that file in the editor.

Creating Project Configurations

The NetBeans device fragmentation solution is based on the use of project configurations. A project should have one project configuration for each distribution Jar/Jad you would like created for that project.

If you examine the file Main.java, you will see that the the authors support multiple platforms with a combination of comments (for Nokia's FullCanvas) and Class.forname(). They also define a variable vendor that is used to track on which phone the application is running. Based on this information, you can see that they are supporting five different groups of phones:

Nokia Series 60

Other Nokia

Motorola

Vodafone

Other

As such, you will create four configurations to handle differences between these distributions.

Creating a Configuration

Right-click on the MarvTheMiner project node and select Properties.

This opens the Project Properties page that is used to control most aspects of the project.

Click the Manage Configurations button at the top of the page. This opens the Manage Configurations dialog.

Click Add and then type NokiaSeries60 and press OK.

Repeat the previous step for Motorola, Vodafone, and NokiaOther. Click Close to close the Manage Configuration dialog.

The Project Configuration combo box at the top of the Project Properties page should now contain five configurations. We will use these configurations in a moment, but for now lets add some emulators into the IDE.

Adding Emulators to the IDE

To run the project using the emulator platforms you have installed on your computer, you must first register them with the IDE.

Select DefaultConfiguration in the Project Configuration combo, and then select the Platform node. Click the Manage Emulators button. The Platform Manager dialog appears.

Note that this dialog can also be accessed from the main menu at Tools>Java Platform Manager.

Click Add Platform and navigate to the directory where you installed your Nokia Series 60 emulator. Click Next.

Ensure that the emulator settings were detected correctly, and then click Next.

Here you can point to the source and javadoc files for the emulator if you want. Otherwise just hit Finish to complete the installation of the platform.

Repeat these steps for each emulator platform you have installed on your machine and that you want to use from within the IDE.

Note that only emulators that comply with UEI standards will be detectable by the IDE. Unfortunately, this means that the Motorola 7.5 emulator that the developers used for Marv The Miner can not be detected. A later section in the tutorial will explain a work-around for using non-UEI emulators from within the IDE.

Customizing Project Settings for Configurations

Each panel in the Project Properties page can be customized separately for each project configuration. By default, configurations will use the settings defined in the default configuration.

Open the Project Properties page and select the Platform panel. Make sure DefaultConfiguration is selected in the Project Configuration combo box.

Select j2me Wireless Toolkit 2.x in the Emulator Platform combo box. Toggle the radio buttons to CLDC-1.0 and MIDP-2.0.

By default, all configurations will use this emulator for building and executing the project. This isn't what we want, however, as the code references several platform-specific libraries.

Select the NokiaSeries60 configuration from the Project Configuration combo.

The Platform panel is now entirely grayed out. This is because we are currently using the values from DefaultConfiguration for this panel.

Uncheck the Use Values from "DefaultConfiguration" check box at the top of the panel.

All elements in the panel should now be enabled. Select the Series 60 MIDP Concept SKD Beta 0.3.1 Nokia platform from the Emulator Platform combo box.

If you toggle between the each configuration, you'll see that all are now using the value specified in DefaultConfiguration except for the NokiaSeries60 configuration. If you change any of the configuration settings in the DefaultConfiguration Platform panel, the changes will propagate to all configurations except NokiaSeries60.

Select the NokiaOther configuration in the Project Configuration combo box. Uncheck the Use Values from "Default Configuration" checkbox and select one of the other Nokia platforms you installed.

Repeat these steps for the Vodafone platform as well.

As mentioned above, the Motorola 7.5 emulator is not UEI-compliant and could therefore not be installed into the IDE. However, we can still point to its APIs for compilation purposes. Activate the Motorla configuration and select the Libraries & Resources panel.

Uncheck the Use Values from "DefaultConfiguration" checkbox.

Click Add Jar/Zip and navigate to {motorola install directory}\Emulator7.5\lib. Select each .zip file (using ctl+mouse) and click Open.

Click OK to exit the project properties. You are done creating projects configurations for now.

Creating Custom Code Blocks for each Configuration

The second part of the device fragmentation solution is the ability to specify certain blocks of code in your source files as being specific to one or more configurations. This is accomplished by using actions in the right-click context menu of the editor, or from the Edit > Preprocessor Blocks menu.

Open Main.java, and examine the initStaticData() method. Here, the method is determining at runtime which device-specific APIs are available, and then behaving accordingly. This is a very clever solution to some parts of the device fragmentation problem. Unfortunately, it also has the problem of being increasing the size of the distribution Jar, impacting runtime performance, adding complexity to the sources, and does not solve all fragmentation problems (as you will see later).

Here is the pertinent part of initStaticData():

vendor = 0;

try

{

// Nokia

Class.forName("com.nokia.mid.sound.Sound");

vendor = 1;

try

{

Class.forName("com.nokia.mid.ui.DeviceControl");

com.nokia.mid.ui.DeviceControl.setLights(0,100);

vendor = 2;

}

catch(Exception ex2){}

}

catch(Exception ex){}

try

{

// Vodafone

Class.forName("com.vodafone.v10.system.device.DeviceControl");

com.vodafone.v10.system.device.DeviceControl.getDefaultDeviceControl().

setDeviceActive(com.vodafone.v10.system.device.DeviceControl.BACK_LIGHT,

true);

vendor = 3;

}

catch(Exception ex){}

try

{

// Motorola

Class.forName("com.motorola.multimedia.Vibrator");

Class.forName("com.motorola.multimedia.Lighting");

com.motorola.multimedia.Lighting.backlightOn();

vendor = 4;

}

catch(Exception ex){}

Remove all of the functionality that is only dealing with determining which device the program is running on, so the code you are left looks like following: // Nokia

com.nokia.mid.ui.DeviceControl.setLights(0,100);

// Vodafone

com.vodafone.v10.system.device.DeviceControl.

getDefaultDeviceControl().

setDeviceActive(com.vodafone.v10.system.device.DeviceControl.BACK_LIGHT,

true);

// Motorola

com.motorola.multimedia.Lighting.backlightOn();

You now have three blocks of code that should be associated with your different configurations.

Highlight the Motorola-specific lines, then right-click on the editor and select Preprocessor Blocks>Motorola.

Repeat this step for the Vodafone block (Preprocessor Blocks > Vodafone).

For the Nokia code, select Preprocessor Blocks>Manage Preprocessor Block.

This opens the Manage Preprocessor Block dialog.

Select the options for both NokiaOther and NokiaSeries60 and click OK.

These code blocks are now associated with the configurations listed in the headers and footers of the preprocessor blocks. Changing the project's active configuration will trigger a preprocessor that will comment in and out blocks based on if the active configuration is a part of the preprocessor block's header and footer.

Change the project's active configuration by using the combo box in the main toolbar.

You can also do this by right-clicking on the project node>Set Active Project Configuration>select configuration from the same menu in the main Build menu, or by toggling the Configuration combo in the main toolbar (if your project is currently the main project).

Notice that the code block highlighting switches colors to identify which blocks are active or inactive. The active configuration name is also highlighted a different color in the header/footer of the code blocks.

Remove all the instances of class.forName() from the beep() method. If you also condense the if blocks, you are left with the following code: if (midlet.muteSound == 0)

{

// Nokia 3650, 7650

com.nokia.mid.sound.Sound sound = new com.nokia.mid.sound.Sound(1000,100);

sound.play(1);

// All other Nokias

com.nokia.mid.sound.Sound sound = new com.nokia.mid.sound.Sound(1000,100);

sound.play(1);

}

if (midlet.useVibra == 1)

{

// Nokia

com.nokia.mid.ui.DeviceControl.startVibra(50,500);

// Vodafone SDK

com.vodafone.v10.system.device.DeviceControl.

getDefaultDeviceControl().

setDeviceActive(

com.vodafone.v10.system.device.DeviceControl.VIBRATION,

true);

vibra_delay = 10;

// Motorola 7.5

com.motorola.multimedia.Vibrator.

setVibrateTone(

com.motorola.multimedia.Vibrator.VIBRATE_LONG);

com.motorola.multimedia.Vibrator.vibrateFor(500);

}

You should be able to associate each block with the correct configuration. Remember to associate the Nokia vibration control call with both Nokia configurations.

The run() method also contains a Vodafone-specific call. Remove the try/catch blocks and associate the two lines with the Vodafone configuration.

We're almost done. The final step is to somehow handle Nokia's FullCanvas.

Activate the NokiaSeries60 configuration.

Right click on the FullCanvas declaration and select Create If/Else Block (NokiaSeries60).

Right click on the first block and add NokiaOther.

Right click on the second block and add NokiaOther.

The second block is an Inverted block. Change the inverted block class definition to extend Canvas.

When you are done, your class definition should appear like so:

Building and Executing the Marv the Miner Application

Building and Executing the Application

At this point, we should be able to compile and run the program for all of our configurations. Clicking any of the icons in the main toolbar will execute the selected action for the Active configuration.

In the main menu, select Build > Build All Main Project Configurations.

Assuming everything is set up correctly, all configurations should now be built.

If you did not have access to one or more of the emulator platforms containing the correct APIs, this step might fail. If that is the case, you should manually comment out any line making a call to an API that you don't have.

Preverification will fail for the Motorola configuration if you have not followed the steps to manually install the motoral emulator described in the section for non-UEI emulators. To make this configuration compile without manually adding the emulator, you can comment out all motorola API calls and remove the motorola libs from the Libraries & Resources panel.

Select the Files tab in the upper left hand side of the IDE and expand the dist folder. In this folder you should have directories containing Jar/JADs for each configuration that was successfully built, as well as a Jar/Jad that represents the DefaultConfiguration build.

Press F5 to run the program for the currently selected configuration. You can switch configurations and press F5 again to run multiple versions of the program at the same time.

5. Exploring Configurations Further

This tutorial should have given you a good understanding of how you can import your existing MIDP projects into the NetBeans environment, but it does not cover all of the Device Fragmentation issues solved by the IDE. Below are some more examples of common problems and how they can be solved within the IDE.

Each panel in the project properties page can be configuration-specific (except the General page). This gives you a great amount of flexibility. For example, you can have different MIDlet-Version values (Application Descriptor panel) for each configuration's uniquely named (Creating Jar panel) distribution Jar.

When setting up dependencies between projects, especially when using Project Configurations, make sure to select the correct output jar in the Project Jar Files list box of the Select Project dialog. A project Jar will appear for each configuration in the project you have selected.

If, for example, you have two projects MyLibrary and MyApplication, both containing two configurations ReleaseConfiguration and DebugConfiguration, then you would take the following steps to set up the dependency correctly:

Open Project Properties for MyApplication. Select ReleaseConfiguration in the Project Configuration combo.

Select Libraries & Resources panel, and click the Add Project button.

Navigate to the location of MyLibrary project. The Project Jar Files listbox will now contain three Project Jars. Select the one in path dist/ReleaseConfiguration/ and click Add Project Jar Files

Switch to DebugConfiguration and repeat these steps, except this time add the project jar located in dist/DebugConfiguration/

This is the manner in which you should set up dependencies between projects when configurations are involved.

The solution is VCS-friendly. All source files will always be saved to the hard drive as if DefaultConfiguration was selected. This prevents conflicts during VCS check-in or update resulting from have a different active configuration. Be sure to also share your project.properties file (located in {projecthome}/nbproject)!

Projects can be run from the command line without the use of the IDE. Just type ant run in the project home directory and the project will be run using the active configuration. You can pass a different configuration to the ant script by typing ant run -Dconfig.active={config_name}

Projects that used existing preprocessor solutions should be easy to import. Though the NetBeans preprocessor is less complex than some, any situation can be expressed using the provided directives.

The Libraries & Resources panel or the Filtering panel can be used to determine which version of a resource should be deployed to a distribution Jar.

Libraries & Resources: Create multiple versions of a Jar file containing all resources for the application and then point to the correct version of the Jar for each configuration. So you might have 3 jars: large_res.Jar, medium_res.Jar, small_res.Jar each containing resources of the same name, but different resolutions. Then point your Nokia_large, Nokia_med, Nokia_small configurations at the correct version.

Filtering: Include your resources directly in or under the src directory then use the Filtering tree to control which version of the resources are included in the distribution Jar.

Using Non-UEI Compliant Emulator Platforms

Though only 3rd party emulator platforms that follow the UEI specification can be automatically detected by the IDE, non-UEI complient emulators can still be used. This section describes how it can be done.

Adding Non-UEI Compliant Emulators

In your userhome directory (the Windows default is C:\Documents and Settings\{username}\.netbeans and the Linux default is /home/{username}/.netbeans), examine the {userhome}\config\Services\Platforms\org-netbeans-api-java-Platform directory.

This directory contains xml files that define the installed emulator platforms. You can manually create these files for any emulator which is not UEI-compliant. The DTD for this xml file can be found at http://www.netbeans.org/dtds/j2me-platformdefinition-1_0.dtd

Save the following as SDK_4.1_MRI_7.5.xml to use the Motorola 7.5 emulator needed for this tutorial. Note that the use of &quot; is intentional, and should be saved as such. <?xml version='1.0'?>

<!DOCTYPE platform PUBLIC '-//NetBeans//DTD j2me PlatformDefinition 1.0//EN'

'http://www.netbeans.org/dtds/j2me-platformdefinition-1_0.dtd'>

<platform name="Motorola_7_5"

home="C:\WTK\Motorola\SDK v4.1 for j2me\Emulator7.5"

type="custom"

displayname="Motorola 7.5"

srcpath=""

preverifycmd="&quot;{platformhome}/bin/preverify.exe&quot;

-classpath &quot;{classpath}&quot; -d &quot;{destdir}&quot;

&quot;{srcdir}&quot;"

runcmd="">

<device name="Motorola_7_5" securitydomains="trusted,untrusted"

description="Motorola_7_5">

<configuration name="CLDC" version="1.1" displayname="CLDC"

classpath="${platform.home}/lib/cldc.zip"

dependencies="" default="true"/>

<profile name="MIDP" version="2.0" displayname="MIDP"

classpath=";${platform.home}/lib/midp.zip"

dependencies="" default="true"/>

</device>

</platform>

You will need to restart the IDE after saving this XML file. Once you have done so, you will be able to choose Motorola 7 5 as a platform and Motorola_7_5 as a device. You should associate the Motorola configuration with this new platform. Note that you may need to delete the cache files located in {userhome}\var\cache in order for the manually installed platform to be detected. Also, you should not delete the mdrstorage folder that may also be located there.

Notice that the runcmd attribute is set to empty string. This is because the command to start this Motorola emulator takes the MIDlet to execute as one of its parameters. This is nothing like UEI standards, and cannot be directly supported in the IDE. However...

If the emulator platform you're using does not require more information than that provided to UEI emulators, then you can skip this step. The following information is provided to UEI emulators:

Security Domain

Platform Type

Platform Home

Jad Location

Jad Destination Directory / Jad Name

If your emulator requires additional information (such as the location of project Jar or the name of the MIDlet to execute), you can execute emulators by modifying the build.xml file located in your project home directory.

This file controls all project actions. We can create a new target here that executes the motorola emulator and passes all appropriate data whenever the Run action is invoked on the Motorola configuration.

Add the following code your project's build.xml:

<target description="Run MIDlet suite." depends="init" name="run">

<condition property="run.motorola">

<!-- arg2 must match the configuration name you would like to use the special emulator -->

<equals arg1="${config.active}" arg2="Motorola"/>

</condition>

<ant inheritrefs="true" inheritall="true" target="run_normal"/>

<ant inheritrefs="true" inheritall="true" target="run_motorola"/>

</target>

<target description="Run MIDlet suite the normal way." depends="init"

name="run_normal" unless="run.motorola">

<nb-run commandline="${platform.runcommandline}"

securitydomain="${evaluated.run.security.domain}"

execmethod="${run.method}" platformtype="${platform.type}"

platformhome="${platform.home}" device="${platform.device}"

jadurl="${dist.jad.url}" jadfile="${dist.dir}/${dist.jad}"/>

</target>

<target description="Run MIDlet suite for motorola's non-UEI emulator."

depends="init" name="run_motorola" if="run.motorola">

<property name="project.home" location="."/>

<!-- the last arg line contains an value "Miner". This must match the name of the midlet you want to execute -->

<java dir="${platform.home}/bin"

fork="true"

classname="com.mot.tools.j2me.emulator.Emulator"

classpath="${platform.home}/bin/Emulator.jar;${platform.home}/bin/configtool.jar">

<jvmarg value="-Djava.library.path=${platform.home}/lib"/>

<arg value="-classpath${project.home}/${dist.dir}/${dist.jar}"/>

<arg line="-deviceFile"/>

<arg value="${platform.home}/bin/RESOUR~1/T720I~1.PRO"/>

<arg line="javax.microedition.midlet.AppManager Miner -JSA 1 1"/>

</java>

</target>

So the run_motorola target will be run whenever the active configuration is Motorola. Otherwise, the run_normal target (which uses the normal emulator execution) will be invoked.

This concludes the Marv the Miner tutorial.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有