Android中使用GoogleMap的地理位置服务
写在前面:android中使用地理位置功能,可以借助Google给我们提供的框架,要是有地理位置功能,你需要引用Google Play Services,请在sdk manager中下载。
如果你还要使用地图功能,请到google官网申请api-key
如果要看官方例子可以到https://github.com/googlesamples/android-play-location.git下载
使用Google地理服务都需要如下,
引用Google Play Services
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
声明权限
定位功能涉及到权限,下面2选1;
ACCESS_COARSE_LOCATION 粗略位置
或者ACCESS_FINE_LOCATION精确位置
1.基本使用,获取上一次的位置。
/**
* 构建位置服务客户端对象
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
} /**
*在onStart中使用客户端连接GooglePlay Service
*/
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
} /**
* 离开界面时,断开连接
*/
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
} /**
* 连接GooglePlay Service成功后,可以在回调方法中获取上一次的位置
*/
@Override
public void onConnected(Bundle connectionHint) {
// Provides a simple way of getting a device's location and is well suited for
// applications that do not require a fine-grained location and that do not need location
// updates. Gets the best and most recent location currently available, which may be null
// in rare cases when a location is not available.
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
mLatitudeText.setText(String.format("%s: %f", mLatitudeLabel,
mLastLocation.getLatitude()));
mLongitudeText.setText(String.format("%s: %f", mLongitudeLabel,
mLastLocation.getLongitude()));
} else {
Toast.makeText(this, R.string.no_location_detected, Toast.LENGTH_LONG).show();
}
} /**
* 连接失败
* @param result
*/
@Override
public void onConnectionFailed(ConnectionResult result) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
} /**
* 连接被暂停了,重新连接
* @param cause
*/
@Override
public void onConnectionSuspended(int cause) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
2.实时刷新最新位置,获取最新位置信息;
连接成功后,在回调方法中执行位置监听;首先配置位置请求参数,创建位置请求对象,后调用监听。
/**
* The desired interval for location updates. Inexact. Updates may be more or less frequent.
*/
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = ; /**
* The fastest rate for active location updates. Exact. Updates will never be more frequent
* than this value.
*/
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / ; /**
* 创建位置请求对象mLocationRequest,封装监听参数
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest(); // Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); // Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* 开始监听位置变化
*/
protected void startLocationUpdates() {
// The final argument to {@code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* 回调方法中获取到改变的最新位置
*/
@Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
Toast.makeText(this, getResources().getString(R.string.location_updated_message),
Toast.LENGTH_SHORT).show();
}
3.获取到位置的经纬度后,可以将其转为地址信息。
这里使用开启服务来解析经纬度。
if (mLastLocation != null) {
// Determine whether a Geocoder is available.
if (!Geocoder.isPresent()) {
Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
return;
}
// It is possible that the user presses the button to get the address before the
// GoogleApiClient object successfully connects. In such a case, mAddressRequested
// is set to true, but no attempt is made to fetch the address (see
// fetchAddressButtonHandler()) . Instead, we start the intent service here if the
// user has requested an address, since we now have a connection to GoogleApiClient.
if (mAddressRequested) {
startIntentService(); //开启服务解析经纬度
}
}
使用IntentService
public class FetchAddressIntentService extends IntentService {
private static final String TAG = "FetchAddressIS"; /**
* The receiver where results are forwarded from this service.
*/
protected ResultReceiver mReceiver; /**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public FetchAddressIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
} /**
* Tries to get the location address using a Geocoder. If successful, sends an address to a
* result receiver. If unsuccessful, sends an error message instead.
* Note: We define a {@link android.os.ResultReceiver} in * MainActivity to process content
* sent from this service.
*
* This service calls this method from the default worker thread with the intent that started
* the service. When this method returns, the service automatically stops.
*/
@Override
protected void onHandleIntent(Intent intent) {
String errorMessage = ""; mReceiver = intent.getParcelableExtra(Constants.RECEIVER); // Check if receiver was properly registered.
if (mReceiver == null) {
Log.wtf(TAG, "No receiver received. There is nowhere to send the results.");
return;
} // Get the location passed to this service through an extra.
Location location = intent.getParcelableExtra(Constants.LOCATION_DATA_EXTRA); // Make sure that the location data was really sent over through an extra. If it wasn't,
// send an error error message and return.
if (location == null) {
errorMessage = getString(R.string.no_location_data_provided);
Log.wtf(TAG, errorMessage);
deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
return;
} // Errors could still arise from using the Geocoder (for example, if there is no
// connectivity, or if the Geocoder is given illegal location data). Or, the Geocoder may
// simply not have an address for a location. In all these cases, we communicate with the
// receiver using a resultCode indicating failure. If an address is found, we use a
// resultCode indicating success. // The Geocoder used in this sample. The Geocoder's responses are localized for the given
// Locale, which represents a specific geographical or linguistic region. Locales are used
// to alter the presentation of information such as numbers or dates to suit the conventions
// in the region they describe.
Geocoder geocoder = new Geocoder(this, Locale.getDefault()); // Address found using the Geocoder.
List<Address> addresses = null; try {
// Using getFromLocation() returns an array of Addresses for the area immediately
// surrounding the given latitude and longitude. The results are a best guess and are
// not guaranteed to be accurate.
addresses = geocoder.getFromLocation(
location.getLatitude(),
location.getLongitude(),
// In this sample, we get just a single address.
);
} catch (IOException ioException) {
// Catch network or other I/O problems.
errorMessage = getString(R.string.service_not_available);
Log.e(TAG, errorMessage, ioException);
} catch (IllegalArgumentException illegalArgumentException) {
// Catch invalid latitude or longitude values.
errorMessage = getString(R.string.invalid_lat_long_used);
Log.e(TAG, errorMessage + ". " +
"Latitude = " + location.getLatitude() +
", Longitude = " + location.getLongitude(), illegalArgumentException);
} // Handle case where no address was found.
if (addresses == null || addresses.size() == ) {
if (errorMessage.isEmpty()) {
errorMessage = getString(R.string.no_address_found);
Log.e(TAG, errorMessage);
}
deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
} else {
Address address = addresses.get();
ArrayList<String> addressFragments = new ArrayList<String>(); // Fetch the address lines using {@code getAddressLine},
// join them, and send them to the thread. The {@link android.location.address}
// class provides other options for fetching address details that you may prefer
// to use. Here are some examples:
// getLocality() ("Mountain View", for example)
// getAdminArea() ("CA", for example)
// getPostalCode() ("94043", for example)
// getCountryCode() ("US", for example)
// getCountryName() ("United States", for example)
for(int i = ; i < address.getMaxAddressLineIndex(); i++) {
addressFragments.add(address.getAddressLine(i));
}
Log.i(TAG, getString(R.string.address_found));
deliverResultToReceiver(Constants.SUCCESS_RESULT,
TextUtils.join(System.getProperty("line.separator"), addressFragments));
}
} /**
* Sends a resultCode and message to the receiver.
*/
private void deliverResultToReceiver(int resultCode, String message) {
Bundle bundle = new Bundle();
bundle.putString(Constants.RESULT_DATA_KEY, message);
mReceiver.send(resultCode, bundle);
}
}
将服务声明下
<service
android:name=".FetchAddressIntentService"
android:exported="false"/>
4.使用地理围栏,在进入和退出围栏时有提醒。
/**
* Adds geofences, which sets alerts to be notified when the device enters or exits one of the
* specified geofences. Handles the success or failure results returned by addGeofences().
*/
public void addGeofencesButtonHandler(View view) {
if (!mGoogleApiClient.isConnected()) {
Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show();
return;
} try {
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
// The GeofenceRequest object.
getGeofencingRequest(),
// A pending intent that that is reused when calling removeGeofences(). This
// pending intent is used to generate an intent when a matched geofence
// transition is observed.
getGeofencePendingIntent()
).setResultCallback(this); // Result processed in onResult().
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
logSecurityException(securityException);
}
}
/**
* Builds and returns a GeofencingRequest. Specifies the list of geofences to be monitored.
* Also specifies how the geofence notifications are initially triggered.
*/
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); // The INITIAL_TRIGGER_ENTER flag indicates that geofencing service should trigger a
// GEOFENCE_TRANSITION_ENTER notification when the geofence is added and if the device
// is already inside that geofence.
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); // Add the geofences to be monitored by geofencing service.
builder.addGeofences(mGeofenceList); // Return a GeofencingRequest.
return builder.build();
}
/**
* Gets a PendingIntent to send with the request to add or remove Geofences. Location Services
* issues the Intent inside this PendingIntent whenever a geofence transition occurs for the
* current list of geofences.
*
* @return A PendingIntent for the IntentService that handles geofence transitions.
*/
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
// addGeofences() and removeGeofences().
return PendingIntent.getService(this, , intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
创建围栏
/**
* This sample hard codes geofence data. A real app might dynamically create geofences based on
* the user's location.
*/
public void populateGeofenceList() {
for (Map.Entry<String, LatLng> entry : Constants.BAY_AREA_LANDMARKS.entrySet()) { mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId(entry.getKey()) // Set the circular region of this geofence.
.setCircularRegion(
entry.getValue().latitude,
entry.getValue().longitude,
Constants.GEOFENCE_RADIUS_IN_METERS
) // Set the expiration duration of the geofence. This geofence gets automatically
// removed after this period of time.
.setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) // Set the transition types of interest. Alerts are only generated for these
// transition. We track entry and exit transitions in this sample.
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
Geofence.GEOFENCE_TRANSITION_EXIT) // Create the geofence.
.build());
}
}
删除围栏。
/**
* Removes geofences, which stops further notifications when the device enters or exits
* previously registered geofences.
*/
public void removeGeofencesButtonHandler(View view) {
if (!mGoogleApiClient.isConnected()) {
Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show();
return;
}
try {
// Remove geofences.
LocationServices.GeofencingApi.removeGeofences(
mGoogleApiClient,
// This is the same pending intent that was used in addGeofences().
getGeofencePendingIntent()
).setResultCallback(this); // Result processed in onResult().
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
logSecurityException(securityException);
}
}
创建和删除围栏的回调,
/**
* Runs when the result of calling addGeofences() and removeGeofences() becomes available.
* Either method can complete successfully or with an error.
*
* Since this activity implements the {@link ResultCallback} interface, we are required to
* define this method.
*
* @param status The Status returned through a PendingIntent when addGeofences() or
* removeGeofences() get called.
*/
public void onResult(Status status) {
if (status.isSuccess()) {
// Update state and save in shared preferences.
mGeofencesAdded = !mGeofencesAdded;
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Constants.GEOFENCES_ADDED_KEY, mGeofencesAdded);
editor.apply(); // Update the UI. Adding geofences enables the Remove Geofences button, and removing
// geofences enables the Add Geofences button.
setButtonsEnabledState(); Toast.makeText(
this,
getString(mGeofencesAdded ? R.string.geofences_added :
R.string.geofences_removed),
Toast.LENGTH_SHORT
).show();
} else {
// Get the status code for the error and log it using a user-friendly message.
String errorMessage = GeofenceErrorMessages.getErrorString(this,
status.getStatusCode());
Log.e(TAG, errorMessage);
}
}
使用服务来监听这种进出围栏的状态,
/**
* Listener for geofence transition changes.
*
* Receives geofence transition events from Location Services in the form of an Intent containing
* the transition type and geofence id(s) that triggered the transition. Creates a notification
* as the output.
*/
public class GeofenceTransitionsIntentService extends IntentService { protected static final String TAG = "GeofenceTransitionsIS"; /**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public GeofenceTransitionsIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
} @Override
public void onCreate() {
super.onCreate();
} /**
* Handles incoming intents.
* @param intent sent by Location Services. This Intent is provided to Location
* Services (inside a PendingIntent) when addGeofences() is called.
*/
@Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
return;
} // Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition(); // Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { // Get the geofences that were triggered. A single event can trigger multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences(); // Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(
this,
geofenceTransition,
triggeringGeofences
); // Send notification and log the transition details.
sendNotification(geofenceTransitionDetails);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition));
}
} /**
* Gets transition details and returns them as a formatted string.
*
* @param context The app context.
* @param geofenceTransition The ID of the geofence transition.
* @param triggeringGeofences The geofence(s) triggered.
* @return The transition details formatted as String.
*/
private String getGeofenceTransitionDetails(
Context context,
int geofenceTransition,
List<Geofence> triggeringGeofences) { String geofenceTransitionString = getTransitionString(geofenceTransition); // Get the Ids of each geofence that was triggered.
ArrayList triggeringGeofencesIdsList = new ArrayList();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesIdsList.add(geofence.getRequestId());
}
String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList); return geofenceTransitionString + ": " + triggeringGeofencesIdsString;
} /**
* Posts a notification in the notification bar when a transition is detected.
* If the user clicks the notification, control goes to the MainActivity.
*/
private void sendNotification(String notificationDetails) {
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class); // Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); // Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(MainActivity.class); // Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent); // Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(, PendingIntent.FLAG_UPDATE_CURRENT); // Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this); // Define the notification settings.
builder.setSmallIcon(R.drawable.ic_launcher)
// In a real app, you may want to use a library like Volley
// to decode the Bitmap.
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
.setColor(Color.RED)
.setContentTitle(notificationDetails)
.setContentText(getString(R.string.geofence_transition_notification_text))
.setContentIntent(notificationPendingIntent); // Dismiss notification once the user touches it.
builder.setAutoCancel(true); // Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // Issue the notification
mNotificationManager.notify(, builder.build());
} /**
* Maps geofence transition types to their human-readable equivalents.
*
* @param transitionType A transition type constant defined in Geofence
* @return A String indicating the type of transition
*/
private String getTransitionString(int transitionType) {
switch (transitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
return getString(R.string.geofence_transition_entered);
case Geofence.GEOFENCE_TRANSITION_EXIT:
return getString(R.string.geofence_transition_exited);
default:
return getString(R.string.unknown_geofence_transition);
}
}
}
5.继承GoogleMap到android项目中;
详细参考可以看,参考
下面说说最关键的地方,其他地方的操作例如如何操地图,添加覆盖物等等则需要看说明文档了。
集成GoogleMap关键就是要申请用于Google地图的apikey,分正式的和测试的key;
正式的key是你打包上架时要用的;测试key是你平时用于测试调试的时候用的。
这2个key的生成是使用正式的keystoreh或者测试的keystore文件,然后利用keytool 工具生成对应的SHA1值,然后到google官网填写包名和SHA1去申请对应的apikey;
测试SHA1的值,keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
正式SHA1的值,keytool -list -v -keystore your_keystore_name -alias your_alias_name
your_alias_name为你生成正式keystore文件时填写的别名。
Android中使用GoogleMap的地理位置服务的更多相关文章
- Android中获取正在运行的服务-------ActivityManager.RunningServiceInfo的使用
关于PackageManager和ActivityManager的使用 ,自己也写了一些DEMO 了,基本上写的线路参考了Settings模块下的 应用程序,大家如果真正的有所兴趣,建议大家看看源码, ...
- Android中Chronometer 计时器和震动服务控件
Chronometer 计时器控件 首先在布局文件中添加chronometer控件:然后在mainActivity中获取到该控件 4 然后通过Button时间监听器中开启计时操作 5 chronome ...
- android中使用https是否对服务证书合法性校验的新的体会
package com.cetcs.logreport.utils; import android.content.Context; import org.apache.http.conn.ssl.S ...
- Android中Service和Activity之间的通信
启动Service并传递数据进去: Android中通过Intent来启动服务会传递一个Intent过去. 可以在Intent中通过putExtra()携带数据 Intent startIntent ...
- Android中后台的劳动者“服务”
前言 作为四大组件之一的Service,想必不少开发者都是了解的,那具体熟悉吗?是不是对Service中的每个知识点是否了解,它与Activity的关系又是什么样的,我们所理解的后台服务跟Servic ...
- Android中Service(服务)详解
http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...
- 一个Demo学完Android中所有的服务(转)
说明:这个例子实现了Android中常见的许多服务,下面是实现的截图 接下来,以源代码的方式分析这个例子 1.MainActivity--主界面 这个类主要是实现用户所看到的这个Activity, ...
- Android中直播视频技术探究之---视频直播服务端环境搭建(Nginx+RTMP)
一.前言 前面介绍了Android中视频直播中的一个重要类ByteBuffer,不了解的同学可以 点击查看 到这里开始,我们开始动手开发了,因为我们后续肯定是需要直播视频功能,然后把视频推流到服务端, ...
- 利用HTML5开发Android(5)---HTML5地理位置服务在Android中的应用
Android中 Java代码 //启用地理定位 webSettings.setGeolocationEnabled(true); //设置定位的数据库路径 webSettings.setGeoloc ...
随机推荐
- List集合的特有功能概述和测试
List集合的特有功能概述和测试A:List集合的特有功能概述void add(int index,E element)E remove(int index)E get(int index)E set ...
- loadrunner安装方法
1.loadrunner安装网盘地址: http://pan.baidu.com/s/1hrP6mDQ 一般会提示:“vc2005_sp1_with_atl_fix_redist 2.确认时提示缺少 ...
- 【剑指Offer】12、数值的整数次方
题目描述: 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 解题思路: 本题看似比较简单,是一个简单的指数运算,但需要完 ...
- dmidecode输出详解
一.先来看几个用dmidecode查看内存信息的例子. 1.查看内存槽数.那个槽位插了内存,大小是多少 [root@jiangyi01.sqa.zmf /home/ahao.mah] #dmideco ...
- Google HTML/CSS Style Guide
转自: http://google.github.io/styleguide/htmlcssguide.xml Google HTML/CSS Style Guide Revision 2.23 Ea ...
- 【JavaScript游戏开发】使用HTML5+Canvas+JavaScript 封装的一个超级马里奥游戏(包含源码)
这个游戏基本上是建立在JavaScript模块化的开发基础上进行封装的,对游戏里面需要使用到的游戏场景进行了封装,分别实现了Game,Sprite,enemy,player, base,Animati ...
- 多态(day10)
二十二 多态(Polymorphic) 函数重写(虚函数覆盖).多态概念 如果将基类中的某个成员函数声明为虚函数,那么子类与其具有相同原型的成员函数就也将是虚函数,并且对基类中的版本形成覆盖. 这时, ...
- UOJ #310 黎明前的巧克力 (FWT)
题目传送门 题目大意:给你一个序列,定义一个子序列的权值表示子序列中元素的异或和,现在让你选出两个互不相交的子序列,求选出的这两个子序列权值相等的方案数,$n,a_{i}\leq 10^{6}$ 这是 ...
- Centos 7源码编译搭建Nginx
一.Nginx入门介绍 1. Nginx(engine x):[ˈendʒɪnks] 2. Nginx 是 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版 ...
- python第十一周:RabbitMQ、Redis
Rabbit Mq消息队列 RabbitMQ能为你做些什么? 消息系统允许软件.应用相互连接和扩展.这些应用可以相互链接起来组成一个更大的应用,或者将用户设备和数据进行连接.消息系统通过将消息的发送和 ...