1.Fragment
可以嵌入活动当中的UI片段。
1.碎片的通信
FragmentManager提供一个finViewById,专门从布局文件中获取碎片的实例
2.碎片的生命周期
1.状态
(1)运行状态:可见
(2)暂停状态:被覆盖但部分可见
(3)停止状态:完全不可见
(4)销毁状态:被移除
2.回调
(1)onAttach()。碎片和活动建立关联。
(2)onCreateView()。碎片创建视图时调用。
(3)onActivityCreated()。确保与碎片相关联的活动一定已经创建完毕的时候调用。
(4)onDestory()。当与碎片关联的视图被移除的时候调用。
(5)onDetach()。当碎片与活动解除关联的时候调用。
3.动态加载布局
使用限定符匹配对应的平板和手机情况。
4.系统通知
点击查看代码
package com.example.notificationtest;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
final String CHANNEL_ID = "channel_id_1";
final String CHANNEL_NAME = "channel_name_1";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button sendNotice = (Button) findViewById(R.id.send_notice);
sendNotice.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onClick(View v) {
Context context = getBaseContext();
Intent intent = new Intent(MainActivity.this,MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(MainActivity.this,0,intent,0);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//Notification notification = new Notification();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR_0_1) {
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID,CHANNEL_NAME,NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(notificationChannel);
}
Notification notification;
notification = new NotificationCompat.Builder(MainActivity.this,CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentTitle("通知标题")
.setAutoCancel(true)
.setContentText("This is a notification This is a notificationThis is a notificationThis is a notificationThis is a notificationThis is a notificationThis is a notificationThis is a notificationThis is a notificationThis is a notificationThis is a notificationThis is a notificationThis is a notification")
.setContentIntent(pi)
.setVibrate(new long[]{0,1000,1000,1000})
.setWhen(System.currentTimeMillis())
.build();
manager.notify(0,notification);
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.notificationtest">
<uses-permission android:name="android.permission.VIBRATE" />
<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/Theme.NotificationTest">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
2.Service
1.服务的生命周期
生命周期回调方法:
(1)onCreate()
(2)onStartCommand()
(3)onBind()
(4)onDestory
调用startService()方法后,对应服务就会启动,并回调onStartCommand()方法,服务没有创建,onCreate()就会先于onStartCommand()方法执行,调用stopService,unBindService方法,执行onDestory方法。
2.前后台服务
点击查看代码
package com.example.servicetest;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import androidx.annotation.Nullable;
public class MyIntentService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public MyIntentService(String name) {
super(name);
}
public MyIntentService(){
super(null);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.d("MyIntentService", "Thread id is" + Thread.currentThread().getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}
package com.example.servicetest;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
public class MyService extends Service {
public MyService() {
}
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder {
public void startDownload() {
Log.d("MyService", "startDownload executed");
}
public int getProgress() {
Log.d("MyService", "getProgress executed");
return 0;
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService","onCreate executed");
Intent intent = new Intent(MyService.this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0, intent, 0);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel("channel_id","channel_name",NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(notificationChannel);
Notification notification = new NotificationCompat.Builder(MyService.this,"channel_id")
.setContentTitle("This is content title")
.setContentText("This is content text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
.setContentIntent(pi)
.build();
startForeground(1, notification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService","onStartCommand executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyService","onDestroy executed");
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mBinder;
}
}
package com.example.servicetest;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyService.DownloadBinder mDownloadBinder;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mDownloadBinder = (MyService.DownloadBinder) service;
mDownloadBinder.startDownload();;
mDownloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startService = (Button) findViewById(R.id.startService);
Button stopService = (Button) findViewById(R.id.stopService);
Button bindService = (Button) findViewById(R.id.bindService);
Button unbindService = (Button) findViewById(R.id.unbindService);
Button startIntentService = (Button) findViewById(R.id.startIntentService);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
startIntentService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.startService:
Intent startIntent = new Intent(this,MyService.class);
startService(startIntent);
break;
case R.id.stopService:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
case R.id.bindService:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, mConnection, BIND_AUTO_CREATE);
break;
case R.id.unbindService:
unbindService(mConnection);
break;
case R.id.startIntentService:
Log.d("MainActivity","Thread id is" + Thread.currentThread().getId());
Intent intentService = new Intent(this, MyIntentService.class);
startService(intentService);
break;
default:
break;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.servicetest">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<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/Theme.ServiceTest">
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
<service android:name=".MyIntentService" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
3.多线程
1.异步消息处理机制
异步消息处理:由四个部分组成,Message、Hanlder、MessageQueue、Looper。
(1)Message:线程之间传递消息,用于在不同线程之间交换数据。
(2)Handler:用于发送和处理消息,sendMessgae(),经过一系列的处理之后,传递到HandleMessgae中。
(3)MessageQueue:用于存放所有通过Handler发送的消息,每个线程只会有一个MessageQueue对象。
(4)Looper:每个线程中的MessageQueue的关机,调用Looper中的loop()方法后,会进入到一个无限循环当中,发现MessageQueue中存在一条消息,就会将其取出,传递到HanleMessage方法中。每个线程中也只会有一个looper对象。
2.AsyncTask使用
重新其中方法可完成对应的任务调度
(1)onProExecute():在后台任务开始执行前调用,用于进行界面上的初始化操作。
(2)doInBackground(Params...):方法中所有代码都会在子线程中执行,不可以进行UI的操作
(3)onProgressUpdate(Progress...):后台调用了publishProgress(Progress...)方法后,此方法就会调用,返回的数据作为参数传递,可以进行Ui操作。
(4)onPostExecute(Result):后台任务执行完毕之后,并执行return 返回时,调用此方法,返回数据作为参数传递到此方法中,可以利用返回数据做UI操作。
4.接入三方SDK实现and ServiceTest
点击查看代码
package com.example.servicebestpratice;
public interface DownloadListener {
void onProgress(int progress);
void onSuccess();
void onFailed();
void onPaused();
void onCancled();
}
package com.example.servicebestpratice;
import java.io.File;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
public class DownloadService extends Service {
private DownloadTask mDownloadTask;
private String downloadUrl;
private NotificationManager mManager;
private DownloadListener mListener = new DownloadListener() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onProgress(int progress) {
getNotificationManager().notify(1,getNotification("Downloading...",progress));
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onSuccess() {
mDownloadTask = null;
stopForeground(true);
getNotificationManager().notify(1,getNotification("Download Success", -1));
Toast.makeText(DownloadService.this, "Download Success", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailed() {
mDownloadTask = null;
Toast.makeText(DownloadService.this, "Download Failed", Toast.LENGTH_SHORT).show();
}
@Override
public void onPaused() {
mDownloadTask = null;
Toast.makeText(DownloadService.this, "Download Paused", Toast.LENGTH_SHORT).show();
}
@Override
public void onCancled() {
mDownloadTask = null;
Toast.makeText(DownloadService.this, "Download Cancled", Toast.LENGTH_SHORT).show();
}
};
public DownloadService() {
}
private DownloadBinder mBinder = new DownloadBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
class DownloadBinder extends Binder {
@RequiresApi(api = Build.VERSION_CODES.O)
public void startDownload(String url) {
if (mDownloadTask == null) {
downloadUrl = url;
mDownloadTask = new DownloadTask(mListener);
mDownloadTask.execute(downloadUrl);
mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel("channelId","channelName",NotificationManager.IMPORTANCE_HIGH);
mManager.createNotificationChannel(notificationChannel);
startForeground(1,getNotification("Download...",0));
Toast.makeText(DownloadService.this, "Downloading...",Toast.LENGTH_SHORT).show();
}
}
public void pauseDownload() {
if (mDownloadTask != null) {
mDownloadTask.pauseDownload();
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void cancelDownload() {
if (mDownloadTask != null) {
mDownloadTask.cancelDownload();
} else {
if (downloadUrl != null) {
String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
File file = new File(directory + fileName);
if (file.exists()) {
file.delete();
}
getNotificationManager().cancel(1);
stopForeground(true);
Toast.makeText(DownloadService.this, "Canceled", Toast.LENGTH_SHORT).show();
}
}
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private NotificationManager getNotificationManager() {
return mManager;
}
private Notification getNotification(String title, int progress) {
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"channelId");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));
builder.setContentIntent(pi);
builder.setContentTitle(title);
if (progress > 0) {
builder.setContentText(progress + "%");
builder.setProgress(100,progress,false);
}
return builder.build();
}
}
package com.example.servicebestpratice;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import android.os.AsyncTask;
import android.os.Environment;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class DownloadTask extends AsyncTask<String, Integer, Integer> {
public static final int TYPE_SUCCESS = 0;
public static final int TYPE_FAILED = 1;
public static final int TYPE_PAUSED = 2;
public static final int TYPE_CANCELED = 3;
private DownloadListener mListener;
private boolean isCanceled = false;
private boolean isPaused = false;
private int lastProgress;
public DownloadTask(DownloadListener listener) {
this.mListener = listener;
}
@Override
protected Integer doInBackground(String... strings) {
InputStream is = null;
RandomAccessFile savedFile = null;
File file = null;
try {
long downloadedLength = 0;
String downloadUrl = strings[0];
String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
file = new File(directory + fileName);
if (file.exists()) {
downloadedLength = file.length();
}
long contentLength = getContentLength(downloadUrl);
if (contentLength == 0) {
return TYPE_FAILED;
} else if (contentLength == downloadedLength) {
return TYPE_SUCCESS;
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.addHeader("RANGE","bytes=" + downloadedLength + "-")
.url(downloadUrl)
.build();
Response response = client.newCall(request).execute();
if (response != null) {
is = response.body().byteStream();
savedFile = new RandomAccessFile(file, "rw");
savedFile.seek(downloadedLength);
byte[] b = new byte[1024];
int total = 0;
int len;
while ((len = is.read(b))!=-1) {
if (isCanceled) {
return TYPE_CANCELED;
} else if (isPaused) {
return TYPE_PAUSED;
} else {
total += len;
savedFile.write(b,0,len);
int progress = (int)((total+downloadedLength) * 100 / contentLength);
publishProgress(progress);
}
}
response.close();
return TYPE_SUCCESS;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (savedFile != null) {
savedFile.close();
}
if (isCanceled && file != null) {
file.delete();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
int progress = values[0];
if (progress > lastProgress) {
mListener.onProgress(progress);
lastProgress = progress;
}
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
switch (integer) {
case TYPE_CANCELED:
mListener.onCancled();
break;
case TYPE_SUCCESS:
mListener.onSuccess();
break;
case TYPE_PAUSED:
mListener.onPaused();
break;
case TYPE_FAILED:
mListener.onFailed();
default:
break;
}
}
private long getContentLength(String downloadUrl) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(downloadUrl)
.build();
Response response = client.newCall(request).execute();
if (response != null && response.isSuccessful()) {
long contentLength = response.body().contentLength();
response.close();
return contentLength;
}
return 0;
}
public void pauseDownload() {
isPaused = true;
}
public void cancelDownload() {
isCanceled = true;
}
}
package com.example.servicebestpratice;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private DownloadService.DownloadBinder mDownloadBinder;
private LocationClient mLocationClient;
private MyLocationListener mListener = new MyLocationListener();
private TextView positionText;
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mDownloadBinder = (DownloadService.DownloadBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
public class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
double latitude = bdLocation.getLatitude();
double longitude = bdLocation.getLongitude();
float radius = bdLocation.getRadius();
String coorType = bdLocation.getCoorType();
int errorCode = bdLocation.getLocType();
positionText.setText(latitude + " ++ " +longitude + " ++ " +radius + " ++ " +coorType + " ++ ");
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLocationClient = new LocationClient(getApplicationContext());
mLocationClient.registerLocationListener(mListener);
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
option.setScanSpan(1000);
mLocationClient.setLocOption(option);
mLocationClient.start();
Button startDownload = (Button) findViewById(R.id.start_download);
Button pauseDownload = (Button) findViewById(R.id.pause_download);
Button cancelDownload = (Button) findViewById(R.id.cancel_download);
positionText = (TextView) findViewById(R.id.position_text_view);
startDownload.setOnClickListener(this);
pauseDownload.setOnClickListener(this);
cancelDownload.setOnClickListener(this);
Intent intent = new Intent(this, DownloadService.class);
startService(intent);
bindService(intent, mConnection, BIND_AUTO_CREATE);
if (ContextCompat
.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
}
}
@SuppressLint("NonConstantResourceId")
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onClick(View v) {
if (mDownloadBinder == null) {
return;
}
switch (v.getId()) {
case R.id.start_download:
String url = "https://raw.githubusercontent.com/guolindev/eclipse/master/eclipse-inst-win64.exe";
mDownloadBinder.startDownload(url);
break;
case R.id.pause_download:
mDownloadBinder.pauseDownload();
break;
case R.id.cancel_download:
mDownloadBinder.cancelDownload();
break;
default:
break;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "failed", Toast.LENGTH_SHORT).show();
finish();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConnection);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/start_download"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Downlaod" />
<Button
android:id="@+id/pause_download"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Pause Downlaod" />
<Button
android:id="@+id/cancel_download"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Cancel Downlaod" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/position_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
plugins {
id 'com.android.application'
}
android {
compileSdk 31
defaultConfig {
ndk {
// 设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so)
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64"
}
applicationId "com.example.servicebestpratice"
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', includes: ['*.jar'])
implementation("com.squareup.okhttp3:okhttp:4.2.0")
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'com.baidu.lbsyun:BaiduMapSDK_Map:7.4.0'
implementation 'com.baidu.lbsyun:BaiduMapSDK_Util:7.4.0'
implementation 'com.baidu.lbsyun:BaiduMapSDK_Search:7.4.0'
implementation 'com.baidu.lbsyun:BaiduMapSDK_Location:9.1.8'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}