添加jellyfin client

This commit is contained in:
sifacaii 2022-08-30 20:58:30 +08:00
parent 9f9e36135e
commit 299595bcad
6 changed files with 373 additions and 119 deletions

2
.idea/misc.xml generated
View File

@ -27,7 +27,7 @@
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_main.xml" value="0.2957427536231884" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_search.xml" value="0.14791666666666667" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_vlc_player.xml" value="0.14895833333333333" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/dialog_login.xml" value="0.2957427536231884" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/dialog_login.xml" value="0.4" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/home_horizon_tvrecycler.xml" value="0.14791666666666667" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/item_h.xml" value="0.14895833333333333" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/item_title.xml" value="0.14895833333333333" />

View File

@ -20,7 +20,7 @@
android:hardwareAccelerated="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:name=".HomeActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -0,0 +1,184 @@
package org.sifacai.vlcjellyfin;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
public class HomeActivity extends BaseActivity{
private final String TAG = "HomeActivity";
private LinearLayout tvContiner;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.jellyfin_home);
disableActiveBarBack();
tvContiner = findViewById(R.id.tvItems);
JfClient.init(this);
Log.d(TAG, "onCreate: " + JfClient.config.getJellyfinUrl());
if(JfClient.AccessToken.equals("") ||JfClient.UserId.equals("")){
showLoadingDialog("正在验证服务器地址!");
JfClient.VerityServerUrl(JfClient.config.getJellyfinUrl(),new JfClient.JJCallBack(){
@Override
public void onSuccess(Boolean bool) {
dismissLoadingDialog();
if(bool){
showLoadingDialog("正在验证用户名和密码!");
JfClient.AuthenticateByName(JfClient.config.getUserName(),JfClient.config.getPassWord(),new JfClient.JJCallBack(){
@Override
public void onSuccess(Boolean bool) {
dismissLoadingDialog();
if(bool){
initView(); //加载首页
}else{
showLoginDialog();
}
}
},false);
}else{
ShowToask("服务器地址不正确!");
showLoginDialog();
}
}
});
}else{
initView();
}
}
private void showLoginDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alert = builder.setTitle("登录")
.setMessage("请输入登录信息")
.setView(R.layout.dialog_login)
.show();
alert.setCanceledOnTouchOutside(false);
EditText urlbox = alert.findViewById(R.id.dialog_login_url);
EditText unbox = alert.findViewById(R.id.dialog_login_un);
EditText pwbox = alert.findViewById(R.id.dialog_login_pw);
CheckBox saveBox = alert.findViewById(R.id.dialog_login_save);
TextView submit = alert.findViewById(R.id.dialog_login_submit);
TextView cancel = alert.findViewById(R.id.dialog_login_cancel);
urlbox.setText(JfClient.config.getJellyfinUrl());
unbox.setText(JfClient.config.getUserName());
pwbox.setText(JfClient.config.getPassWord());
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.exit(0);
}
});
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showLoadingDialog("正在验证服务器地址!");
JfClient.VerityServerUrl(urlbox.getText().toString(),new JfClient.JJCallBack(){
@Override
public void onSuccess(Boolean bool) {
dismissLoadingDialog();
if(bool){
showLoadingDialog("正在验证用户名和密码!");
JfClient.AuthenticateByName(unbox.getText().toString(),pwbox.getText().toString(),new JfClient.JJCallBack(){
@Override
public void onSuccess(Boolean bool) {
dismissLoadingDialog();
if(bool){
alert.dismiss();
initView(); //加载首页
}else{
ShowToask("用户名密码不正确!");
}
}
},saveBox.isChecked());
}else{
ShowToask("服务器地址不正确!");
}
}
});
}
});
}
private void initView(){
JfClient.GetViews(new JfClient.JJCallBack(){
@Override
public void onSuccess(JsonArray views) {
showLoadingDialog("正在加载首页…………");
addRowTvRecyclerView("我的媒体", views, true);
dismissLoadingDialog();
}
});
}
/**
* 添加类别行
*/
private void addRowTvRecyclerView(String title, JsonArray data, boolean horizon) {
JRecyclerView tvRecyclerView = (JRecyclerView) LayoutInflater.from(this)
.inflate(R.layout.home_horizon_tvrecycler, null);
((V7LinearLayoutManager) tvRecyclerView.getLayoutManager()).setOrientation(V7LinearLayoutManager.HORIZONTAL);
JAdapter jAdapter = new JAdapter(data, horizon);
jAdapter.setOnItemClickListener(new JAdapter.OnItemClickListener() {
@Override
public void onClick(JsonObject jo) {
String type = Utils.getJsonString(jo, "Type").getAsString();
String itemId = jo.get("Id").getAsString();
Intent intent = null;
if (type.equals("Folder") || type.equals("CollectionFolder")) {
intent = new Intent(mAA, CollectionActivity.class);
} else {
intent = new Intent(mAA, DetailActivity.class);
}
intent.putExtra("itemId", itemId);
mAA.startActivity(intent);
}
});
tvRecyclerView.setAdapter(jAdapter);
TextView titleView = new TextView(tvRecyclerView.getContext());
titleView.setText(title);
tvContiner.addView(titleView);
tvContiner.addView(tvRecyclerView);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exit();
return false;
}
return super.onKeyDown(keyCode, event);
}
private long exitTime = 0;
public void exit() {
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(getApplicationContext(), "再按一次退出程序",
Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
}
}

View File

@ -1,20 +1,34 @@
package org.sifacai.vlcjellyfin;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheEntity;
import com.lzy.okgo.cache.CacheMode;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.model.HttpHeaders;
import com.lzy.okgo.model.Response;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
public class JfClient {
public final String XEmbyAuthorization = "MediaBrowser Client=\"Vlc_J_TV\", Device=\"Vlc_J_TV\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBXa\", Version=\"10.8.1\"";
public HttpHeaders headers;
public String UserId="";
public String AccessToken="";
public String serverUrl;
public static final String TAG = "JellyfinClient";
public static final String XEmbyAuthorization = "MediaBrowser Client=\"Vlc_J_TV\", Device=\"Vlc_J_TV\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBXa\", Version=\"10.8.1\"";
public static HttpHeaders headers;
public static Config config;
public static String UserId = "";
public static String AccessToken = "";
public enum ReportType {
playing,
@ -22,23 +36,33 @@ public class JfClient {
stop
}
/**
* 初始化配置
* @param context
*/
public static void init(Context context) {
config = new Config(context);
SetHeaders();
}
/**
* 回放报告
*
* @param type
* @param id
* @param PositionTicks
*/
public void ReportPlayBackState(ReportType type,String id,long PositionTicks){
String url = serverUrl;
if(type == ReportType.playing){
public static void ReportPlayBackState(ReportType type, String id, long PositionTicks) {
String url = config.getJellyfinUrl();
if (type == ReportType.playing) {
url += "/Sessions/Playing";
}else if(type == ReportType.Progress){
} else if (type == ReportType.Progress) {
url += "/Sessions/Playing/Progress";
}else if(type == ReportType.stop){
} else if (type == ReportType.stop) {
url += "/Sessions/Playing/Stopped";
}
String reqstr = "{\"itemId\":\"" + id + "\",\"PositionTicks\":\"" + PositionTicks * 10000 + "\"}";
SendPost(url,reqstr,new JJCallBack(){
SendPost(url, reqstr, new JJCallBack() {
@Override
public void onSuccess(String str) {
//回放报告
@ -48,49 +72,52 @@ public class JfClient {
/**
* 获取封面图url
*
* @param itemid
* @param tagid
* @return
*/
public String GetImgUrl(String itemid, String tagid) {
String url = serverUrl + "/Items/" + itemid + "/Images/Primary";
public static String GetImgUrl(String itemid, String tagid) {
String url = config.getJellyfinUrl() + "/Items/" + itemid + "/Images/Primary";
url += "?fillHeight=286&fillWidth=200&quality=96&tag=" + tagid;
return url;
}
public String GetImgUrl(JsonObject item) {
String id = jeFromGson(item,"Id").getAsString();
String imgid = jeFromGson(jeFromGson(item,"ImageTags").getAsJsonObject(),"Primary").getAsString();
return GetImgUrl(id,imgid);
public static String GetImgUrl(JsonObject item) {
String id = jeFromGson(item, "Id").getAsString();
String imgid = jeFromGson(jeFromGson(item, "ImageTags").getAsJsonObject(), "Primary").getAsString();
return GetImgUrl(id, imgid);
}
/**
* 获取播放url
*
* @param itemid
* @return
*/
public String GetPlayUrl(String itemid){
String playurl = serverUrl + "/videos/" + itemid + "/stream.mp4?static=true&a";
public static String GetPlayUrl(String itemid) {
String playurl = config.getJellyfinUrl() + "/videos/" + itemid + "/stream.mp4?static=true&a";
return playurl;
}
/**
* 获取剧集
*
* @param seriesId 剧ID
* @param seasonId 季ID
* @param cb
*/
public void GetEpisodes(String seriesId,String seasonId,JJCallBack cb){
String EpisodesUrl = serverUrl + "/Shows/" + seriesId + "/Episodes?seasonId=" + seasonId;
public static void GetEpisodes(String seriesId, String seasonId, JJCallBack cb) {
String EpisodesUrl = config.getJellyfinUrl() + "/Shows/" + seriesId + "/Episodes?seasonId=" + seasonId;
EpisodesUrl += "&userId=" + UserId;
EpisodesUrl += "&Fields=ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount,Overview";
SendGet(EpisodesUrl,new JJCallBack(){
SendGet(EpisodesUrl, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonObject item = strToGson(str,JsonObject.class);
JsonObject item = strToGson(str, JsonObject.class);
if (null != item) {
JsonArray items = jeFromGson(item,"Items").getAsJsonArray();
JsonArray items = jeFromGson(item, "Items").getAsJsonArray();
cb.onSuccess(items);
}
}
@ -100,19 +127,20 @@ public class JfClient {
/**
* 获取季(Seasons)数据
*
* @param seriesId 剧ID
* @param cb
*/
public void GetSeasons(String seriesId,JJCallBack cb){
String SeasonsUrl = serverUrl + "/Shows/" + seriesId + "/Seasons?userId=" + UserId;
public static void GetSeasons(String seriesId, JJCallBack cb) {
String SeasonsUrl = config.getJellyfinUrl() + "/Shows/" + seriesId + "/Seasons?userId=" + UserId;
SeasonsUrl += "&Fields=ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,MediaSourceCount";
SendGet(SeasonsUrl,new JJCallBack(){
SendGet(SeasonsUrl, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonObject item = strToGson(str,JsonObject.class);
if(null != item){
JsonArray items = jeFromGson(item,"Items").getAsJsonArray();
JsonObject item = strToGson(str, JsonObject.class);
if (null != item) {
JsonArray items = jeFromGson(item, "Items").getAsJsonArray();
cb.onSuccess(items);
}
}
@ -121,19 +149,20 @@ public class JfClient {
/**
* 获取合集条目
*
* @param parentId
* @param type 类型 movietvshows
* @param sortBy 排序条件 评分加入时间
* @param type 类型 movietvshows
* @param sortBy 排序条件 评分加入时间
* @param sortOrder 排序规则 升序降序
* @param limit 每页条数
* @param page
* @param limit 每页条数
* @param page
* @param cb
*/
public void GetCollection(String parentId,String type,String sortBy,String sortOrder,int limit,int page,JJCallBack cb){
String itemsUrl = serverUrl + "/Users/" + UserId + "/Items?ParentId=" + parentId + "&Limit=" + limit;
public static void GetCollection(String parentId, String type, String sortBy, String sortOrder, int limit, int page, JJCallBack cb) {
String itemsUrl = config.getJellyfinUrl() + "/Users/" + UserId + "/Items?ParentId=" + parentId + "&Limit=" + limit;
itemsUrl += "&Recursive=true&Fields=PrimaryImageAspectRatio,BasicSyncInfo,Seasons,Episodes&ImageTypeLimit=1";
itemsUrl += "&EnableImageTypes=Primary,Backdrop,Banner,Thumb";
itemsUrl += "&SortBy="+sortBy+",SortName,ProductionYear&SortOrder=" + sortOrder;
itemsUrl += "&SortBy=" + sortBy + ",SortName,ProductionYear&SortOrder=" + sortOrder;
if (type.equals("tvshows")) {
itemsUrl += "&IncludeItemTypes=Series";
@ -145,10 +174,10 @@ public class JfClient {
int startIndex = page * limit - limit;
itemsUrl += "&StartIndex=" + startIndex;
SendGet(itemsUrl,new JJCallBack(){
SendGet(itemsUrl, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonObject items = strToGson(str,JsonObject.class);
JsonObject items = strToGson(str, JsonObject.class);
cb.onSuccess(items);
}
});
@ -156,20 +185,21 @@ public class JfClient {
/**
* 获取最新项目
*
* @param parentId
* @param cb
*/
public void GetLatest(String parentId,JJCallBack cb){
String lastestUrl = serverUrl + "/Users/" + UserId + "/Items/Latest?";
public static void GetLatest(String parentId, JJCallBack cb) {
String lastestUrl = config.getJellyfinUrl() + "/Users/" + UserId + "/Items/Latest?";
lastestUrl += "Limit=16&Fields=PrimaryImageAspectRatio%2CBasicSyncInfo%2CPath";
lastestUrl += "&ImageTypeLimit=1&EnableImageTypes=Primary,Backdrop,Thumb";
lastestUrl += "&ParentId=" + parentId;
SendGet(lastestUrl,new JJCallBack(){
SendGet(lastestUrl, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonArray latestObj = strToGson(str,JsonArray.class);
if(null != latestObj) {
JsonArray latestObj = strToGson(str, JsonArray.class);
if (null != latestObj) {
cb.onSuccess(latestObj);
}
}
@ -178,19 +208,20 @@ public class JfClient {
/**
* 获取最近播放
*
* @param cb
*/
public void GetResume(JJCallBack cb){
String resumeUrl = serverUrl + "/Users/" + UserId + "/Items/Resume?";
public static void GetResume(JJCallBack cb) {
String resumeUrl = config.getJellyfinUrl() + "/Users/" + UserId + "/Items/Resume?";
resumeUrl += "Limit=12&Recursive=true&Fields=PrimaryImageAspectRatio,BasicSyncInfo";
resumeUrl += "&ImageTypeLimit=1&EnableImageTypes=Primary,Backdrop,Thumb";
resumeUrl += "&EnableTotalRecordCount=false&MediaTypes=Video";
SendGet(resumeUrl,new JJCallBack(){
SendGet(resumeUrl, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonObject resumeObj = strToGson(str,JsonObject.class);
if(null != resumeObj) {
JsonObject resumeObj = strToGson(str, JsonObject.class);
if (null != resumeObj) {
JsonArray resumes = jeFromGson(resumeObj, "Items").getAsJsonArray();
cb.onSuccess(resumes);
}
@ -200,16 +231,17 @@ public class JfClient {
/**
* 获取首页
*
* @param cb
*/
public void GetViews(JJCallBack cb){
String viewsUrl = serverUrl + "/Users/" + UserId + "/Views";
SendGet(viewsUrl,new JJCallBack(){
public static void GetViews(JJCallBack cb) {
String viewsUrl = config.getJellyfinUrl() + "/Users/" + UserId + "/Views";
SendGet(viewsUrl, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonObject viewsObj = strToGson(str,JsonObject.class);
if(null!=viewsObj){
JsonArray views = jeFromGson(viewsObj,"Items").getAsJsonArray();
JsonObject viewsObj = strToGson(str, JsonObject.class);
if (null != viewsObj) {
JsonArray views = jeFromGson(viewsObj, "Items").getAsJsonArray();
cb.onSuccess(views);
}
}
@ -218,16 +250,17 @@ public class JfClient {
/**
* 获取项目详情
*
* @param itemid
* @param cb
*/
public void GetItemInfo(String itemid,JJCallBack cb){
String url = serverUrl + "/Users/" + UserId + "/Items/" + itemid;
SendGet(url,new JJCallBack(){
public static void GetItemInfo(String itemid, JJCallBack cb) {
String url = config.getJellyfinUrl() + "/Users/" + UserId + "/Items/" + itemid;
SendGet(url, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonObject item = strToGson(str,JsonObject.class);
if(null != item){
JsonObject item = strToGson(str, JsonObject.class);
if (null != item) {
cb.onSuccess(item);
}
}
@ -236,29 +269,34 @@ public class JfClient {
/**
* 验证用户名密码
*
* @param username
* @param password
* @param cb
*/
public void authenticateByName(String username,String password,JJCallBack cb){
String url = serverUrl + "/Users/authenticatebyname";
public static void AuthenticateByName(String username, String password, JJCallBack cb, boolean saveUser) {
String url = config.getJellyfinUrl() + "/Users/authenticatebyname";
String reqjson = "{\"Username\":\"" + username + "\",\"Pw\":\"" + password + "\"}";
SendPost(url,reqjson,new JJCallBack(){
SendPost(url, reqjson, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonObject userObj = strToGson(str, JsonObject.class);
if (userObj != null) {
String userId = jeFromGson(jeFromGson(userObj, "User").getAsJsonObject(),"Id").getAsString();
String Token = jeFromGson(userObj,"AccessToken").getAsString();
String userId = jeFromGson(jeFromGson(userObj, "User").getAsJsonObject(), "Id").getAsString();
String Token = jeFromGson(userObj, "AccessToken").getAsString();
if (!Token.equals("")) {
UserId = userId;
AccessToken = Token;
if (saveUser) {
config.setUserName(username);
config.setPassWord(password);
}
SetHeaders();
cb.onSuccess(true);
}else {
} else {
cb.onSuccess(false);
}
}else {
} else {
cb.onSuccess(false);
}
}
@ -267,14 +305,15 @@ public class JfClient {
/**
* 获取用户列表
* @param cb
*
* @param cb
*/
public void GetUsers(JJCallBack cb){
String url = serverUrl + "/users/public";
SendGet(url,new JJCallBack(){
public static void GetUsers(JJCallBack cb) {
String url = config.getJellyfinUrl() + "/users/public";
SendGet(url, new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonArray users = strToGson(str,JsonArray.class);
JsonArray users = strToGson(str, JsonArray.class);
cb.onSuccess(users);
}
});
@ -282,34 +321,41 @@ public class JfClient {
/**
* 验证服务器地址
*
* @param url
* @param cb
*/
public void VerityServerUrl(String url,JJCallBack cb){
SendGet(url + "/system/info/public",new JJCallBack(){
@Override
public void onSuccess(String str) {
JsonObject serverInfo = strToGson(str,JsonObject.class);
if (serverInfo != null) {
String ServerId = jeFromGson(serverInfo,"Id").getAsString();
if (ServerId == null || ServerId.length() == 0) {
cb.onSuccess(false);
} else {
serverUrl = url;
cb.onSuccess(true);
public static void VerityServerUrl(String url, JJCallBack cb) {
if (url.length() > 0) {
if (url.startsWith("http://") || url.startsWith("https://")) {
SendGet(url + "/system/info/public", new JJCallBack() {
@Override
public void onSuccess(String str) {
JsonObject serverInfo = strToGson(str, JsonObject.class);
String ServerId = jeFromGson(serverInfo, "Id") == null ? null : jeFromGson(serverInfo, "Id").getAsString();
if (ServerId == null || ServerId.length() == 0) {
cb.onSuccess(false);
} else {
config.setJellyfinUrl(url);
cb.onSuccess(true);
}
}
}
});
}
});
}else{
cb.onSuccess(false);
}
}
/**
* 设置请求头
*/
public void SetHeaders(){
public static void SetHeaders() {
headers = new HttpHeaders();
String xea = XEmbyAuthorization;
if(null != AccessToken && AccessToken.length() > 0){
if (null != AccessToken && AccessToken.length() > 0) {
xea += ", Token=\"" + AccessToken + "\"";
}
headers.put("Accept", "application/json");
@ -319,39 +365,46 @@ public class JfClient {
/**
* Get
*
* @param url
* @param cb
*/
public void SendGet(String url, JJCallBack cb){
OkGo.<String>get(url).headers(headers).execute(new AbsCallback<String>() {
@Override
public String convertResponse(okhttp3.Response response) throws Throwable {
String result = "";
if(null != response.body()){
result = response.body().string();
public static void SendGet(String url, JJCallBack cb) {
OkGo.<String>get(url).headers(headers).execute(new AbsCallback<String>() {
@Override
public String convertResponse(okhttp3.Response response) throws IOException {
String result = "";
if (null != response.body()) {
result = response.body().string();
}
return result;
}
return result;
}
@Override
public void onSuccess(Response<String> response) {
cb.onSuccess(response.body());
}
});
@Override
public void onSuccess(Response<String> response) {
cb.onSuccess(response.body());
}
@Override
public void onError(Response<String> response) {
cb.onSuccess("");
}
});
}
/**
* Post
*
* @param url
* @param jsonStr
* @param cb
*/
public void SendPost(String url, String jsonStr, JJCallBack cb){
public static void SendPost(String url, String jsonStr, JJCallBack cb) {
OkGo.<String>post(url).headers(headers).upJson(jsonStr).execute(new AbsCallback<String>() {
@Override
public String convertResponse(okhttp3.Response response) throws Throwable {
String result = "";
if(null != response.body()){
if (null != response.body()) {
result = response.body().string();
}
return result;
@ -361,11 +414,17 @@ public class JfClient {
public void onSuccess(Response<String> response) {
cb.onSuccess(response.body());
}
@Override
public void onError(Response<String> response) {
cb.onSuccess("");
}
});
}
/**
* Json字符串转Gson对象
*
* @param jsonStr
* @param tClass
* @param <T>
@ -384,19 +443,20 @@ public class JfClient {
/**
* 按key获取JsonElement
*
* @param obj
* @param key
* @return
*/
public static JsonElement jeFromGson(JsonObject obj,String key){
JsonElement je = new Gson().fromJson("",JsonElement.class);
if(obj.has(key)){
je = obj.get(key);
public static JsonElement jeFromGson(JsonObject obj, String key) {
JsonElement jo = null;
if (obj != null && obj.has(key)) {
jo = obj.get(key).getAsJsonObject();
}
return je;
return jo;
}
public class JJCallBack implements JCallBack{
public static class JJCallBack implements JCallBack {
@Override
public void onSuccess(String str) {
@ -419,10 +479,13 @@ public class JfClient {
}
}
public interface JCallBack{
public interface JCallBack {
void onSuccess(String str);
void onSuccess(Boolean bool);
void onSuccess(JsonObject jsonObject);
void onSuccess(JsonArray jsonArray);
}
}

View File

@ -3,43 +3,48 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/padding_border" >
android:padding="@dimen/padding_border"
android:paddingTop="0dp">
<EditText
android:id="@+id/dialog_login_url"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="@dimen/dialog_text_height"
android:inputType="text"
android:lines="1"
android:nextFocusDown="@id/dialog_login_un"
android:hint="服务器地址"/>
<EditText
android:id="@+id/dialog_login_un"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="@dimen/dialog_text_height"
android:inputType="text"
android:lines="1"
android:nextFocusDown="@id/dialog_login_pw"
android:hint="用户名"/>
<EditText
android:id="@+id/dialog_login_pw"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="@dimen/dialog_text_height"
android:inputType="text"
android:lines="1"
android:nextFocusDown="@id/dialog_login_save"
android:hint="密码"/>
<CheckBox
android:id="@+id/dialog_login_save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/dialog_text_height"
android:focusable="true"
android:background="@drawable/shape_user_focus"
android:nextFocusDown="@id/dialog_login_submit"
android:text="保存用户" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="@dimen/dialog_text_height"
android:orientation="horizontal">
<TextView

View File

@ -24,6 +24,8 @@
<dimen name="drawable_padding_s">6dp</dimen>
<dimen name="drawable_padding_b">12dp</dimen>
<!-- 登录框 -->
<dimen name="dialog_text_height">48dp</dimen>
<!-- 播放控制器 -->
<dimen name="time_text_size">26dp</dimen>