疯狂Android讲义学习笔记008Service和BroadCastReceiver

1.创建、配置和启动Services

1创建Service文件 FirstService,需要继承Service

public class FirstService extends Service {
    public FirstService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("nc", "onCreate: ===================");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("nc", "onStartCommand: started");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("nc", "onDestroy: destoried");
    }
}

2、在manifest上注册services

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fengray.myex016services">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".FirstService"
            android:enabled="true"
            android:exported="true"></service>
    </application>

</manifest>

3、activity文件中开启、关闭Service(通过intent来实现)

public class MainActivity extends AppCompatActivity {
    private Button start,destory;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final Intent intent=new Intent(this,FirstService.class);

        start=findViewById(R.id.start);
        destory=findViewById(R.id.destory);

        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startService(intent);
            }
        });

        destory.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopService(intent);
            }
        });

    }
}
2.绑定本地Service并与之通信Services

1、创建BindService类,继承自Service类

public class BindService extends Service {
    private int count;
    private  boolean quit;
    private MyBinder binder=new MyBinder();


    public BindService() {
    }

    class MyBinder extends Binder{
        //获取Service的运行状态,即他的count
        public int getCount(){
            return BindService.this.count;
        }
    }

    //Service被绑定时回调该方法
    public IBinder onBind(Intent intent){
        Log.d("nc", "onBind: Service is Binded");
        return binder;
    }

    //Service被创建时回调该方法
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("nc", "onCreate: Service is created");
        //启动一条线程,动态修改count状态值
        new Thread(new Runnable(){

            @Override
            public void run() {
                while (!quit){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    BindService.this.count++;
                }
            }
        }).start();
    }

    //Service被断开连接时回调该方法
    public boolean onUnbind(Intent intent){
        Log.d("nc", "onUnbind: Service is Unbinded");
        return true;
    }

    //Service被关闭之前回调该方法
    public void onDestroy(){
        super.onDestroy();
        this.quit=true;
        Log.d("nc", "onDestroy: Service is destroied");
    }
}

2、主布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/start"
        android:text="start"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/stop"
        android:text="stop"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/getService"
        android:text="getService"/>

</LinearLayout>

3、activity文件

public class MainActivity extends AppCompatActivity {
    private Button btnbinder,btnunbind,btnget;
    //保持所启动的Service的IBinder对象?啥叫保持,
    private BindService.MyBinder binder;
    //定义一个ServiceConnect对象
    private ServiceConnection serviceConnection = new ServiceConnection() {
        //当该activity与Service连接成功时回调该方法
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d("nc", "onServiceConnected");
            //获取Service的onBind方法所返回的MyBinder对象
            binder=(BindService.MyBinder)iBinder;
        }
        //当该activity与Service断开连接时回调该方法
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d("nc", "onServiceDisconnected");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnbinder=findViewById(R.id.start);
        btnunbind=findViewById(R.id.stop);
        btnget=findViewById(R.id.getService);
        final Intent intent=new Intent(this,BindService.class);

        btnbinder.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //绑定制定service
                //bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
                //由于是获取context的bindSerVice方法可以显示地写为
                getApplicationContext().bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
            }
        });

        btnunbind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //unbindService(serviceConnection);
                getApplicationContext().unbindService(serviceConnection);
            }
        });

        btnget.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"Service的count值为:"+binder.getCount(),Toast.LENGTH_SHORT).show();
            }
        });
    }
}
3.使用IntentService

1、IntenService文件

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        long endTime=System.currentTimeMillis()+5*1000;
        Log.d("nc", "onStartCommand");
        while (System.currentTimeMillis()<endTime){
            synchronized (this){
                try {
                    wait(endTime-System.currentTimeMillis());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        Log.d("nc", "耗时任务完成================");
    }
}

2、activity文件

public class MainActivity extends AppCompatActivity {
    private Button startService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        startService=findViewById(R.id.btnIntentService);
        final Intent intent=new Intent(this,MyIntentService.class);
        startService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startService(intent);
            }
        });
    }
}
4.跨进程调用Service(AIDL Service)

这里有一个参考文章:

Android Service 远程服务

4.电话管理器(TelephoyManager)

values目录里

<resources>
    <!-- 声明一个名为statusNames的字符串数组 -->
    <string-array name="statusNames">
        <item>设备编号</item>
        <item>软件版本</item>
        <item>网络运营商代号</item>
        <item>网络运营商名称</item>
        <item>手机制式</item>
        <item>蜂窝状态信息</item>
        <item>SIM卡的国别</item>
        <item>SIM卡序列号</item>
        <item>SIM卡状态</item>
    </string-array>
    <!-- 声明一个名为simState的字符串数组 -->
    <string-array name="simState">
        <item>状态未知</item>
        <item>无SIM卡</item>
        <item>被PIN加锁</item>
        <item>被PUK加锁</item>
        <item>被NetWork PIN加锁</item>
        <item>已准备好</item>
        <item>未准备好</item>
        <item>SIM损毁</item>
        <item>读写SIM卡出错</item>
        <item>SIM卡被限制使用</item>
    </string-array>
    <!-- 声明一个名为phoneType的字符串数组 -->
    <string-array name="phoneType">
        <item>未知</item>
        <item>GSM</item>
        <item>CDMA</item>
        <item>SIP</item>
    </string-array>
</resources>

2、list的布局页面

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/values"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

3、Manif

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fengray.myex019aidl">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
</manifest>

4、activity文件

public class MainActivity extends AppCompatActivity {
    private ListView mylist;
    private List<String> statusValues=new ArrayList<>();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestPermissions(new String[] {Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.READ_PHONE_STATE},0x123);
        setContentView(R.layout.activity_main);

        mylist=findViewById(R.id.mylist);

    }

    @SuppressLint("MissingPermission")
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode==0x123 && grantResults[0]== PackageManager.PERMISSION_GRANTED && grantResults[1]==PackageManager.PERMISSION_GRANTED){
            //获取系统的TelephoneyManager对象
            TelephonyManager telephonyManager=(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
            //获取代表状态名称的数组
            String [] statusNames=getResources().getStringArray(R.array.statusNames);
            //获取代表SIM卡状态的数组
            String [] simState=getResources().getStringArray(R.array.simState);
            //获取代表电话网络类型的数组
            String [] phoneType=getResources().getStringArray(R.array.phoneType);
            //获取设备编号
            statusValues.add(telephonyManager.getImei());
            //获取系统平台的版本
            statusValues.add(telephonyManager.getDeviceSoftwareVersion()!=null? telephonyManager.getDeviceSoftwareVersion():"未知");
            //获取网络运营商代号
            statusValues.add(telephonyManager.getNetworkOperator());
            //获取网络运营商名称
            statusValues.add(telephonyManager.getNetworkOperatorName());
            //获取手机网路哦类型
            statusValues.add(phoneType[telephonyManager.getPhoneType()]);
            //获取蜂窝状态信息
            statusValues.add(telephonyManager.getAllCellInfo()!=null? telephonyManager.getAllCellInfo().toString():"未知信息");
            //获取sim卡国别
            statusValues.add(telephonyManager.getSimCountryIso());
            //获取sim序列号
            statusValues.add(telephonyManager.getSimSerialNumber());
            //获取sim卡状态
            statusValues.add(simState[telephonyManager.getSimState()]);
            //获取listView对象
            List<Map<String,String>> status=new ArrayList<>();
            //便利statusValues集合,将statusName,statuesValues数据封装到list集合中
            for (int i=0;i<statusValues.size();i++){
                Map<String,String> map = new HashMap<>();
                map.put("name",statusNames[i]);
                map.put("value",statusValues.get(i));
                status.add(map);
            }

            //使用SimpleAdapter封装list数据
            SimpleAdapter adapter=new SimpleAdapter(this,status,R.layout.line,new String[]{"name","value"},new int[]{R.id.name,R.id.values});
            mylist.setAdapter(adapter);
        }else {
           Toast.makeText(this,"showinfo",Toast.LENGTH_SHORT).show();
        }
    }
}

最终效果
在这里插入图片描述

5.BroadcastReceive广播-发送与接收广播

1、创建FengRayReceiver类继承BroadcastReceiver

public class FengRayReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "接收到的intent的action为:"+intent.getAction()+"\n消息内容是:"+intent.getStringExtra("msg"), Toast.LENGTH_SHORT).show();
    }
}

2、在manifest文件中添加制定name为FengRayReceiver(BroadcastReceive的实现类),并制定接收到intent后的action为:com.fengray.myex020broadcast.action.FENGRAY_BROADCAST

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fengray.myex020broadcast">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".FengRayReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="com.fengray.myex020broadcast.action.FENGRAY_BROADCAST"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

3、创建广播发送者,activity文件

public class MainActivity extends AppCompatActivity {
    private Button sendBroadcast;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sendBroadcast=findViewById(R.id.sendBroadcast);
        sendBroadcast.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent();
                intent.setAction("com.fengray.myex020broadcast.action.FENGRAY_BROADCAST");
                intent.setPackage("com.fengray.myex020broadcast");
                intent.putExtra("msg","今年网络授课");
                sendBroadcast(intent);
            }
        });
    }
}
6.有序广播

1、创建主activity文件,创建intent,并设置action,同时给intent加入消息,并发送有序广播

public class MainActivity extends AppCompatActivity {
    private Button Mybut;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Mybut=findViewById(R.id.Mybut);
        Mybut.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent();
                intent.setAction("com.fengray.myex021broadcast.action.MYACTION");
                intent.setPackage("com.fengray.myex021broadcast");
                intent.putExtra("msg","一则简单消息");
                //发送有序广播
                sendOrderedBroadcast(intent,null);
            }
        });
    }
}

2、创建第一个接收器MyRecever1,并继承BroadcastReceiver

public class MyReceiver1 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "接收到Intent的Action为:"+intent.getStringExtra("msg"), Toast.LENGTH_SHORT).show();
        //创建一个Bundle对象,并存入数据
        Bundle bundle=new Bundle();
        bundle.putString("first","第一个BroadCastReceiver存入的消息");
        //将bundle放入结果中
        setResultExtras(bundle);
        //取消Broadcast
        //abortBroadcast();
    }
}

3、创建第一个接收器MyRecever2,并继承BroadcastReceiver

public class MyReceiver2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle=getResultExtras(true);
        String first=bundle.getString("first");
        Toast.makeText(context, "第一个存入的消息为:"+first, Toast.LENGTH_SHORT).show();
    }
}

4、注册manifest文件,给不同的receiver指定不同的级别(priority)

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fengray.myex021broadcast">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".MyReceiver1">
            <intent-filter android:priority="20">
                <action android:name="com.fengray.myex021broadcast.action.MYACTION"/>
            </intent-filter>
        </receiver>
        <receiver android:name=".MyReceiver2">
            <intent-filter android:priority="0">
                <action android:name="com.fengray.myex021broadcast.action.MYACTION"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>
7.基于Service的音乐播放器

assets资源文件在main上右键new-folder-assets folder
1、布局文件

public class MainActivity extends AppCompatActivity {
    public static final String CTL_ACTION="com.fengray.action.CTL_ACTION";
    public static final String UPDATE_ACTION="com.fengray.action.UPDATE_ACTION";

    //获得界面上的显示歌曲的标题、作者文本框
    private TextView titleTV;
    private TextView authorTv;

    //播放暂停停止按钮
    private ImageButton playbtn,stopbtn;
    private ActivityReceiver activityReceicer;

    //定义音乐的播放状态,0x11代表没有播放,0x12表示正在播放,0x13代表暂停
    int status=0x11;
    String [] titleStrs=new String[]{"心愿","约定","美丽新世界"};
    String [] authorStrs=new String[]{"未知艺术家","周会","伍佰"};



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        playbtn=findViewById(R.id.playbtn);
        stopbtn=findViewById(R.id.stopbtn);

        titleTV=findViewById(R.id.titleTv);
        authorTv=findViewById(R.id.authorTv);

        View.OnClickListener listener=new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //创建intent
                Intent intent=new Intent(CTL_ACTION);
                intent.setPackage("com.fengray.myex022musicplayer");
                switch (view.getId()){
                    //单击播放/暂停按钮
                    case R.id.playbtn:
                        intent.putExtra("control",1);
                        break;
                    case R.id.stopbtn:
                        intent.putExtra("control",2);
                        break;
                }
                sendBroadcast(intent);

            }
        };

        //为两个按钮的单击事件添加监听器
        playbtn.setOnClickListener(listener);
        stopbtn.setOnClickListener(listener);

        activityReceicer=new ActivityReceiver();

        //创建intentFilter,因此在manifest文件中不要在创建service下的intentfilter项了
        IntentFilter filter=new IntentFilter();
        //指定BroadCastRecive监听的Action
        filter.addAction(UPDATE_ACTION);
        //注册broadcastreceiver
        registerReceiver(activityReceicer,filter);
        Intent intent=new Intent(this,MusicService.class);
        //启动后台Service
        startService(intent);



    }
    //自定义的BroadCastReceiver,负责监听从Service穿回来的广播
    class ActivityReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            //获取Intent中的update消息,update代表播放状态
            int update =intent.getIntExtra("update",-1);
            //获取Intent中的current消息,current代表当前正在播放的歌曲
            int current=intent.getIntExtra("current",-1);
            if (current>=0){
                titleTV.setText(titleStrs[current]);
                authorTv.setText(authorStrs[current]);
            }
            switch (update){
                //播放
                case 0x11:
                    playbtn.setImageResource(R.drawable.play);
                    status=0x11;
                    break;
                //暂停
                case 0x12:
                    playbtn.setImageResource(R.drawable.pause);
                    status=0x12;
                    break;
                //暂停状态下设置使用播放图标
                case 0x13:
                    playbtn.setImageResource(R.drawable.play);
                    status=0x13;
                    break;
            }

        }
    }
}

2、创建自己的service类,继承自BroadCastReceiver

public class MusicService extends Service {
    private MyReceiver serviceReceiver;
    private AssetManager assetManager;
    private String [] musics=new String[]{"wish.mp3","promise.mp3","beautiful.mp3"};
    private MediaPlayer mMediaPlayer;
    //当前的状态,0x11表示没有播放,0x12表示正在播放,0x13表示暂停
    private int status=0x11;
    //记录当前正在播放的音乐
    private  int  current=0;
    public MusicService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        assetManager=getAssets();
        //创建BroadcastReceiver
        serviceReceiver=new MyReceiver();
        //创建IntentFilter
        IntentFilter filter=new IntentFilter();
        filter.addAction(MainActivity.CTL_ACTION);
        registerReceiver(serviceReceiver,filter);

        //创建Mediaplayer
        mMediaPlayer=new MediaPlayer();
        //为Mediaplyer指定播放完成时间绑定监听器,这是一个轮播时间,一首播完下一首的事件
        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mediaPlayer) {
                current++;
                if (current>=3){
                    current=0;
                }
                //发送广播通知activity更改文本框

                Intent sendIntent=new Intent(MainActivity.UPDATE_ACTION);
                sendIntent.setPackage("com.fengray.myex022musicplayer");
                sendIntent.putExtra("current",current);
                //发送广播,将被Activity组件中的BroadCastReceiver接收到
                sendBroadcast(sendIntent);
                //准备并播放音乐
                prepareAndPlay(musics[current]);
            }
        });

    }

    class MyReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            int control=intent.getIntExtra("control",-1);
            switch (control){
                //播放或暂停
                case 1:
                    switch (status){
                        //原来处于没有播放状态
                        case 0x11:
                            //准备并播放音乐
                            prepareAndPlay(musics[current]);
                            status=0x12;
                            break;

                        //原来处于播放状态
                        case 0x12:
                            mMediaPlayer.pause();
                            //改变为暂停状态
                            status=0x13;
                            break;

                        //原来处于暂停状态
                        case 0x13:
                            mMediaPlayer.pause();
                            //改变为暂停状态
                            status=0x12;
                            break;
                    }
                    break;
                    //停止声音
                case 2:
                    //如果原来正在播放或暂停
                    if(status==0x12 || status==0x13){
                        //停止播放
                        mMediaPlayer.stop();
                        status=0x11;
                    }
                    break;

            }
            //广播通知activity改变图标、文本框
            Intent sendIntent=new Intent(MainActivity.UPDATE_ACTION);
            sendIntent.setPackage("com.fengray.myex022musicplayer");
            sendIntent.putExtra("update",status);
            sendIntent.putExtra("current",current);
            //发送广播,将被activity组件中的BroadCastReceiver接收到
            sendBroadcast(sendIntent);
        }
    }

    private void prepareAndPlay(String music){
        try {
            //打开指定音乐文件
            AssetFileDescriptor assetFileDescriptor=assetManager.openFd(music);
            mMediaPlayer.reset();
            //使用Mediaplayer加载指定的声音文件
            mMediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),assetFileDescriptor.getStartOffset(),
                    assetFileDescriptor.getDeclaredLength());
            //准备声音
            mMediaPlayer.prepare();
            //播放
            mMediaPlayer.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

3、布局文档

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <TextView
        android:id="@+id/titleTv"
        android:text="title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/authorTv"
        android:text="author"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <ImageButton
        android:id="@+id/playbtn"
        android:src="@drawable/play"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageButton
        android:id="@+id/stopbtn"
        android:src="@drawable/stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>


</LinearLayout>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第18章 疯狂连连看 18.1 连连看游戏简介 18.2 开发游戏界面 18.2.1 开发界面布局 18.2.2 开发游戏界面组件 18.2.3 处理方块之间的连接线 18.3 连连看的状态数据模型 18.3.1 定义数据模型 18.3.2 初始化游戏状态数据 18.4 加载界面的图片 18.5 实现游戏Activity 18.6 实现游戏逻辑 18.6.1 定义GameService组件接口 18.6.2 实现GameService组件 18.6.3 获取触碰点的方块 18.6.4 判断两个方块是否可以相连 18.6.5 定义获取通道的工具方法 18.6.6 没有转折点的横向连接 18.6.7 没有转折点的纵向连接 18.6.8 一个转折点的连接 18.6.9 两个转折点的连接 18.6.10 找出最短距离 18.7 本章小结 第19章 电子拍卖系统 19.1 系统功能简介和架构设计 19.1.1 系统功能简介 19.1.2 系统架构设计 19.2 JSON简介 19.2.1 使用JSON语法创建对象 19.2.2 使用JSON语法创建数组 19.2.3 Java的JSON支持 19.3 发送请求的工具类 19.4 用户登录 19.4.1 处理登录的Servlet 19.4.2 用户登录 19.5 查看流拍物品 19.5.1 查看流拍物品的Servlet 19.5.2 查看流拍物品 19.6 管理物品种类 19.6.1 浏览物品种类的Servlet 19.6.2 查看物品种类 19.6.3 添加种类的Servlet 19.6.4 添加物品种类 19.7 管理拍卖物品 19.7.1 查看自己的拍卖物品的Servlet 19.7.2 查看自己的拍卖物品 19.7.3 添加拍卖物品的Servlet 19.7.4 添加拍卖物品 19.8 参与竞拍 19.8.1 选择物品种类 19.8.2 根据种类浏览物品的Servlet 19.8.3 根据种类浏览物品 19.8.4 参与竞价的Servlet 19.8.5 参与竞价 19.9 权限控制 19.10 本章小结

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值