Android移动软件开发总结

Android实验参考目录

  1. Android生命周期

  2. UI设计-Android计算器

  3. Android UI ListView用法

  4. Intent组件通信

  5. 线程的使用-计时器

  6. 数据的存储与访问sqlite

常用知识点总结

服务绑定bind Service

MathService.java,提供绑定,解绑定,加法的服务

package com.example.pprp.servicebind;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;

public class MathService extends Service {

    private final IBinder mBinder = new LocalBinder();

    public class LocalBinder extends Binder
    {
        MathService getService(){
            return MathService.this;
        }
    }

    public MathService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(this,"本地邦定:mathservice",Toast.LENGTH_SHORT).show();
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Toast.makeText(this,"取消绑定:mathservice",Toast.LENGTH_SHORT).show();
        return false;
    }

    public long Add(long a, long b)
    {
        return a+b;
    }
}

MainActivity.java

bindService()需要参数:ServiceConnection对象,在ServiceConnection对象中可以获得一个mathService对象。依然用Intent来开启service

package com.example.pprp.servicebind;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private Button btn_bind, btn_unbind,btn_calc;
    private TextView tv;

    private MathService mathService;
    private boolean isBind =false;

    private ServiceConnection mCon = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mathService = ((MathService.LocalBinder)iBinder).getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mathService = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main1);
        tv = (TextView)findViewById(R.id.tv);
        btn_bind = (Button)findViewById(R.id.btn_bind);
        btn_calc = (Button)findViewById(R.id.btn_calc);
        btn_unbind  = (Button)findViewById(R.id.btn_unbind);


        btn_bind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!isBind)
                {
                    final Intent serviceIntent = new Intent(MainActivity.this,MathService.class);
                    //startService(serviceIntent);
                    bindService(serviceIntent,mCon, Context.BIND_AUTO_CREATE);
                    isBind = true;
                }
            }
        });
        btn_calc.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mathService == null)
                {
                    tv.setText("UNBIND!");
                    return;
                }
                long a = Math.round(Math.random()*100);
                long b = Math.round(Math.random()*100);
                long result = mathService.Add(a,b);
                String msg = String.valueOf(a)+"+"+String.valueOf(b)+"="+String.valueOf(result);
                tv.setText(msg);
            }
        });
        btn_unbind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(isBind)
                {
                    isBind=false;
                    unbindService(mCon);
                    mathService=null;
                }
            }
        });
    }
}

注册问题:貌似只要是通过new出来的service就不用人工注册了

ThreadService使用总结

MyThreadService.java文件:

构造一个Runnable对象(用于产生随机数),分别在onCreate()中new一个thread,在onStart()中开启thread,在onDestory()中中断thread。

package com.example.pprp.threadtest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

public class MyThreadService extends Service {
    public MyThreadService() {
    }
    private Thread workThread;
    private Runnable backWork = new Runnable() {
        @Override
        public void run() {
            try{
                while(!Thread.interrupted())
                {
                    double randomDouble = Math.random();
                    MainActivity.UpdateGUI(randomDouble);
                    Thread.sleep(1000);
                }
            }catch(InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(this,"oncreate()",Toast.LENGTH_SHORT).show();
        workThread = new Thread(null,backWork,"workThread");
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Toast.makeText(this,"onstart()",Toast.LENGTH_SHORT).show();
        if(!workThread.isAlive())
        {
            workThread.start();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this,"ondestroy()",Toast.LENGTH_SHORT).show();
        workThread.interrupt();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return null;
    }
}

MainActivity.java:

创建一个Runnable对象(用来更新线程,必须使用handler),声明静态TextView, new 一个静态Handler, new一个Intent来开启service, 通过button的事件函数触发事件,分别开启服务和关闭服务。

package com.example.pprp.threadtest;

import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
    static TextView tv;
    Button st,ed;
    private static double randomDouble;
    private static Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main1);
        tv = (TextView)findViewById(R.id.tv);
        st = (Button)findViewById(R.id.btn_start);
        ed = (Button)findViewById(R.id.btn_stop);

        final Intent serviceIntent = new Intent(this,MyThreadService.class);

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

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

    }

    public static void UpdateGUI(double refreshDouble)
    {
        randomDouble = refreshDouble;
        handler.post(refreshRunnable);

    }
    private static Runnable refreshRunnable = new Runnable() {
        @Override
        public void run() {
            tv.setText("output"+String.valueOf(randomDouble));
        }
    };
}

Service用法总结

new一个service出来:

package com.example.pprp.servicetest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

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

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(this,"oncreate()!!",Toast.LENGTH_LONG).show();
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Toast.makeText(this,"onstart()!!",Toast.LENGTH_LONG).show();

        double randomDouble = Math.random();
        String msg = "RANDOM OUOTPUT :" + String.valueOf(randomDouble);
        Toast.makeText(this,msg,Toast.LENGTH_LONG).show();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this,"ondestory()!!",Toast.LENGTH_LONG).show();
    }
}

注册,修改AndroidManifest.xml文件中的内容

<service
    android:name=".MyService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.pprp.servicetest"/>
    </intent-filter>
</service>

在主Activity中的用法:

package com.example.pprp.servicetest;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainA extends AppCompatActivity {
    Button st,ed;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main1);
        st = (Button)findViewById(R.id.btn_start);
        ed = (Button)findViewById(R.id.btn_stop);
       
        final Intent ServiceIntent = new Intent(this,MyService.class);

        st.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startService(ServiceIntent);
            }
        });
        ed.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopService(ServiceIntent);
            }
        });
    }
}

Broadcast Receiver用法

broadcast receiver应该通过new的方式新建,比较好,需要添加几行代码

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.pprp.intenttest">

    <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>
        <activity android:name=".childA" />

        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="tttesttt"/>
            </intent-filter>

        </receiver>
    </application>

</manifest>

MyReceiver.java

package com.example.pprp.intenttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        String msg = intent.getStringExtra("key1");
        Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();
    }
}

onCreate中涉及到的部分:这里tttesttt跟AndroidManifest.xml文件中的一致

   		String UNIQUE_STRING="tttesttt";   
		btn_broad.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(UNIQUE_STRING);
                intent.putExtra("key1","thisis1test");
                sendBroadcast(intent);
            }
        });

Intent使用注意事项

首先,应该使用new Activity的方法来创建子程序,尽量不要手动创建,如果手动创建还需在AndroidManifest.xml文件中添加相应的部分
然后,调用子activity的时候,如果用startActivityForResult,才会有返回值,才能写onActivityResult函数;如果用startAcitivity则不会运行该函数。

1. Intent使用方法

如果发送Intent是:

Uri data = Uri.parse("message string");
Intent intent = new Intent(null,data);
setResult(intent);

那么解析的时候应该是:(父部分的处理)

Uri uridata = data.getData();
tv.setText(uridata.toString());

如果发送Intent是:

Intent intent = new Intent();
intent.putExtra("Name",et.getText().toString());

那么应该用以下方式进行解析:

Uri uridata = data.getData();
tv.setText(uridata.getStringExtra("Name"));

2. 父activity得到子activity的消息

父Activity在btn事件函数中调用子Activity:

Intent intent = new Intent(MainActivity.this,Subsub.class);
startActivityForResult(intent,SUB);

子Activity在btn事件函数中进行Intent发送:

 Uri data = Uri.parse(et.getText().toString());
 Intent result = new Intent(null,data);
 setResult(RESULT_OK,result);
 finish();

父Activity中的onActivityResult函数中的内容,用于处理子Activity发送内容

if(requestCode == SUB)
{
    if(resultCode == RESULT_OK)
    { 
        Uri uriData = data.getData();
        System.out.println("result: " + uriData.toString());
        tvs.setText(uriData.toString());
    }
}

3. 子activity得到父activity的内容

父activity:

Intent intent = new Intent(MainActivity.this,ChildActivity.class);
intent.putExtra("Name",et.getText().toString());
startActivityForResult(intent,SUBACTIVITY);

子Activity进行接收:

Intent data = getIntent();
tv.setText(data.getStringExtra("Name"));

ListView用法总结

提前需要做的工作:在res目录下new一个menu文件,添加一个Item

主要的用法:

//声明ArrayList, ArrayAdapter
    ListView lv;
    ArrayList<String> list;
    ArrayAdapter<String> adp;

//在onCreate函数中进行如下操作:
    lv = (ListView)findViewById(R.id.lv);
    list = new ArrayList<String>();
    adp = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,list);

    lv.setAdapter(adp);

//btn事件函数操作:
    String ans = "";
    ans += et_cls.getText().toString();
    ans += et_stuno.getText().toString();
    ans += et_name.getText().toString();
    ArrayAdapter temp_adp = (ArrayAdapter) lv.getAdapter();
    temp_adp.add(ans);

//listView的事件函数:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, final int pos, long l) {
                if(l > 0)
                {
                    System.out.println("test");
                    PopupMenu popup = new PopupMenu(MainActivity.this,view);
                    popup.getMenuInflater().inflate(R.menu.del,popup.getMenu());
                    popup.show();
                    popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            switch(item.getItemId())
                            {
                                case R.id.del:
                                    ArrayAdapter temp = (ArrayAdapter)lv.getAdapter();
                                    temp.remove(temp.getItem(pos));
                                    return true;
                                default:
                                    return false;
                            }
                        }
                    });
                }
            }
        });

完整代码:

btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        String msg = et.getText().toString();
        ArrayAdapter tp = (ArrayAdapter)lv.getAdapter();
        tp.add(msg);
    }
});
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, final int pos, long l) {
        if(l > 0)
        {
            PopupMenu popup = new PopupMenu(MainActivity.this,view);
            popup.getMenuInflater().inflate(R.menu.menu1,popup.getMenu());
            popup.show();
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    if(item.getItemId() == R.id.ddelete)
                    {                    			Toast.makeText(MainActivity.this,"ddlete",Toast.LENGTH_SHORT).show();
 						ArrayAdapter<String> tmp = (ArrayAdapter)lv.getAdapter();
                        tmp.remove(tmp.getItem(pos));
                    }
                    else if(item.getItemId() == R.id.oopen)
                    {
                        Toast.makeText(MainActivity.this,"oopen",Toast.LENGTH_SHORT).show();
                   }
                   else if(item.getItemId() == R.id.nnew)
                   {
                        Toast.makeText(MainActivity.this,"nnew",Toast.LENGTH_SHORT).show();
                    }
                    return false;
                }
            });
        }
    }
 });

spinner 用法

spn = (Spinner)findViewById(R.id.spinner);
List<String> list = new ArrayList<String>();
list.add(0,"test1");
list.add(1,"test2");
list.add(2,"test3");
ArrayAdapter<String> adp = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,list);

adp.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

spn.setAdapter(adp);

spn.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
	@Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
        if(l > 0)
        {           tv.setText(adapterView.getItemAtPosition(i).toString());
        }
    }
    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {

    }
});

ArrayAdapter的用法总结

lv = (ListView)findViewById(R.id.lv);
list = new ArrayList<String>();
adp = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,list);

ArrayAdapter tp = (ArrayAdapter)lv.getAdapter();
tp.add("your String");
tp.remove(tp.getItem(pos));

遇到的问题

Installation failed with message Invalid File

这个问题详细报错如下:

Installation failed with message Invalid File: 

C:\Android\workspace\Calculator\app\build\intermediates\split-apk\debug\slices\slice_9.apk. 

It is possible that this issue is resolved by uninstalling an existing version of the apk if it is present, and then re-installing.

通过谷歌搜索到stackoverflow上的内容:

其中最好的解决方案如下:

Click Build tab ---> Clean Project
Click Build tab ---> Build APK
Run.

亲测有效

版本不匹配导致的gradle编译出错

这时候应该打开GradleScripts目录下的 build.gradle(Module:app),
然后进行修改:

android {
    compileSdkVersion 26
    buildToolsVersion "27.0.3"
    defaultConfig {
        applicationId "com.example.administrator.calculator"
        minSdkVersion 25
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

修改:minSdkVersion 和 compileSdkVersion 等,到你想要的版本

Error:Failed to find target with hash string 'android-26' in: D:\programFile

国内无法访问google的关于android的库,可以选择国内的镜像网站(百度经验中就有),也可以使用VPN(百度搜索android studio VPN)就可以了,
除此以外有时候真的还是要靠运气

需要注意:

版本高的API兼容版本低的API,反之不可行。

  • 模拟器已经打开但是运行时找不到对应的模拟器

找到模拟器的adb文件,如果用的是Android原装adb:

cd C:\Android\sdk\platform-tools
adb connect 127.0.0.1:62001

即可。

如果使用的是夜神模拟器:

cd ../..
cd "Program Files (x86)"/Nox/bin
nox_adb connect 127.0.0.1:62001

即可。

sqlite3 进入运行时遇见报错:

error: no devices/emulators found

解决方案:首先需要明确,必须要先打开模拟器,然后使用哪个模拟器,就要找对应模拟器的adb可执行文件:

如果用的是Android的原装sdk中的模拟器:

cd C:\Android\sdk\platform-tools
adb shell

如果用的是夜神模拟器:

cd "Program Files (x86)"/Nox/bin
nox_adb shell

即可。

sqlite3中进入shell以后,如果遇到以下报错:

mkdir failed for , Read-only file system

可以用以下命令进行解决:

adb shell 
mount -o remount rw /

Android Studio快捷键

其他用法

快捷键 说明
Ctrl+D 复制一行
Ctrl+Y 删除当前行
Ctrl+G 快捷定位某行
Ctrl+/ 注释一行
Ctrl+E 查看最近打开的文件
Ctrl+N 查找类名,文件名
Ctrl+O 显示父类中可覆写方法(常用)
Ctrl+F 类内搜索
Ctrl+R 查找替换
Ctrl+J 自动代码(自动提示)
Ctrl+H 显示类的继承结构
Ctrl+W 选中代码,类似双击效果
Ctrl+shift+"+/-" 折叠,展开代码块
Alt+Q 上下文信息
Ctrl+Alt+Shift+f8 临时断电
Ctrl+Shift+J 合并行和文本,例如多行注释,if(){}
Alt+Shift+Up/Down 移动上下行
shift+f6 全局重命名(或者quick fix)

Android 界面设计实用工具

颜色代码

常用颜色搭配

Android常用Theme

Android美化

posted @ 2018-09-04 09:13  pprp  阅读(1468)  评论(0编辑  收藏  举报