贴话APP实现的功能类似于百度贴吧,实现发帖,读帖,修改帖,删帖功能,项目特色在于借助个人服务器的数据库实现网络服务,利用本地LitaPal实现用户数据缓存。没有唯一用户的说法,使用人可以以任何用户名发帖,他人发帖可以看到。实现了NavigationView侧边栏功能和WebView个人博客,上传图片的功能,支持用户登录,头像上传和帖子图片上传。设计使用高德地图开发包实现地图功能。使用CardView美化RecylerView,支持ToolBar和Scrolling美化页面动画。 项目搭建 首页
首页采用Android Stdio模板(自带侧边栏),首页采用碎片,用RecylerView和CardView搭建,侧边栏采用NavigationView搭建。
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private static Connection conn = null;
private static PreparedStatement stmt = null;
private SwipeRefreshLayout swipeRefreshLayout;
private List sNewsList = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("主页");
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Intent intent = new Intent(MainActivity.this, PublishPost.class);
startActivity(intent);
item.setIntent(intent);
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, PublishPost.class);
startActivityForResult(intent, 1);
} else if (id == R.id.nav_gallery) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, WebBlog.class);
startActivity(intent);
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if (requestCode == RESULT_OK) {
String result = data.getStringExtra("message");
finish();
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
}
}
}
}
其中,onCreate函数初始化界面,引入ToolBar和NavigationView,onNavigationItemSelected函数设置侧边栏的点击事件的响应,onOptionsItemSelected函数设置ToolBar右边下拉框点击事件的响应。
布局
其中
首页内容显示采用碎片+RecylerView+CardView,核心代码如下
public class NewsTitleFragment extends Fragment {
private boolean isTwoPane;
private static Connection conn = null;
private static PreparedStatement stmt = null;
private List sNewsList = new ArrayList();
private static final CountDownLatch ctl = new CountDownLatch(1);
private SwipeRefreshLayout swipeRefreshLayout;
private NewsAdapter newsAdapter = new NewsAdapter();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.news_title_frag, container, false);
RecyclerView newsTitleRecyclerView = (RecyclerView) view.findViewById(R.id.news_title_recycle_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()) {
@Override
protected int getExtraLayoutSpace(RecyclerView.State state) {
return 300;
}
};
newsTitleRecyclerView.setLayoutManager(layoutManager);
@SuppressLint("HandlerLeak") final
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
sNewsList = (List) msg.obj;
Log.d("sNewList.length : ", String.valueOf(sNewsList.size()));
}
};
Thread thread = null;
thread = new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "ppppp: ???");
try {
conn = MySQLConnections.getConnection("blog");
} catch (Exception e) {
e.printStackTrace();
}
try {
String sql = "select id,author,title,content from Blog";
List list_tmp = new ArrayList();
if (conn != null) {
stmt = conn.prepareStatement(sql);
conn.setAutoCommit(false);
ResultSet rs = stmt.executeQuery();//用rs接收sql语句返回的查询结果
//执行查询语句并且保存结果
while (rs.next()) {
Log.d("1", "1");
News news = new News();
news.setId(Integer.parseInt(rs.getString("id")));
news.setAuthor(rs.getString("author"));
news.setTitle(rs.getString("title"));
news.setContent("u3000u3000" + rs.getString("content"));
Log.d("Title", news.getTitle());
list_tmp.add(news);
}
Collections.reverse(list_tmp);
sNewsList = list_tmp;
Message msg = new Message();
msg.obj = list_tmp;
handler.sendMessage(msg);
rs.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
});
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swip_refresh);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener(){
@Override
public void onRefresh() {
refreshContent();
}
});
newsAdapter.setmNewList(sNewsList);
Log.d("length:", String.valueOf(sNewsList.size()));
Log.d(TAG, "What???");
newsTitleRecyclerView.setAdapter(newsAdapter);
return view;
}
private void refreshContent() {
@SuppressLint("HandlerLeak") final
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
sNewsList = (List) msg.obj;
newsAdapter.addList(sNewsList);
swipeRefreshLayout.setRefreshing(false);
Log.d("sNewList.length : ", String.valueOf(sNewsList.size()));
}
};
Thread thread = null;
thread = new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "ppppp: ???");
try {
Thread.sleep(2000);
conn = MySQLConnections.getConnection("blog");
} catch (Exception e) {
e.printStackTrace();
}
try {
String sql = "select id,author,title,content from Blog";
List list_tmp = new ArrayList();
if (conn != null) {
stmt = conn.prepareStatement(sql);
conn.setAutoCommit(false);
ResultSet rs = stmt.executeQuery();//用rs接收sql语句返回的查询结果
//执行查询语句并且保存结果
while (rs.next()) {
Log.d("1", "1");
News news = new News();
news.setId(Integer.parseInt(rs.getString("id")));
news.setAuthor(rs.getString("author"));
news.setTitle(rs.getString("title"));
news.setContent("u3000u3000" + rs.getString("content"));
Log.d("Title", news.getTitle());
list_tmp.add(news);
}
sNewsList = list_tmp;
Message msg = new Message();
msg.obj = list_tmp;
handler.sendMessage(msg);
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
});
thread.start();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getActivity().findViewById(R.id.new_content_layout) != null) {
isTwoPane = true;
} else {
isTwoPane = false;
}
}
class NewsAdapter extends RecyclerView.Adapter {
private List mNewsList = new ArrayList();
private LayoutInflater mInflater;
class ViewHolder extends RecyclerView.ViewHolder {
TextView newsTitleText;
CardView newsCardView;
TextView newsContentPreView;
ImageView imageViewPreView;
public ViewHolder(View view) {
super(view);
newsCardView = (CardView) view.findViewById(R.id.item_cardview);
newsTitleText = (TextView) view.findViewById(R.id.news_title);
newsContentPreView = (TextView) view.findViewById(R.id.news_contentPre);
imageViewPreView = (ImageView) view.findViewById(R.id.imagePreRandon);
}
}
public NewsAdapter() {
}
public void setmNewList(List list) {
this.mNewsList = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.new_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
News news = mNewsList.get(holder.getAdapterPosition());
if (isTwoPane) {
NewsContentFragment newsContentFragment = (NewsContentFragment) getFragmentManager()
.findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(news.getTitle(), news.getContent());
} else {
NewsContentActivity.actionStart(getActivity(), news.getTitle(), news.getContent());
}
}
});
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
News news = mNewsList.get(position);
holder.newsTitleText.setText(news.getTitle());
holder.newsContentPreView.setText(news.getContent().substring(0, (news.getContent().length() > 10 ? 10 : news.getContent().length() / 2)));
int cnt = 1 + new Random().nextInt(11);
if (cnt == 1) {
holder.imageViewPreView.setImageResource(R.drawable.img_1);
} else if (cnt == 2) {
holder.imageViewPreView.setImageResource(R.drawable.img_2);
} else if (cnt == 3) {
holder.imageViewPreView.setImageResource(R.drawable.img_3);
} else if (cnt == 4) {
holder.imageViewPreView.setImageResource(R.drawable.img_5);
} else if (cnt == 5) {
holder.imageViewPreView.setImageResource(R.drawable.img_5);
} else if (cnt == 6) {
holder.imageViewPreView.setImageResource(R.drawable.img_6);
} else if (cnt == 7) {
holder.imageViewPreView.setImageResource(R.drawable.img_7);
} else if (cnt == 8) {
holder.imageViewPreView.setImageResource(R.drawable.img_8);
} else if (cnt == 9) {
holder.imageViewPreView.setImageResource(R.drawable.img_9);
} else if (cnt == 10) {
holder.imageViewPreView.setImageResource(R.drawable.img_10);
} else if (cnt == 11) {
holder.imageViewPreView.setImageResource(R.drawable.img_11);
} else {
holder.imageViewPreView.setImageResource(R.drawable.img_12);
}
}
@Override
public int getItemCount() {
return mNewsList.size();
}
}
}
重写onCreateView函数承载每个子项的布局,函数中开启线程和回调函数负责于服务器服务器建立连接MySQLConnections.getConnection("blog"),同时进行select查询;建立SwipeRefreshLayout实现下拉刷新事件。
onActivityCreated函数判断是平板显示还是手机显示,若是平板显示,则调用帖子内容碎片,否则调用内容活动Activity。
建立内容类适配器NewsAdapter,初始化CardView_item的内容,同时重写onCreateViewHolder函数,负责接收点击CardView_item跳转到帖子详情页面的事件。
重写onBindViewHolder函数承载每个子项Holder绑定数据,函数实现了随机图片显示。swipeRefreshLayout.setOnRefreshListener实现下拉刷新事件,重写OnRefresh函数使用refreshContent函数实现下拉刷新内容数据的更新。
getItemCount函数获取帖子个数。
碎片布局
主页内容碎片采用RelativeLayout布局,标签设置背景图片,SwipeRefreshLayout实现下拉刷新RecylarView。
RecylerView的子布局
RecyclerView的子view采用CardView布局
Head
Menu
活动核心代码
public class NewsContentActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private ImageView imageViewContent;
public static void actionStart(Context context, String newsTitle, String newsContent) {
Intent intent = new Intent(context, NewsContentActivity.class);
intent.putExtra("news_title", newsTitle);
intent.putExtra("news_content", newsContent);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news_content);
imageViewContent = (ImageView) findViewById(R.id.imageContent);
int cnt = 1 + new Random().nextInt(11);
if (cnt == 1) {
imageViewContent.setImageResource(R.drawable.img_1);
} else if (cnt == 2) {
imageViewContent.setImageResource(R.drawable.img_2);
} else if (cnt == 3) {
imageViewContent.setImageResource(R.drawable.img_3);
} else if (cnt == 4) {
imageViewContent.setImageResource(R.drawable.img_5);
} else if (cnt == 5) {
imageViewContent.setImageResource(R.drawable.img_5);
} else if (cnt == 6) {
imageViewContent.setImageResource(R.drawable.img_6);
} else if (cnt == 7) {
imageViewContent.setImageResource(R.drawable.img_7);
} else if (cnt == 8) {
imageViewContent.setImageResource(R.drawable.img_8);
} else if (cnt == 9) {
imageViewContent.setImageResource(R.drawable.img_9);
} else if (cnt == 10) {
imageViewContent.setImageResource(R.drawable.img_10);
} else if (cnt == 11) {
imageViewContent.setImageResource(R.drawable.img_11);
} else {
imageViewContent.setImageResource(R.drawable.img_12);
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
String newsTitle = getIntent().getStringExtra("news_title");
String newContent = getIntent().getStringExtra("news_content");
NewsContentFragment newsContentFragment = (NewsContentFragment) getSupportFragmentManager()
.findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(newsTitle, newContent);
toolbar.setTitle(newsTitle);
toolbar.setSubtitle(newsTitle);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);//左侧添加一个默认的返回图标
getSupportActionBar().setHomeButtonEnabled(true); //设置返回键可用
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
return false;
}
}
actionStart函数负责启动活动,onCreate生成活动窗口,初始化内容。
帖子详情页面布局
内容布局采用CoordinatorLayout(Super-power frameLayout)作为顶部布局和同时负责协调子view交互。使用AppBarLayout响应滚动手势和ToorBar**作为顶部子项。使用CardView作为帖子详细内容主体。
PublishPost核心代码
public class PublishPost extends AppCompatActivity { private Uri imageUri; private static int number = 0; private ImageView imageView; private EditText editText1; private EditText editText2; private EditText editText3; private Toolbar toolbar; private Button button; private final int CODE_PICK_PHOTO = 0; private final int RESULT_REQUEST_CODE = -1; private String bitmapToString= null; private String photoPath = null; private Bitmap bitmap; private String username; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_publish_post); Intent intentRec = getIntent(); username = intentRec.getStringExtra("userName"); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); final Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message message) { return false; } }); new Thread(new Runnable() { @Override public void run() { Message msg = new Message();//message用于给handler传递参数 try { MySQLConnections.getConnection("Blog"); } catch (Exception e) { e.printStackTrace(); Log.d("TAG", " 数据操作异常"); } handler.sendMessage(msg); } }).start(); imageView = (ImageView) findViewById(R.id.imageUp); imageView.setonClickListener(new View.onClickListener() { @Override public void onClick(View v) { Intent intent_gallery = new Intent(Intent.ACTION_PICK); intent_gallery.setType("image private void checkingAndroidVersion() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //Android6.0及以上先获取权限再定位 requestPermission(); } else { //Android6.0以下直接定位 mLocationClient.startLocation(); } } @AfterPermissionGranted(REQUEST_PERMISSIONS) private void requestPermission() { String[] permissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; if (EasyPermissions.hasPermissions(this, permissions)) { //true 有权限 开始定位 showMsg("已获得权限,可以定位啦!"); mLocationClient.startLocation(); } else { //false 无权限 EasyPermissions.requestPermissions(this, "需要权限", REQUEST_PERMISSIONS, permissions); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); //设置权限请求结果 EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); } private void initLocation() { //初始化定位 try { mLocationClient = new AMapLocationClient(getApplicationContext()); } catch (Exception e) { e.printStackTrace(); } //设置定位回调监听 mLocationClient.setLocationListener(this); //初始化AMapLocationClientOption对象 mLocationOption = new AMapLocationClientOption(); //设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。 mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); //获取最近3s内精度最高的一次定位结果: //设置setonceLocationLatest(boolean b)接口为true,启动定位时SDK会返回最近3s内精度最高的一次定位结果。如果设置其为true,setonceLocation(boolean b)接口也会被设置为true,反之不会,默认为false。 mLocationOption.setonceLocationLatest(true); //设置是否返回地址信息(默认返回地址信息) mLocationOption.setNeedAddress(true); //设置定位请求超时时间,单位是毫秒,默认30000毫秒,建议超时时间不要低于8000毫秒。 mLocationOption.setHttpTimeOut(20000); //关闭缓存机制,高精度定位会产生缓存。 mLocationOption.setLocationCacheEnable(false); //给定位客户端对象设置定位参数 mLocationClient.setLocationOption(mLocationOption); } private void showMsg(String s) { Toast.makeText(MapActivity.this, s, Toast.LENGTH_SHORT).show(); } @Override public void onLocationChanged(AMapLocation aMapLocation) { if (aMapLocation != null) { if (aMapLocation.getErrorCode() == 0) { //地址 String address = aMapLocation.getAddress(); double latitude = aMapLocation.getLatitude(); double longitude = aMapLocation.getLongitude(); StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("纬度:" + latitude + "n"); stringBuffer.append("经度:" + longitude + "n"); stringBuffer.append("地址:" + address + "n"); Log.d("MapActivity:", stringBuffer.toString()); if (mListener != null) { mListener.onLocationChanged(aMapLocation); } mLocationClient.stopLocation(); //显示浮空按钮 fabPOI.show(); //赋值 cityCode = aMapLocation.getCityCode(); //城市赋值 city = aMapLocation.getCity(); updateMapCenter(new LatLng(latitude, longitude)); } else { //定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。 Log.e("AmapError", "location Error, ErrCode:" + aMapLocation.getErrorCode() + ", errInfo:" + aMapLocation.getErrorInfo()); } } } @Override protected void onDestroy() { super.onDestroy(); //销毁定位客户端,同时销毁本地定位服务。 mLocationClient.onDestroy(); } @Override protected void onResume() { super.onResume(); //在activity执行onResume时执行mMapView.onResume (),重新绘制加载地图 mapView.onResume(); } @Override protected void onPause() { super.onPause(); //在activity执行onPause时执行mMapView.onPause (),暂停地图的绘制 mapView.onPause(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); //在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),保存地图当前的状态 mapView.onSaveInstanceState(outState); } private void initMap(Bundle savedInstanceState) throws AMapException { mapView = (MapView) findViewById(R.id.map_view); //在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),创建地图 mapView.onCreate(savedInstanceState); //初始化地图控制器对象 aMap = mapView.getMap(); //设置最小缩放等级为16 ,缩放级别范围为[3, 20] aMap.setMinZoomLevel(12); //开启室内地图 aMap.showIndoorMap(true); aMap.setonMapClickListener(this); aMap.setonMapLongClickListener(this); // 自定义精度范围的圆形边框颜色 都为0则透明 myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0)); // 自定义精度范围的圆形边框宽度 0 无宽度 myLocationStyle.strokeWidth(0); // 设置圆形的填充颜色 都为0则透明 myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0)); //设置定位蓝点的Style aMap.setMyLocationStyle(myLocationStyle); // 设置定位监听 aMap.setLocationSource(this); // 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false aMap.setMyLocationEnabled(true); //实例化UiSettings类对象 mUiSettings = aMap.getUiSettings(); //隐藏缩放按钮 mUiSettings.setZoomControlsEnabled(false); //显示比例尺 默认不显示 mUiSettings.setScaleControlsEnabled(true); //构建GeocodeSearch对象 geocodeSearch = new GeocodeSearch(this); geocodeSearch.setonGeocodeSearchListener(this); } private void latlonToAddress(LatLng latLng) { //位置点 通过经纬度进行构建 LatLonPoint latLonPoint = new LatLonPoint(latLng.latitude, latLng.longitude); //逆编码查询 第一个参数表示一个Latlng,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 20, GeocodeSearch.AMAP); //异步获取地址信息 geocodeSearch.getFromLocationAsyn(query); } @Override public void activate(onLocationChangedListener onLocationChangedListener) { mListener = onLocationChangedListener; if (mLocationClient == null) { mLocationClient.startLocation();//启动定位 } } @Override public void deactivate() { mListener = null; if (mLocationClient != null) { mLocationClient.stopLocation(); mLocationClient.onDestroy(); } mLocationClient = null; } public void queryPOI(View view) throws AMapException { //构造query对象 query = new PoiSearch.Query("购物", "", cityCode); // 设置每页最多返回多少条poiitem query.setPageSize(10); //设置查询页码 query.setPageNum(1); //构造 PoiSearch 对象 poiSearch = new PoiSearch(this, query); //设置搜索回调监听 poiSearch.setonPoiSearchListener(this); //发起搜索附近POI异步请求 poiSearch.searchPOIAsyn(); } @Override public void onPoiSearched(PoiResult poiResult, int i) { //解析result获取POI信息 //获取POI组数列表 ArrayList poiItems = poiResult.getPois(); for (PoiItem poiItem : poiItems) { Log.d("MainActivity", " Title:" + poiItem.getTitle() + " Snippet:" + poiItem.getSnippet()); } } @Override public void onPoiItemSearched(PoiItem poiItem, int i) { } @Override public void onMapClick(LatLng latLng) { showMsg("点击了地图,经度:" + latLng.longitude + ",纬度:" + latLng.latitude); latlonToAddress(latLng); updateMapCenter(latLng); } @Override public void onMapLongClick(LatLng latLng) { showMsg("长按了地图,经度:" + latLng.longitude + ",纬度:" + latLng.latitude); latlonToAddress(latLng); } @Override public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int rCode) { //解析result获取地址描述信息 if (rCode == PARSE_SUCCESS_CODE) { RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress(); //显示解析后的地址 showMsg("地址:" + regeocodeAddress.getFormatAddress()); } else { showMsg("获取地址失败"); } } @Override public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { if (i == PARSE_SUCCESS_CODE) { List geocodeAddressList = geocodeResult.getGeocodeAddressList(); if (geocodeAddressList != null && geocodeAddressList.size() > 0) { LatLonPoint latLonPoint = geocodeAddressList.get(0).getLatLonPoint(); //显示解析后的坐标 showMsg("坐标csac:" + latLonPoint.getLongitude() + "," + latLonPoint.getLatitude()); LatLng latLng = new LatLng(latLonPoint.getLatitude(), latLonPoint.getLongitude()); updateMapCenter(latLng); } } else { showMsg("获取坐标失败"); } } @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) { //获取输入框的值 String address = etAddress.getText().toString().trim(); if (address == null || address.isEmpty()) { showMsg("请输入地址"); } else { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); //隐藏软键盘 imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0); // name表示地址,第二个参数表示查询城市,中文或者中文全拼,citycode、adcode GeocodeQuery query = new GeocodeQuery(address, city); geocodeSearch.getFromLocationNameAsyn(query); } return true; } return false; } private void updateMapCenter(LatLng latLng) { // CameraPosition 第一个参数: 目标位置的屏幕中心点经纬度坐标。 // CameraPosition 第二个参数: 目标可视区域的缩放级别 // CameraPosition 第三个参数: 目标可视区域的倾斜度,以角度为单位。 // CameraPosition 第四个参数: 可视区域指向的方向,以角度为单位,从正北向顺时针方向计算,从0度到360度 Da //位置变更 CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition); //改变位置 aMap.animateCamera(cameraUpdate); } }
更新帖子
该模块实现更新修改用户已经发布的帖子。
核心代码
public class UpdataPost extends AppCompatActivity { private ImageView imageView; private EditText editText1; private EditText editText2; private EditText editText3; private Toolbar toolbar; private Button button; private Connection connection; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_updata_post); imageView = (ImageView) findViewById(R.id.imageUp); editText1 = (EditText) findViewById(R.id.upAuthor); editText2 = (EditText) findViewById(R.id.uptitle); editText3 = (EditText) findViewById(R.id.upcontent); Intent intent = getIntent(); String title = intent.getStringExtra("title"); final String content = intent.getStringExtra("content"); editText2.setText(title); editText3.setText(content); button = (Button) findViewById(R.id.buttonUp); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { try{ connection = MySQLConnections.getConnection("blog"); String title1 = editText2.getText().toString(); String content1 = editText3.getText().toString(); String sql = "update Blog set title='"+title1+"' where content='"+content+"'"; PreparedStatement pst; pst = connection.prepareStatement(sql); pst.executeUpdate(); sql = "update Blog set content='"+content1+"' where title='"+title1+"'"; pst.close(); connection.close(); }catch (Exception e){ e.printStackTrace(); } } }).start(); } }); } }
News
public class News { private String title; private String content; private String author; private int id; private String image; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } }
MyPost
public class MyPost extends DataSupport { private String username; private String newstitle; private String newscontent; private String imagePost; public String getNewstitle() { return newstitle; } public void setNewstitle(String newstitle) { this.newstitle = newstitle; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getNewscontent() { return newscontent; } public void setNewscontent(String newscontent) { this.newscontent = newscontent; } public String getImagePost() { return imagePost; } public void setImagePost(String imagePost) { this.imagePost = imagePost; } }
User
public class User extends DataSupport { private String name; private String password; private String image; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } }
ImageHelper
实现Bitmap和String的转换
public class ImageHelper { public static Bitmap stringToBitmap(String string) { // 将字符串转换成Bitmap类型 Bitmap bitmap = null; try { byte[] bitmapArray; bitmapArray = base64.decode(string, base64.DEFAULT); bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length); } catch (Exception e) { e.printStackTrace(); } return bitmap; } //把bitmap转换成字符串 public static String bitmapToString(Bitmap bitmap) { String string = null; ByteArrayOutputStream btString = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, btString); byte[] bytes = btString.toByteArray(); string = base64.encodeToString(bytes, base64.DEFAULT); return string; } }
MySQLConnection
实现服务器数据库的连接以及数据库的操作(导入MySqlConnector包)。
public class MySQLConnections { public static int number = 0; private String driver = ""; private String dbURL = ""; private String user = ""; private String password = ""; private static MySQLConnections connection = null; private static Connection conn = null; private static PreparedStatement stmt = null; private static ListnewsList = new ArrayList(); private MySQLConnections() throws Exception { driver = "com.mysql.jdbc.Driver"; dbURL = "jdbc:mysql://182.92.153.231:3306/blog"; user = "lkk"; password = "123456"; System.out.println("dbURL:" + dbURL); } public static Connection getConnection(String dbName) { Connection conn = null; if (connection == null) { try { connection = new MySQLConnections(); } catch (Exception e) { e.printStackTrace(); return null; } } try { Class.forName(connection.driver); conn = DriverManager.getConnection(connection.dbURL, connection.user, connection.password); } catch (Exception e) { e.printStackTrace(); } return conn; } public static int insertIntoData(final int id, final String author,final String title,final String content,String image) throws SQLException {//增加数据 Connection conn = null; conn = getConnection("blog");//填写需要连接的数据库的名称,我是用的是person //使用DriverManager获取数据库连接 Statement stmt = conn.createStatement(); //使用Connection来创建一个Statment对象 String sql = "insert INTO Blog (id,author,title,content,image)VALUES('"+id+"','"+author+"','"+title+"','"+content+"','"+image+"')"; return stmt.executeUpdate(sql);//返回的同时执行sql语句,返回受影响的条目数量,一般不作处理 } public static List querycol() throws SQLException {//读取某一行 //加载数据库驱动 final Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message message) { //下一步执行的代码 return false; } }); new Thread(new Runnable() { @Override public void run() { Message msg = new Message();//message用于给handler传递参数 try { //调用连接数据库方法的代码 conn = MySQLConnections.getConnection("Blog"); } catch (Exception e) { e.printStackTrace(); Log.d("TAG", " 数据操作异常"); }handler.sendMessage(msg); try { String sql = "select * from Blog"; if(conn != null){ stmt = conn.prepareStatement(sql); conn.setAutoCommit(false); ResultSet rs =stmt.executeQuery();//用rs接收sql语句返回的查询结果 //执行查询语句并且保存结果 while (rs.next()){ News news = new News(); news.setId(Integer.parseInt(rs.getString("id"))); news.setAuthor(rs.getString("author")); news.setTitle(rs.getString("title")); news.setContent(rs.getString("content")); news.setImage(rs.getString("image")); newsList.add(news); } rs.close(); } sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } }).start(); return newsList; } public static int insertIntoUser(String name, String password, String image) throws SQLException { Connection conn = null; conn = getConnection("blog");//填写需要连接的数据库的名称,我是用的是person //使用DriverManager获取数据库连接 Statement stmt = conn.createStatement(); //使用Connection来创建一个Statment对象 String sql = "insert INTO User (name,password,image)VALUES('"+name+"','"+password+"','"+image+"')"; return stmt.executeUpdate(sql); } }
地址:https://gitee.com/lkksxxdxxd/android



