遇到的问题:
1.新建Activity,无法引入新的xml文件 setContentView(R.layout.myActivity)
2.android R.id找不到资源的问题
3.OKHttp无法访问http请求
4.安卓10无法对SD卡内容进行读写
5.存储目录
6.播放本地音乐
7.真机调试
8.更改app图标
9.安卓UI
10.OKHttp请求中使用Toast报错
11.okHttp post 发送语音文件
12.设置圆角按钮
13.封装toast方法
14.设置欢迎页、解决欢迎页暂时白屏问题
15.post请求提交表单
16.fragment中获取控件
17.fragment中更新UI报错 Only the original thread that created a view hierarchy can touch its views
18.BottomNavigationView 底部菜单多于3时,底部菜单显示不全
19.隐藏AppCompatActivity的默认标题栏
20.fragment中使用RecyclerView(RecyclerView代替原始控件ListView)
21.okhttp get请求带参数
22.gson 解析json数据
23.Only the original thread that created a view hierarchy can touch its views.(okhttp中更新视图报错)
24.RecyclerView 数据更新
25.输入法把底部菜单栏顶到上面
解决办法:
1.重启android studio解决,当然不是根本解决办法,但是这个最快最简单。
2.同上,重启androird studio即可解决
安卓10 在以往的读写权限之外还需要加入如下设置:①在 AndroidManifest.xml 中加入 android:requestLegacyExternalStorage=“true”
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 读取SDCard数据权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
5.存储路径详解
链接
6.本地新建raw文件,raw文件下放音频文件(notice.mp3),使用MediaPlayer播放。
//播放按钮
class PlayRecordListener implements View.OnClickListener{
@Override
public void onClick(View v) {
MediaPlayer mPlayer = new MediaPlayer();
AssetFileDescriptor file = mContext.getResources().openRawResourceFd(R.raw.notice);
try{
mPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
mPlayer.prepare();
mPlayer.start();
}catch (IOException e){
Log.e("fail","播放失败");
}
}
}
7.真机调试
1.打开开发者选项
2.打开USB调试
3.下载 Google USB driver file->setting->android SDK->SDK Tools->下载Google USB driver
4.run 选择真机
5.允许安装
更多参见网址:
链接链接
8.更改app图标
链接
AndroidManifest.xml文件中的其中icon 和 roundIcon为app的图标设置,放置新的图标到drawable中,不要直接替换或删除原本的图标。
<application
android:allowBackup="true"
android:icon="@drawable/icon"
android:networkSecurityConfig="@xml/network_config"
android:label="@string/app_name"
android:roundIcon="@drawable/icon_round"
android:supportsRtl="true"
android:requestLegacyExternalStorage="true"
android:theme="@style/AppTheme"
tools:targetApi="n">
9.安卓UI
10.OKHttp中get请求调用Toast
提示错误信息:Can’t toast on a thread that has not called Looper.prepare()
Looper.prepare();
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
Looper.loop();
13.封装toast
1.新建toastUtils
2.新建APP
3.mainfests调用App,实例化toast对象
4.使用 App.toast.showToastMessage()
14.设置欢迎页
欢迎页空白,添加style样式文件,并应用到welcomeActivity页面
styles.xml
<style name="FullScreenWithBackground" parent="@style/Theme.AppCompat.Light">
<item name="android:windowNoTitle">true</item>//无标题
<item name="android:windowActionBar">false</item>//无ActionBar
<item name="android:windowFullscreen">true</item>//全屏即无通知栏
<item name="android:windowContentOverlay">@null</item>//是否有遮盖
<item name="android:windowBackground">@mipmap/welcome</item>
</style>
mainfests.xml
<!--为解决欢迎页空白情况,添加style-->
<activity android:name=".Activity.WelcomeActivity" android:theme="@style/FullScreenWithBackground">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
链接
普通post请求报错 “Unsupported Media Type”,“message”:“Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported”,“path”:"/wx/login"
这是因为android的默认Media Type是"application/x-www-form-urlencoded;charset=UTF-8",而后台接口要的是“application/json; charset=utf-8”格式。
关键代码:设置requestBody的content-type
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
JSONObject json = new JSONObject();
json.put("wxUserAccount","13243210010");
json.put("wxUserPassword","123456aaa");
RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json.toString());
完整post请求如下:
new Thread(new Runnable() {//在这个方法中同样还是先开启了一个子线程
@Override
public void run() {
try {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
JSONObject json = new JSONObject();
json.put("wxUserAccount","13243210010");
json.put("wxUserPassword","123456aaa");
String http_url = "http://192.168.1.50:8080/v1/api/wx/login";
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json.toString());
Log.i("respBody", String.valueOf(requestBody));
Request request = new Request.Builder()
.url(http_url)
.post(requestBody)
.build();
Response response = client.newCall(request).execute();//接收服务器返回的数据
String responseData = response.body().string();//得到具体数据
Log.i("resp", responseData);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
16.fragment中获取控件
对比在Activity中获取控件直接通过findViewById(),在fragment中需要添加View名称
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
// 获取控件
test_btn= (Button) root.findViewById(R.id.test_btn);
return root;
}
链接
17.fragment中更新UI报错
链接
android中相关的view和控件不是线程安全的,我们必须单独做处理。这里借此引出Handler的使用。
package djx.android;
import djx.downLoad.DownFiles;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class downLoadPractice extends Activity {
private Button button_submit=null;
private TextView textView=null;
private String content=null;
private Handler handler=null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//创建属于主线程的handler
handler=new Handler();
button_submit=(Button)findViewById(R.id.button_submit);
textView=(TextView)findViewById(R.id.textView);
button_submit.setOnClickListener(new submitOnClieckListener());
}
//为按钮添加监听器
class submitOnClieckListener implements OnClickListener{
@Override
public void onClick(View v) {
//本地机器部署为服务器,从本地下载a.txt文件内容在textView上显示
final DownFiles df=new DownFiles("http://192.168.75.1:8080/downLoadServer/a.txt");
textView.setText("正在加载......");
new Thread(){
public void run(){
content=df.downLoadFiles();
handler.post(runnableUi);
}
}.start();
}
}
// 构建Runnable对象,在runnable中更新界面
Runnable runnableUi=new Runnable(){
@Override
public void run() {
//更新界面
textView.setText("the Content is:"+content);
}
};
}
18.BottomNavigationView 底部菜单多于3时,底部菜单显示不全
设置属性:app:labelVisibilityMode=“labeled” 即可。
更多相关知识:
链接
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:labelVisibilityMode="labeled"
app:menu="@menu/bottom_nav_menu" />
19.隐藏AppCompatActivity的默认标题栏
在onCreate()之后设置属性 getSupportActionBar().hide(); 即可。
链接
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide(); // 隐藏AppCompatActivity的标题栏
20.fragment中使用RecyclerView
链接
1.添加依赖
implementation 'com.android.support:recyclerview-v7:29.0.0'
2.新建ListView,列表容器
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/collect_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
3.新建list-item,列表项此为列表项中每一项的样式文件
4.自定义实体类 Entity文件下新建实体类
- 设置RecyclerView的适配器 Adapter文件下新建适配器
6.解析数据 Bean文件下根据返回json数据结构解析数据
7.应用
通过okhttp获取到数据,在调用Recycler方法
if(gasDataBean.getCode() == 200) {
for (int i = 0; i < gasDataBean.getData().getList().size(); i++) {
GasDataBean.DataBean.ListsBean b = gasDataBean.getData().getList().get(i);
GasEntity gasEntity = new GasEntity();
gasEntity.setCh4(b.getCh4());
gasEntity.setCo(b.getCo());
gasEntity.setO2(b.getO2());
gasEntity.setHumidity(b.getHumidity());
gasEntity.setTemperature(b.getTemperature());
gasEntity.setStaff_name(b.getStaffname());
gasEntity.setGroup_name(b.getGroupName());
gasEntity.setTemppositionname(b.getTemppositionname());
gasEntity.setCreatetime(b.getCreatetime());
gasEntityArrayList.add(gasEntity);
}
handler.post(runnableUi);
}
private void initRecyclerView() {
//获取RecyclerView
mCollectRecyclerView=(RecyclerView)gas.findViewById(R.id.collect_recyclerView);
//创建adapter
mCollectRecyclerAdapter = new GasListAdapter(getActivity(), gasEntityArrayList);
//给RecyclerView设置adapter
mCollectRecyclerView.setAdapter(mCollectRecyclerAdapter);
//设置layoutManager,可以设置显示效果,是线性布局、grid布局,还是瀑布流布局
//参数是:上下文、列表方向(横向还是纵向)、是否倒叙
mCollectRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
//设置item的分割线
mCollectRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),DividerItemDecoration.VERTICAL));
//RecyclerView中没有item的监听事件,需要自己在适配器中写一个监听事件的接口。参数根据自定义
mCollectRecyclerAdapter.setOnItemClickListener(new GasListAdapter.OnItemClickListener() {
@Override
public void OnItemClick(View view, GasEntity data) {
//此处进行监听事件的业务处理
Toast.makeText(getActivity(),"我是item",Toast.LENGTH_SHORT).show();
}
});
}
21.okhttp get请求带参数
Request.Builder reqBuild = new Request.Builder();
HttpUrl.Builder urlBuilder =HttpUrl.parse("https://api.weibo.com/2/users/show.json")
.newBuilder();
urlBuilder.addQueryParameter("access_token", oauth2AccessToken.getToken());
urlBuilder.addQueryParameter("uid", oauth2AccessToken.getUid());
reqBuild.url(urlBuilder.build());
Request request = reqBuild.build();
23.Only the original thread that created a view hierarchy can touch its views.(okhttp中更新视图报错)
使用handler
// 声明变量
private Handler handler;
// 初始化 onCreate中
handler = new Handler();
// 调用 okhttp中
handler.post(runnableUi);
// 构建Runnable对象,在runnable中更新界面
private Runnable runnableUi =new Runnable(){
@Override
public void run() {
//更新界面
initRecyclerView();
}
};
24.RecyclerView 数据更新
查询功能,先清空列表,后查询
code == 111 清空列表
gasEntityArrayList.clear();
mCollectRecyclerAdapter.notifyDataSetChanged();
dataList.clear(); //去掉之前的数据
dataList.add(weather); //添加新的Weather对象
mAdapter.notifyDataSetChanged(); // 清空recyclerView
25.输入法把底部菜单栏顶到上面
android:windowSoftInputMode="adjustPan"
android:windowSoftInputMode="adjustPan"
<activity
android:name=".IndexActivity"
android:windowSoftInputMode="adjustPan"
android:label="@string/title_activity_index"/>